一. 前言
本文分享基于【富芮坤FR3068x-C】开发板实现基于micrpython的本地音频播放器。完全按照产品化的项目进行,考虑可测试可调式可移植可维护性,完成一个完整的项目。
代码见:https://gitee.com/qinyunti/fr3068-e-c-micropython.git
视频见:
【【富芮坤FR3068x-C】基于REPL MicroPython实现本地音乐播放】 https://www.bilibili.com/video/BV1aPCMYsEyf/?share_source=copy_web&vd_source=30f88a61ba48d80acfe41f622b10a844
二. 前期技术准备
详见网站文章
file:///C:\Users\qinyunti\AppData\Local\Temp\ksohtml22964\wps15.jpg
file:///C:\Users\qinyunti\AppData\Local\Temp\ksohtml22964\wps16.jpg
框图如下
包括实现基于fifo的uart驱动给micropython,shell,文件传输等提供好用高效的串口读写接口。
Shell的实现,实现了大量的测试调试命令集,文件操作命令集,音频播放命令集等,
Micropython基于mdk的移植,实现pyb模块,LED和AUDIO设备等
SPI的驱动测试BUG修改,FLASH读写驱动重写,FATFS适配测试调试。
DAC驱动调试包括示波器测试波形等,DAC的ping-pong发送驱动,基于FIFO状态机机的播放调度,消息队列和其他任务交互。
以及基础组件,FIFO实现,X.YMODEM实现,WAV解析,MD5计算等。
file:///C:\Users\qinyunti\AppData\Local\Temp\ksohtml22964\wps17.jpg
三. 音频播放设计
3.1 Wav格式解析
见微信公众号文章
基于DWC2的USB驱动开发-UAC之WAV-PCM音频文件格式详解
解析代码见代码wav_decode.c/h
3.2 架构设计
ping-pong发送架构
启动时先填满硬件FIFO,在硬件FIFO半满时产生中断,中断回调中填入新的一半数据。
file:///C:\Users\qinyunti\AppData\Local\Temp\ksohtml22964\wps18.jpg
FIFO流实现
上述DAC半满中断中,需要获取新的待发送数据写入硬件FIFO,这个操作必须快速,所以这里不能直接去读音频文件,而是通过一层软件FIFO来实现。
任务中读音频文件,写入软件FIFO,中断中从软件FIFO中取数写入硬件FIFO。
file:///C:\Users\qinyunti\AppData\Local\Temp\ksohtml22964\wps19.jpg
处理状态机
为了方便管理音频的播放,启停,音频播放任务按照状态机设置,
通过消息队列往该任务发送控制。
默认进入空闲状态,收到play消息,进入play状态,读取文件,写入软件FIFO。
播放完或者收到stop消息停止,进入空闲状态。
file:///C:\Users\qinyunti\AppData\Local\Temp\ksohtml22964\wps20.jpg
断流问题
参考公众号文章第四小节介绍
es8388音频芯片驱动之六:ES8388+UAC的录音播放实例分享
即半满中断回调从软件FIFO取数,以及任务往软件FIFO写数,之前可能存在临界状态。比如前者可能时间是
999uS,1ms后者可能是
1.1ms, 999us
那么可能存在前一次取数时间间隔小于写入使劲间隔,导致本次取数失败断流,这是因为两者平均速度有微小偏差导致,这个偏差抖动会导致经常性的断流。
解决办法是,先让软件FIFO中有多笔数据时,才开始取数,这样之后每次都能取到数,因为这个小的波动被FIFO中积蓄的数据消除掉。
3.3 音频驱动
详见网站上文章,这里不再介绍,可以先输出正弦波等进行测试,确保输出正确。
四. Shell下音频播放测试
详见视频演示
准备wav文件
下载MP3测试文件,我这里假设是leiqiao.mp3。
下载ffmpeg。
在当前文件夹下,命令行下运行命令:
ffmpeg/ffmpeg.exe -i leiqiao.mp3 -ac 1 -ar 16000 -acodec pcm_s16le -ss 00:00:05 -t 00:00:30 leiqiao.wav
其中-i后面为输入文件
-ac后面1表示输出1通道
-ar后面16000表示采样率16k
-acodec表示数据格式pcm_s16le表示 pcm有符号16位小端
-ss表示截取开始时间
-t表示截取时间长度
16k.wav是输出文件名。
这里有三个测试文件放在了源码目录下
file:///C:\Users\qinyunti\AppData\Local\Temp\ksohtml22964\wps21.jpg
导入文件
通过xmodem导入wav文件到开发板
file:///C:\Users\qinyunti\AppData\Local\Temp\ksohtml22964\wps22.jpg
file:///C:\Users\qinyunti\AppData\Local\Temp\ksohtml22964\wps23.jpg
启动播放
file:///C:\Users\qinyunti\AppData\Local\Temp\ksohtml22964\wps24.jpg
dacplay 文件名
停止播放
dacstop
静音控制
dacvolume 音量
音量设置
dacpa 0/1
五.绑定microplay 音频播放模块
py\genhdr\moduledefs.h中之前LED示例中已经注册模块pyb_module,
我们在
Src\py_port\modpyb.c中
pyb_module_globals_table下添加
{ MP_ROM_QSTR(MP_QSTR_AUDIO), MP_ROM_PTR(&pyb_audio_type) },
即注册pyb下的audio。
file:///C:\Users\qinyunti\AppData\Local\Temp\ksohtml22964\wps25.jpg
实现代码见audio.c和audio.h
audio.c中实现
主要绑定实现以下接口,mute,volume,play,stop
file:///C:\Users\qinyunti\AppData\Local\Temp\ksohtml22964\wps26.jpg
六.Micropython下音频播放测试
详细效果见视频演示
Shell环境中输入micropython进入python环境,
import pyb
audio = pyb.AUDIO(1) 这里注意ID从1开始只有一个实例
开始播放audio.play("2:/leiqiao.wav")
提前结束播放audio.stop()
file:///C:\Users\qinyunti\AppData\Local\Temp\ksohtml22964\wps27.jpg
mute测试
audio.mute(1) 静音
audio.mute(0) 不静音
设置音量测试
audio.volume(1)可以听到声音变小
退出python环境 按组合按键ctrl+d
七. 总结
以上分享了基于【富芮坤FR3068x-C】开发板实现基于micrpython的本地音频播放器。
可见富芮坤FR3068x-C开发板资源丰富,性能不错,尤其针对音频解决方案集成度高,使用直接PWM-DAC输出播放音频效果也非常不错,从演示视频可以看到,播放效果非常好几乎无杂音,完全不需要外置音频芯片可以满足大部分应用,是低成本高集成度的解决方案。在音频应用领域可以优先考虑该方案。