目录
前言
STM32F4开发板拥有全双工I2S(也就是可以同时双向进行传输,A到B传输信息的同时B也可以向A进行信息传输),并且开发板外扩了一颗HIFI级CODEC芯片:WM8978G,支持最高192K 24BIT的音频播放,并且支持录音。STM32F4开发板的音乐播放器仅支持WAV播放。
1. WAV简介
WAV文件是计算机领域最常用的数字化声音文件格式之一,它是微软专门为Windows系统定义的波形文件格式(Waveform Audio),由于其扩展名为 “*. wav” 。wave文件有很多不同的压缩格式,现在一些程序生成的wave文件都或多或少的含有一些错误,这些错误很大程度是因为在压缩和解压缩后没有正确地组织好文件的内部结构。最基本的WAVE文件是PCM(脉冲编码调制)格式的,这种文件直接存储采样的声音数据没有经过任何的压缩,是声卡直接支持的数据格式,要让声卡正确播放其它被压缩的声音数据,就应该先把压缩的数据解压缩成PCM格式,然后再让声卡来播放。
1.1 WAVE文件的内部结构
WAVE文件是以RIFF(Resource Interchange File Format,资源交互文件格式)格式来组织内部结构的。RIFF文件结构可以看作是树状结构,其基本构成是称为 “块(Chunk)”的单元,最顶端是一个 “RIFF块” ,下面的每个块由 “类型块标识”、“标志符”、“数据大小” 及 “数据” 等项所组成。

上面提及的 “类型块标识” 只在部分chunk中用到,如 “WAVE chunk” 中,它表示的意义是下面嵌套有别的chunk,当使用了 “类型块标识” 时,该chunk中就没有别的项(如块标志等,数据大小等),它只作为文件读取时的一个标识(类似于链表中的指针域,指向下一个数据域,起一个导向的作用)。先找到这个 “类型块标识”,再以它为起点读取它下面嵌套的其他chunk。
//Chunk结构示意图:
WAV是由若干个Chunk组成的。按照在文件中出现的位置包括:RIFF WAVE Chunk、Format Chunk、Fact Chunk(可选)、Data Chunk。每个Chunk由块标识符、数据大小和数据三部分组成,
其中块标识符由4个ASCII码构成,数据大小则标出紧跟其后的数据的长度(单位为字节),注意这个长度不包含块标识符和数据大小的长度,即不包含最前面的8个字节(这8个字节是块标识符和数据大小总共的字节数)。所以实际 Chunk 的大小为数据大小加8。(也就是说一个Chunk是刚开始是块标识符,占4个字节;紧接着是数据大小,占4个字节;最后才是真正意义上的数据。)
首先,先来看 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 减8 是因为整个数据是放在块标志符和数据大小之后的,块标志符和数据大小各占4个字节 u32 Format; //格式;WAVE,即0x45564157 }ChunkRIFF;Format 块(Format Chunk),该块以 “fmt ”作为标示(注意有个空格!),一般情况下,该段的大小为16个字节,但是有些软件生成的wav格式,该部分可能有18个字节,含有两个字节的附加信息。Format 块的 Chunk 结构如下:
//fmt块 (Format块的Chunk 结构) typedef__packed struct { u32 ChunkID; //chunk id;这里固定为 “fmt ” ,即0x20746D66 u32 ChunkSize; //子集合大小(不包括 ID 和 Size);这里为:20 u16 AudioFormat; //音频格式;0x10,表示线性PCM;0x11,表示 IMA ADPCM u16 NumOfChannels; //通道数量;1,表示单声道;2,表示双声道 u32 SampleRate; //采样率;0x1F40,表示8Khz u32 ByteRate; //字节速率=采样率*通道数*(ADC位数/8) u16 BlockAlign; //块对齐(字节)=通道数*(ADC位数/8) u16 BitsPerSample; //单个采样数据大小;16位 ADPCM,设置为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);文件大小-60 }ChunkDATA;ChunkSize 后紧接着就是 wav 数据。根据Format Chunk中的声道数以及采样 bit 数,wav数据的 bit 位置可以分为如下几种形式:
本章,我们播放的音频支持:16位和24位,立体声,所以每个取样为 4/6 个字节,低字节在前,高字节在后。在得到这些 wav数据 以后,通过 I2S 丢给WM8978,就可以欣赏音乐啦。
只要依循此结构的文件,我们称之为RIFF档。此种结构提供了一种系统化的分类。如果和 MS、DOS 文件系统作比较,"RIFF"chunk 就好比是一台硬盘的根目录,其格式辨别码 便是此硬盘的逻辑代码(C:或 D:),而"L1ST"chunk 即为其下的子目录,其他的 chunk 则为一 般的文件。至于在 RIFF 文件的处理方面,微软提供了相关的函数。视窗下的各种多媒体文件 格式就如同在磁盘机下规定仅能放怎样的目录,而在该目录下仅能放何种数据。
每个文件最前端写入的是RIFF块,每个文件只有一个RIFF块。

非PCM格式的文件会至少多加入一个 “fact”块,它用来记录数据解压缩后的大小。这个 “fact” 块一般加在 “data” 块的前面。
WAVE文件是非常简单的一种RIFF文件,它的格式类型为 “WAVE”。RIFF块 包含两个子块,这两个子块的ID分别为 “fmt” 和 “data” ,其中 “fmt” 子块由结构 PCMWAVEFORMAT 所组成 ,其子块的大小就是 sizeof(PCMWAVEFORMAT),数据组成就是 PCMWAVEFORMAT 结构中的数据。

// PCMWAVEFORMAT 结构定义如下:
Typedef struct
{
WAVEFORMAT wf; //波形格式
WORD wBitsPerSample; //WAVE文件的采样大小
}PCMWAVEFORMAT;
//WAVEFORMAT结构定义如下:
typedef struct
{
WORD wFormatag; //编码格式,包括WAVE_FORMAT_PCM,WAVEFORMAT_ADPCM等
WORD nChannls; //声道数,单声道为1,双声道为2;
DWORD nSamplesPerSec; //采样频率
DWORD nAvgBytesperSec; //每秒的数据量
WORD nBlockAlign; //块对齐
}WAVEFORMAT;
“data” 子块 包含 WAVE 文件的数字化波形声音数据,其存放格式依赖于 “fmt” 子块中wFormatTag 成员指定的格式种类,在多声道WAVE文件中,样本是交替出现的。

2. WM8978简介
WM8978 是一个低功耗、高质量的立体声多媒体数字信号编译码器。是欧胜(Wolfson)推出的一款全功能音频处理器。它带有一个 HI-FI 级数字信号处理内核,支持增强 3D 硬件环绕音效,以及 5 频段的硬件均衡器,可以有效改善音质;并有一个可编程的陷波滤波器,用以去除屏幕开、切换等噪音。
WM8978 集成了对麦克风的支持,用于一个强悍的扬声器功放,可提供高达 900mW 的高质量音响效果扬声器功率。
WM8978 拥有一个数字回放限制器,可防止扬声器声音过载。进一步提升了耳机放大器输出功率,在推动 16Ω 耳机的时候,每声道最大输出功率高达 40毫瓦 !可以连接市面上绝大多数适合随身听的高端 HI-FI 耳机。
WM8978的主要特性有:
- I2S接口,支持最高192K,24bit 音频播放
- DAC信噪比98dB;ADC信噪比90dB
- 支持无电容耳机驱动(提供40mW 16Ω 的输出能力)
- 支持扬声器输出(提供 0.9W@8Ω 的驱动能力)
- 支持立体声差分输入/麦克风输入
- 支持左右声道音量独立调节
- 支持 3D 效果,支持 5 路 EQ 调节
WM8978的控制通过 I2S 接口(即数字音频接口)同 MCU 进行音频数据传输(支持音频接收和发送),通过两线(MODE=0,即 IIC 接口)或三线(MODE=1)接口进行配置。WM8978的 I2S 接口,由4个引脚组成:
- ADCDAT:ADC数据输出
- DACDAT:DAC数据输入
- LRC:数据左 / 右对齐时钟
- BCLK:位时钟,用于同步
WM8978可作为 I2S 主机,输出 LRC 和 BLCK 时钟,不过我们一般使用 WM8978 作为从机,接收LRC 和 BLCK 时钟。另外,WM8978的 I2S 接口支持 5 种不同的音频数据模式:左(MSB)对齐标准、右(LSB)对齐标准、飞利浦(I2S)标准(本节我们使用飞利浦标准来传输I2S数据)、DSP模式 A 和DSP模式 B。
飞利浦(I2S)标准模式,数据在跟随 LRC 传输的 BCLK 的第二个上升沿时传输MSB,其他位一直到LSB按顺序传输。传输依赖于字长、BCLK频率和采样率,在每个采样的 LSB 和下一个 MSB 之间都应该有未用的 BCLK 周期。飞利浦标准模式的 I2S 数据传输协议如下:

fs 表示音频信号的采样率;LRC的频率就是音频信号的采样率。另外,S

本文围绕STM32F4开发板的音乐播放实验展开。介绍了WAV文件结构、WM8978音频处理器、I2S总线标准。阐述了硬件设计,如开机检测字库、循环播放SD卡音乐等功能。还给出实验程序,包括main.c、I2S.c等文件,说明了通过I2S驱动WM8978播放音乐的步骤。


最低0.47元/天 解锁文章
675

被折叠的 条评论
为什么被折叠?



