WAV即WAVE文件,是最常用的数字化声音文件格式之一,其扩展名为“.wav”。符合RIFF(Resource Interchange File Format)文件规范,用于保存Windows平台的音频信息资源,被Windows平台及其应用程序所广泛支持。 WAV格式还支持MS ADPCM,CCITT A LAW等多种压缩运算法,支持多种音频数字,取样频率和声道。标准格式化的WAV文件和CD格式一样,也是44.1K的取样频率,16位量化数字,因此在声音文件质量和CD相差无几!
WAV组成
WAV是由若干个Chunk组成的。按照在文件中的出现位置包括:①RIFF WAVE Chunk、② Format Chunk、 ③Fact Chunk(可选)和④Data Chunk。每个Chunk由块标识符、数据大小和数据三部分组成,如下图所示:
其中块标识符由4个ASCII码构成,数据大小则标出紧跟其后的数据的长度(单位为字节),注意这个长度不包含块标识符和数据大小的长度,即不包含最前面的8个字节。所以实际Chunk的大小为数据大小加8。
①RIFF块(RIFF WAVE Chunk),该块以“RIFF”作为标示,紧跟wav文件大小(该大小是wav文件的总大小-8),然后数据段为“WAVE”,表示是wav文件。RIFF块的Chunk结构如下:
//RIFF块
typedef __packed struct
{
u32 ChunkID; //chunk id;这里固定为"RIFF",即0X46464952
u32 ChunkSize ; //集合大小;文件总大小-8
u32 Format; //格式;WAVE,即0X45564157
}ChunkRIFF ;
②Format块(Format Chunk),该块以“fmt ”作为标示(注意有个空格!),一般情况下,该段的大小为16个字节,但是有些软件生成的wav格式,该部分可能有18个字节,含有2个字节的附加信息。Format块的Chunk结构如下:
//fmt块
typedef __packed struct
{
u32 ChunkID; //chunk id;这里固定为"fmt ",即0X20746D66
u32 ChunkSize ; //子集合大小(不包括ID和Size);
u16 AudioFormat; //音频格式;一般为0X0001,表示线性PCM;
u16 NumOfChannels; //通道数量;1,表示单声道;2,表示双声道;
u32 SampleRate; //采样率;0X1F40,表示8Khz
u32 ByteRate; //字节速率=采样率*通道数*(ADC位数/8)
u16 BlockAlign; //块对齐(字节)=通道数*(ADC位数/8)
u16 BitsPerSample; //单个采样的位数;16位PCM,设置为16
u16 ByteExtraData; //附加的数据字节;2个; 线性PCM,没有这个参数(可有可无)
}ChunkFMT;
③Fact块(Fact Chunk),该块为可选块,以“fact”作为标示,不是每个WAV文件都有,在非PCM格式的文件中,一般会在Format结构后面加入一个Fact块,该块Chunk结构如下:
//fact块
typedef __packed struct
{
u32 ChunkID; //chunk id;这里固定为"fact",即0X74636166;
u32 ChunkSize ; //子集合大小(不包括ID和Size);这里为:4.
u32 DataFactSize; //数据转换为PCM格式后的大小
}ChunkFACT;
DataFactSize是这个Chunk中最重要的数据,如果这是某种压缩格式的声音文件,那么从这里就可以知道他解压缩后的大小。对于解压时的计算会有很大的好处!
④数据块(Data Chunk),该块是真正保存wav数据的地方,以“data”'作为该Chunk的标示,然后是数据的大小。数据块的Chunk结构如下:
//data块
typedef __packed struct
{
u32 ChunkID; //chunk id;这里固定为"data",即0X61746164
u32 ChunkSize ; //子集合大小(不包括ID和Size);
}ChunkDATA;
ChunkSize的大小就是音频数据的大小(仅指音频数据大小,不包括Chunk ID之类的数据),在ChunkSize之后,紧跟音频数据。
WAV数据说明
根据Format Chunk中的声道数以及采样bit数,wav数据的bit位置可以分成如下表所示的几种形式:
在得到这些wav数据以后,通过I2S送给WM8978,即可欣赏音乐了。
WM8978简介
WM8978是欧胜(Wolfson)推出的一款全功能音频处理器。它带有HI-FI级数字信号处理内核,支持增强3D硬件环绕音效,和5频段的硬件均衡器,可以有效改善音质。
同时集成了对麦克风的支持,和一个输出功率达0.9W的高质量功放。
WM8978进一步提升了耳机放大器输出功率,在推动16欧姆耳机的时候,每声道最大输出功率高达40毫瓦!可以连接市面上绝大多数适合随身听的高端HI-FI耳机。
WM8978特点
●I2S接口,支持最高192K,24bit音频播放
●DAC信噪比98dB;ADC信噪比90dB
●支持无电容耳机驱动(提供40mW@16Ω的输出能力)
●支持扬声器输出(提供0.9W@8Ω的驱动能力)
●支持立体声差分输入/麦克风输入
●支持左右声道音量独立调节
●支持3D效果,支持5路EQ调节
WM8978接口
WM8978通过I2S接口(即数字音频接口)同MCU进行音频数据传输(支持音频接收和发送),通过两线(MODE=0,即IIC接口)或三线(MODE=1)接口进行配置。WM8978的I2S接口,由4个引脚组成:
1,ADCDAT: ADC数据输出
2,DACDAT:DAC数据输入
3,LRC:数据左/右对齐时钟
4,BCLK:位时钟,用于同步
WM8978的I2S接口支持多种不同的音频数据模式:左(MSB)对齐标准、右(LSB)对齐标准、飞利浦(I2S)标准等,本例程,我们采用飞利浦标准。
飞利浦(I2S)标准模式,数据在跟随LRC传输的BCLK的第二个上升沿时传输MSB,其他位一直到LSB按顺序传输。传输依赖于字长、BCLK频率和采样率,在每个采样的LSB和下一个采样的MSB之间都应该有未用的BCLK周期。飞利浦标准I2S数据传输协议如下图所示:
图中,fs即音频信号的采样率,比如44.1Khz,因此:LRC的频率就是音频信号的采样率。另外,WM8978还需要一个MCLK,本例程由STM32F4为其提供MCLK时钟,MCLK的频率必须等于256fs,也就是音频采样率的256倍。
WM8978内部有很多的模拟开关,用来选择通道,同时还有很多调节器,用来设置增益和音量。
相关寄存器
R0寄存器(00h)
该寄存器用于控制WM8978的软复位,写任意值到该寄存器地址,即可实现软复位WM8978。注意:WM8978的寄存器是9位的!而且是不可读的,只可以写,不可读!
R1寄存器(01h)
第3位设置为1,模拟部分的放大器才会工作,才可以听到声音。其他位都为默认的0。
R2寄存器(02h)
该寄存器设置ROUT1EN(bit8),LOUT1EN(bit7)和SLEEP(bit6)等三个位,ROUT1EN和LOUT1EN,设置为1,使能耳机输出,SLEEP设置为0,进入正常工作模式。
R3寄存器(03h)
该寄存器设置LOUT2EN(bit6),ROUT2EN(bit5),RMIXER(bit3),LMIXER(bit2),DACENR(bit1)和DACENL(bit0)等6个位。LOUT2EN和ROUT2EN,设置为1,使能喇叭输出;LMIXER和RMIXER设置为1,使能左右声道混合器;DACENL和DACENR则是使能左右声道的DAC了,必须设置为1。
R4寄存器(04h)
该寄存器要设置WL(bit6:5)和FMT(bit4:3)等4个位。WL(bit6:5)用于设置字长(即设置音频数据有效位数),00表示16位音频,10表示24位音频;FMT(bit4:3)用于设置I2S音频数据格式(模式),我们一般设置为10,表示I2S格式,即飞利浦模式。
R6寄存器(06h)
该寄存器直接全部设置为0即可,设置MCLK和BCLK都来自外部,即由STM32F4提供
R10寄存器(0Ah)
该寄存器我们要设置SOFTMUTE(bit6)和DACOSR128(bit3)等两个位,SOFTMUTE设置为0,关闭软件静音;DACOSR128设置为1,DAC得到最好的SNR(信噪比),设置为0是低功耗。
R49寄存器(31h)
该寄存器要设置SPKBOOST(bit2)和TSDEN(bit1)这两个位。SPKBOOST用于设置喇叭的增益,设置为0即可(gain=-1),如想获得更大的声音,可设置为1(gain=+1.5)即;TSDEN用于设置过热保护,设置为1(开启)即可,如果不开启则可能因为功率过大把芯片烧毁。
R50&R51寄存器(32h&33h)
上图为R50寄存器描述,用于设置左声道,另外一个用于设置右声道(R51)。只需要设置这两个寄存器的最低位为1即可,将左右声道的DAC输出接入左右声道混合器里面,才能在耳机/喇叭听到音乐。
R52&R53寄存器(34h&35h)
上图为R52寄存器描述,用于设置耳机输出左声道(R52),另一个用于设置耳机输出右声道(R53)。这两个寄存器的最高位(HPVU)用于设置是否更新左右声道的音量,最低6位用于设置左右声道的音量,我们可以先设置好两个寄存器的音量值,最后设置其中一个寄存器最高位为1,即可同时更新左右音量设置。
R54&R55寄存器(36h&37h)
这两个寄存器用于设置喇叭音量,同R52,R53设置一模一样。