G723音频格式读入内存
·
音频是用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);
// 写出帧信息
}
直接把头信息和帧信息一起写出即可。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)