首頁 > 評測 > 基于靈動MM32F5270開發(fā)板播放MP3和WAV音頻文件
基于靈動MM32F5270開發(fā)板播放MP3和WAV音頻文件
- [導讀]
- 本帖最后由 春嬌霹靂娃 于 2023-6-16 14:47 編輯 #申請原創(chuàng)# @21小跑堂 一、I2S簡介 I2S(Inter-IC Sound)總線為集成在芯片內的音頻總線,是飛利浦公司為數(shù)字音頻設備之間的音頻數(shù)據傳輸而制定的一種總
本帖最后由 春嬌霹靂娃 于 2023-6-16 14:47 編輯
#申請原創(chuàng)# @21小跑堂
一、I2S簡介
I2S(Inter-IC Sound)總線為集成在芯片內的音頻總線,是飛利浦公司為數(shù)字音頻設備之間的音頻數(shù)據傳輸而制定的一種總線標準。
MM32F5270系列MCU最多支持3個I2S接口,支持半雙工通信和全雙工通信,數(shù)據幀格式可配置為 16 位、24 位或 32 位。數(shù)據傳輸方向始終是MSB優(yōu)先,且每個I2S接口都支持DMA傳輸方式。MM32F5270系列的I2S支持飛利浦標準、MSB向左對齊標準、LSB向右對齊標準和PCM標準四種。
MM32F5270 是一款搭載了安謀科技 Arm China STAR-MC1 內核的 MCU 產品,其工作頻率可達 120MHz,內置多達 256KB Flash 和 192KB RAM。MM32F5270 相較于現(xiàn)有產品全面提升了性能、存儲容量、總線架構和外設配置,旨在覆蓋更廣泛的工業(yè)、汽車和 IoT 應用。
二、本文實現(xiàn)音頻播放的設計框架
本實驗搭載在 PLUS-F5270 開發(fā)板,通過 SDSPI 組件實現(xiàn) FatFs 移植讀取音頻文件,分為 WAV 格式音頻文件解碼和 MP3 格式音頻文件通過 libmad 解碼。組件包含SDSPI、FatFS 和 Libmad 三部分組成,整個設計框圖如下圖:
三、實驗環(huán)境
1.硬件環(huán)境:MM32F5277E9P開發(fā)板,SD卡及讀卡器
I2S 部分電路原理圖:
2.軟件環(huán)境:KEIL軟件,Tera Term 終端軟件,酷狗音樂
本實驗整個設計思路為:
1.通過 SDSPI 接口操作 SD 卡,移植 FatFs 文件系統(tǒng)對音頻文件進行識別,對音頻文件數(shù)據進行讀取操作;
2.通過 DMA 搬運的方式,將存儲在 SD 卡中的音頻文件(WAV 格式 / MP3 格式)通過 I2S 總線,將音頻數(shù)據發(fā)送給 CS4344 音頻數(shù)模轉換芯片,從而播放出音樂;
3.開啟 DMA 傳輸完成中斷和半傳輸完成中斷;
4.使用雙緩沖區(qū),實現(xiàn)流暢的音頻文件播放效果。
四、FatFS簡介
1.FatFs official website: http://elm-chan.org/fsw/ff/00index_e.html
FatFS 負責管理和存儲文件信息的軟件機構,是一種在磁盤上組織文件的方法。其優(yōu)點有:
2.移植FatFS
適配ffconf.h和diskio.c文件,使編譯通過。
FatFS常用的API如下圖:
五、WAV格式音頻文件
1.WAV是 Waveform 的簡寫,也叫波形文件,是一種可以存儲聲音波形的數(shù)字音頻格式。其具有真實記錄聲音波形的特點,基本無數(shù)據壓縮,數(shù)據體量相對較大。典型的WAV文件格式如下圖:
WAV 文件采用的是 RIFF 格式結構,至少由 RIFF 塊、fmt 塊和 data 塊組成。每個 RIFF 文件由若干個塊 (chunk) 組成,每個塊由塊標識、塊長度以及數(shù)據這三部分組成。塊標識由 4 個 ASCII 碼字符組成的,如果不滿 4 個字符則在右邊以空格來補齊。塊長度由 4 個字節(jié)存儲空間,保存的是當前塊數(shù)據的長度,但不包含塊標識和塊長度字段,所以一個塊的實際長度就是塊長度字段的數(shù)值再加上 8 字節(jié)。
WAV文件格式實例解析如下:
2.WAV文件解碼
- 結構體定義:wav_decode.h
- 結構解析:
- bool wav_decode_open(wav_decode_obj_t * obj, char * file_name, uint8_t * buf, uint32_t buf_size)
- bool wav_decode_read(wav_decode_obj_t * obj, uint16_t * buf, uint32_t buf_len)
- void wav_decode_close(wav_decode_obj_t * obj)
- 播放實現(xiàn):void app_wav_play(void)
wav_decode_open 打開FatFS 中音頻文件:
- <font face="Arial"><span style="background-color: black;"><font color="#fffacd">/* open fatfs file. */
- bool wav_decode_open(wav_decode_obj_t * obj,char * file_name, uint8_t * buf, uint32_t buf_size){
- UINT fatfs_br = 0u;
- uint8_t offset = 0u;
- if (FR_OK != f_open(&(obj->fatfs_file), file_name, FA_READ) ){
- return false;}
- obj->fatfs_buf = buf;
- obj->fatfs_buf_size = buf_size;
- if (FR_OK != f_read(&(obj->fatfs_file), obj->fatfs_buf, WAV_DECODE_HEAD_BUFFER_SIZE, &fatfs_br)){
- return false;}
- chunk_riff_def_t *chunk_riff;
- chunk_fmt_def_t *chunk_fmt;
- chunk_fact_def_t *chunk_fact;
- chunk_data_def_t *chunk_data;
- chunk_riff = (chunk_riff_def_t *)(obj->fatfs_buf);
- chunk_fmt = (chunk_fmt_def_t *)(obj->fatfs_buf + 12);
- chunk_fact = (chunk_fact_def_t *)(obj->fatfs_buf + 12 + 8 + chunk_fmt->sub_chunk1_size);
- if((chunk_fact->chunk_id == 0x74636166) || (chunk_fact->chunk_id == 0x5453494C)){
- chunk_data = (chunk_data_def_t *)(obj->fatfs_buf + 12 + 8 + chunk_fmt->sub_chunk1_size + 8 + chunk_fact->chunk_size);
- offset = 12 + 8 + chunk_fmt->sub_chunk1_size + 8 + chunk_fact->chunk_size;}
- else{
- chunk_data = (chunk_data_def_t *)(obj->fatfs_buf + 12 + 8 + chunk_fmt->sub_chunk1_size);
- offset = 12 + 8 + chunk_fmt->sub_chunk1_size;}
- if(chunk_riff->format == 0x45564157 && chunk_data->sub_chunk2_id == 0x61746164){
- obj->audio_format = chunk_fmt->audio_format;
- obj->channel = chunk_fmt->num_of_channels;
- obj->sample_rate = chunk_fmt->sample_rate;
- obj->bits_per_sample = chunk_fmt->bits_per_sample;
- obj->bit_rate = chunk_fmt->byte_rate * 8;
- obj->block_align = chunk_fmt->block_align;
- obj->data_size = chunk_data->sub_chunk2_size;
- obj->data_start_offset = offset;
- obj->total_second = obj->data_size;
- }else{
- return false;}
- return true;
- }</font></span></font>
wav_decode_read 讀取音頻文件數(shù)據:
- <font face="Arial">/* read fatfs file. */
- bool wav_decode_read(wav_decode_obj_t * obj,uint16_t * buf,uint32_t buf_len){
- UINT fat_br = 0u;
- if (FR_OK != f_read(&(obj->fatfs_file), buf, buf_len,&fat_br) ){
- return false;}
- obj->current_second+=fat_br;
- if((fat_br <= 0) || (fat_br < buf_len)){
- return false;}
- return true;
- }</font>
wav_decode_close 解碼數(shù)據結束:
- <font face="Arial">/* close fatfs file. */
- void wav_decode_close(wav_decode_obj_t * obj){
- f_close(&(obj->fatfs_file) );}
- </font>
app_wav_play 播放 WAV:
- <font face="Arial">/* play wave audio. */
- void app_wav_play(void){
- if( wav_decode_open(&wav_obj, file_path, file_buf, 10240) ){
- if( (wav_obj.bits_per_sample == 16) &&
- (wav_obj.channel == 2) &&
- (wav_obj.sample_rate > 44000) &&
- (wav_obj.sample_rate < 48100)){
- Audio_ClearStatus(AUDIO_STATUS_XFER_HALF | AUDIO_STATUS_XFER_DONE);
- wav_decode_read(&wav_obj, audio_buf[0], 5120);
- Audio_SetConf(44100, (uint16_t *)audio_buf[0], 2560);
- Audio_Enable(true);}}
- else{
- return;}
- uint8_t next_index = 1;
- while(1){
- while((Audio_GetStatus() & AUDIO_STATUS_XFER_HALF) != AUDIO_STATUS_XFER_HALF);
- Audio_ClearStatus(AUDIO_STATUS_XFER_HALF);
- if(next_index == 0){
- if(!wav_decode_read(&wav_obj,audio_buf[0], 5120)){
- break;}}
- else{
- if(!wav_decode_read(&wav_obj,audio_buf[1], 5120)){
- break;}}
- while((Audio_GetStatus() & AUDIO_STATUS_XFER_DONE) != AUDIO_STATUS_XFER_DONE);
- Audio_ClearStatus(AUDIO_STATUS_XFER_DONE);
- if(next_index == 0){
- Audio_SetConf(44100, (uint16_t *)audio_buf[0], 2560);
- next_index = 1;}
- else{
- Audio_SetConf(44100, (uint16_t *)audio_buf[1], 2560);
- next_index = 0;}
- Audio_Enable(true);}
- Audio_Enable(false);
- wav_decode_close(&wav_obj);}</font>
六、MP3音頻文件解碼
1.MP3 格式音樂文件 (Moving Picture Experts Group Audio Layer III (MPEG Audio Layer 3) ),經過壓縮后的 MP3 文件數(shù)據由多個幀 (frame) 組成。幀是 MP3 文件的最小組成單位,每個幀由幀頭 、附加信息和聲音數(shù)據組成,幀的長度由不同的 MP3 文件而不同,每個幀包含一段音頻的壓縮數(shù)據,通過解碼庫解碼即可得到對應 PCM 音頻數(shù)據。
2.MP3解碼庫
適合在小型嵌入式控制器移植的有兩個開源 MP3 解碼庫,libmad 解碼庫和 helix 解碼庫,這兩個解碼庫都是以一幀為解碼單位,一次解碼一幀,其區(qū)別見下表:
Libmad | Helix |
|
|
3.libmad軟件解碼庫
本實驗使用Libmad解碼庫進行MP3解碼。libmad 是一個開源 MP3 解碼庫,其對 MP3 解碼算法做了很多優(yōu)化,性能較好,很多播放器如 mplayer、xmms 等都是使用這個開源庫進行解碼的。Download from : https://downloads.sourceforge.net/mad/libmad-0.15.1b.tar.gz
“mad.h” 頭文件定義了 libmad 的數(shù)據結構及 API 函數(shù),libmad 中的主要數(shù)據結構體如下表所示:
4.移植libmad
將 libmad-0.15.1b 文件夾復制到工程目錄,將所有的 .c 文件加入工程,設置好包含路徑。
若編譯出現(xiàn) “FPM not select” 警告,在 KEIL 進行宏定義配置,如下圖:
libmad 代碼中使用 DEBUG 預編譯作為調試開關,需將其屏蔽
libmad 解碼出的數(shù)據為 24-bit PCM 數(shù)據,需進行 24-bit 至 16-bit 的轉換,使用 uint16_t scale(mad_fixed_t sample) 函數(shù)。
解碼用到三個數(shù)據結構,需將其定義為全局變量,防止?臻g不夠:
解碼的緩沖區(qū) audio buffer 要設置為全局變量,注意字節(jié)對齊的問題。
Libmad音頻解碼MP3也分為三個API完成:
酷狗音樂下載網址
https://www.kugou.com/yy/html/rank.html
附件
軟件工程源代碼:
MM32F5270原理圖:
- 本文系21ic原創(chuàng),未經許可禁止轉載!
網友評論
- 聯(lián)系人:巧克力娃娃
- 郵箱:board@21ic.com
- 我要投稿
-
歡迎入駐,開放投稿
-
人均百萬?英偉達中國員工收入曝光! 2024-08-29
-
《黑神話:悟空》玩家硬盤升級攻略:提升游戲體驗,暢享3A大作 2024-08-29
-
數(shù)睿數(shù)據參加《系統(tǒng)與軟件工程 低代碼開發(fā)平臺通用技術要求》國家標準編制 2024-08-29
- NRF52810藍牙數(shù)字耳機找人定制
預算:¥30005天前
- 125KW模塊式PCS軟硬件外包開發(fā)
預算:¥1100000015小時前
- 12V汽車啟動電源項目BMS設計
預算:¥50000023小時前
- 數(shù)據可視化軟件 開發(fā)
預算:¥5000023小時前
- PLC項目調試修改
預算:¥100001天前
- 起動電機控制器開發(fā)
預算:¥1100001天前