前几天我对MS进行优化,解决一个时间戳跳变问题。将修改的代码提交后,经过现场测试结果发现双声道录音中有一个通道不正常。我记得这个功能让让同事修改了,在现场运行正常。目前他已经离职了,我打电话询问,他说不知道怎么回事。他平时脑子就不是特别清晰,我也懒得去追究了。然后我静下心分析,最后分析发现,这个离职的同事没有将该修改的代码提交入库。考虑他平时就有些悟性差,我就当做是无心之举了。经过我细心分析,发现了问题BUG,调整后,录音及通话均正常了。闲话少叙,下面我将16K 16BIT的双声道文件格式继续做个分享,希望对读者能有所帮助。

        一、文件头格式

         我用UE打开双声道的文件,进行举例说明。

       1)开头4个字节 0~3 固定是RIFF

         

16K 16BIT双声道文件格式解析_WAV

   2)4~7字节是长度

16K 16BIT双声道文件格式解析_语音_02

这个长度是其后所有字节数的总和。这4个字节填充时,低位字节在前,高位字节在后。

3)8~15字节是WAVEfmt 。

这8个字节是WAVEfmt ,请注意t后面有个空格。

16K 16BIT双声道文件格式解析_人工智能_03

4)16~19是fmtsize,固定是16

     

16K 16BIT双声道文件格式解析_语音_04

固定是16,低位字节在前,高位字节在后。

5)20~21 固定是01

16K 16BIT双声道文件格式解析_WAV_05

 固定是1,低位字节在前,高位字节在后。1表示PCM语音格式。语音格式表如下:

16K 16BIT双声道文件格式解析_WAV_06

6)22~23 声道数2

16K 16BIT双声道文件格式解析_语音识别_07

声道数2,低字节在前。

7)24~27 单个通道采样率16000

16K 16BIT双声道文件格式解析_录音_08

单个通道采样率16000,低字节在前。

8)28~31 两个声道每秒记录的数据长度64000

16K 16BIT双声道文件格式解析_语音识别_09

 每秒记录的数据长度为=采样率*声道数*位长/8,16000*2*16/2=64000。低位字节在前。

9)32~33 块对齐 4

16K 16BIT双声道文件格式解析_录音_10

这个是块对齐,告知播放软件一次性需处理多少字节。公式为: BitsPerSample*FmtChannels/8。

10)34~35 采样位数 16

16K 16BIT双声道文件格式解析_语音_11

这个是采样位数,标题中16BIT指的就是它。

11)36~39 固定是data

16K 16BIT双声道文件格式解析_语音_12

固定为data

 12)40~43 是真实语音的长度。

16K 16BIT双声道文件格式解析_录音_13

这个长度和前面那个长度不一样的是前面的长度比它多了36个字节头。这个长度就是真实语音的长度。

    二、文件体格式

前面的文件头一共是44个字节,它告诉了播放器播放的参数。那么双声道的语音中,左右声道的语音语句是如何存储的呢。

算法是左声道一次采样+右声道一次采样。声道一次采样是16BIT,也就是两个字节。所以一次采样存储4个字节,前面两个字节存左声道,后面两个字节存右声道。

 我将部分代码贴一下,仅供参考。

 

int i = 0;
//int j = 0;
//int k = 0;
//int state = 0;
char twoChannelBuffer[MAXAUDIOBUFFERSIZE] ;
memset(twoChannelBuffer,0,MAXAUDIOBUFFERSIZE);

// for ( i = 0, j = 0 ; i != 640; i++ )
for ( i = 0; i <320; i++)
{
twoChannelBuffer[4*i] = buffer1[i*2];
twoChannelBuffer[4*i+1] = buffer1[i*2+1];
twoChannelBuffer[4*i+2] = buffer2[i*2];
twoChannelBuffer[4*i+3] = buffer2[i*2+1];
}
m_mediaFile->putAudioData(twoChannelBuffer, i*4 );

这样的算法,我一次保存的字节是1280个字节。之所以这样计算是因为我的MS,每20ms循环一次,一秒钟循环50次。那么我的一秒的16000次采样,分到20毫秒中,每次320个采样。每个采样是16BIT,也就是2个字节。那么我的一个声道的一次采样就是640个字节。两个声道的采样就是1280个字节。

总结:

以上是我的实战经验,仅供参考,谢谢阅读。