stm32 mp3软件音频解码案例分析流程(一)

最近做了一个无人机的语音播放项目,查了一下网上大部分都是硬件解码,成本相对比较高,而为了节约成本,
我们采用了stm32f446 RET6作为主控+tas5720作为dac功放,实现mp3软件音频解码实现语音播报功能。
采用成熟的Helix音频解码库,该库比市面上的Libmad 解码库更适用在小型嵌入式控制器移植。将该算法移植到STM32 控制器运行使用定点
计算实现,它支持MPEG-1、MPEG-2 以及MPEG-2.5 标准的Layer3 解码。Helix 解码库支持可变位速率、恒定位速率,以及立体声和单声道音频格式。

功能实际上就是从usart读取mp3 格式数据流,
然后提取里边音频数据通过I2S 传输到tas5720芯片内实现声音播放。
源码在我的博客中会进行公开。
直接上干货,讲解mp3解码库运行流程:
一、MP3InitDecoder:初始化解码器函数
代码函数调用为Mp3Decoder = MP3InitDecoder();
它会申请分配一个存储空间用于存放解码器状态的一个数据结构并将其初始化,该数据结构由MP3DecInfo 结构体定义,它封装了解码器内部运算数据信息。MP3InitDecoder 函数会返回指向该数据结构的指针。

二、MP3FreeDecoder:关闭解码器函数
代码函数中的调用为MP3FreeDecoder(Mp3Decoder);
当读取mp3码流失败时将调用该函数,释放由MP3InitDecoder 函数申请的存储空间,所以一个MP3InitDecoder 函数都需要有一个MP3FreeDecoder 函数与之对应。它有一个形参,一般由MP3InitDecoder 函数的返回指针赋值。

三、MP3FindSyncWord:寻找帧同步函数
代码 函数中的调用为read_offset = MP3FindSyncWord(read_ptr, bytes_left);
实际上就是寻址数据帧开始的11bit 都为“1”的同步信息。它有两个形参,第一个为源数据缓冲区指针,第二个为缓冲区大小,它会返回一个int 类型变量,用于指示同步字较缓冲区起始地址的偏移量,如果在缓冲区中找不到同步字,则直接返回-1。

四、MP3Decode:解码MP3 帧函数

代码函数中调用为
err = MP3Decode(Mp3Decoder, &read_ptr, &bytes_left, outbuffer[bufflag], 0);
它有五个形参,
第一个为解码器数据结构指针,一般由MP3InitDecoder 函数返回值赋值;
第二个参数为指向解码源数据缓冲区开始地址的一个指针,注意这里是地址的指针,即是指针的指针;
第三个参数是一个指向存放解码源数据缓冲区有效数据量的变量指针;
第四个参数是解码后输出PCM数据的指针,一般由我们定义的缓冲区地址赋值,对于双声道输出数据缓冲区以LRLRLR…顺序排列;
第五个参数是数据格式选择,一般设置为0 表示标准的MPEG 格式。函数还有一个返回值,用于返回解码错误,返回ERR_MP3_NONE 说明解码正常。
此函数内部通过汇编实现了pcm码流的转化过程,想深入了解的可以反汇编进入追踪观察。

五、MP3GetLastFrameInfo:获取帧信息函数
代码中函数调用为:Mp3FrameInfo.samprate != mp3player.ucFreq
printf(" \r\n Bitrate %dKbps", Mp3FrameInfo.bitrate/1000);
printf(" \r\n Samprate %dHz", mp3player.ucFreq);
printf(" \r\n BitsPerSample %db", Mp3FrameInfo.bitsPerSample);
printf(" \r\n nChans %d", Mp3FrameInfo.nChans);
printf(" \r\n Layer %d", Mp3FrameInfo.layer);
printf(" \r\n Version %d", Mp3FrameInfo.version);
printf(" \r\n OutputSamps %d", Mp3FrameInfo.outputSamps);
它有两个形参,第一个为解码器数据结构指针,一般由MP3InitDecoder 函数返回值赋值;第二个参数为数据帧信息结构体指针。
这个函数可以解析出mp3的帧头格式,即波特率、采样率、位率、通道数、协议、版本、以及输出的pcm个数。
了解清楚了解码库的接口以及运行流程,下篇讲解代码的运行流程。

上一篇:python-通过eyeD3更改MP3文件中的歌词


下一篇:如何在C#/.NET / DirectX中检索mp3音频文件的正确持续时间?