音频是用ffmpeg转的,然后用c++把文件从磁盘读到内存
按帧存储,每一帧有24字节(192比特)
文件头和码流部分是分开的
我并不确定每个文件头都一样

文件头和帧定义
struct WaveFileHead
{
	char   riff_id[4];     //"RIFF"
	int    size0;          //波形块的大小
	char   wave_fmt[8];    //"wave" and "fmt "
	// 二合一
	int    size1;          //格式块的大小
	short  fmttag;         //波形编码格式
	short  channel;        //波形文件数据中的通道数
	int    sampl;          //波形文件的采样率
	int    bytepersecblockalign;  //平均每秒波形音频所需要的记录的字节数
	short  blockalign;      //一个采样所需要的字节数
	short  bitpersamples;   //声音文件数据的每个采样的位数
	char	notKnow[24];	// 不知道是什么
	char	list[4];		// LIST
	int		nothinSize;
	char	otherThing[26];	// 对应着上个参数的大小 放一些没啥用的东西
	char   data[4];         //"data"
	short int    datasize;      //数据块大小
};


struct Frame {
	bitset<192> content;
};

文件头最后本应该有一个数据块大小,也就是data是4字节,datasize也是4字节,但是不知道为什么拆开读数据会有错误,我想有可能是上面的26字节数据块的对齐有问题,暂时未知,没有去研究,因为我并不需要修改文件头。
所以上面这个bug后来让我花了半个下午的时间去check,本来我需要的长度是102,但是sizeof出来时104…所以直接限定长度即可。
Frame 是一帧的定义,下面会开一个数组用来存body。

读入723文件
	ifstream f;
	WaveFileHead wavehead;
	int FrameCnt = 0;
	Frame *a = new Frame[99999];
	int size_wav = 102;
	G723(string s) {
		f.open(s, ios::binary);
		f.read((char *)&wavehead, size_wav);
		while (f) {
			f.read((char *)&a[FrameCnt++], sizeof( Frame)); // 每次读一帧
		}
	}// 读入一个723文件 获取头信息和帧信息

两段代码合在一起,加上头文件和命名空间即可。
需要注意bitset的用法,是从低位存储到高位,
也就是说 x = 12 的二进制是 1100,那么
x[0] = 0,
x[1] = 0,
x[2] = 1,
x[3] = 1

这个也是个坑爹的地方,这就意味着和码元表对应的数据不一样。
不过物理存储倒是没什么问题,读写需要加一个映射关系。

723文件写出
	void WriteFile(string path) {
		ofstream out(path, ios::binary);
		out.write((char *)&wavehead, size_wav);
		// 写出头信息
		out.write((char *)a, sizeof( Frame) * FrameCnt);
		// 写出帧信息
	}

直接把头信息和帧信息一起写出即可。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐