硬件准备
ADSP-EDU-BF533:BF533开发板
AD-HP530ICE:ADI DSP仿真器
软件准备
Visual DSP++软件
硬件链接
代码实现功能
代码实现了读取工程目录下的一个 MP3 文件,对文件进行解码后,将生成的数据以 PCM 文件的形式保存在工程目录下。代码调用了 MP3 解码库,该解码库可对采样率 44.1KHz,位速 128Kbps 的 MP3 文件进行解码。解码后文件以 PCM 格式保存,通过 GoldWave 软件可对文件进行播放。
代码使用说明
主要函数说明:
int find_head(unsigned char *start,unsigned char *end)
参数:start :mp3 数据的起始内存地址
End :mp3 数据的终止内存地址
返回值:音频帧的起始地址,相对 start 的偏移量。
作用:从 start 到 end 的内存进行音频帧的查询,得到距离 start 地址最近的帧位置。
int check_data(char * pMp3Stream,char *pPCMStream,int *in_size,int *out_size,FILE *save_file)
参数:pMp3Stream :mp3 数据帧的起始位置,可参照 demo 的使用(至少有 0x20 个数据 字节):mp3 数据的起始地址+帧的偏移地址;
pPCMStream :mp3 解码数据的存储地址,必须要保证 4920 字节长度。
in_size :返回针对本 mp3 音频格式的每次解码所需的数据帧大小
out_size :返回针对本 mp3 音频格式的每次解码后的数据大小
save_file:如果进行文件保持,该项传递要保存文件的指针。
如果不用进行文件保存,则传递 0x0 参数。
返回值:1:表示检测过程真确,得到了文件的信息,并保证返回的参数有效;
-1:表示本次检测失败;原因:pMp3Stream 的地址是否是帧起始地址;该地址 开始是否存储有 mp3 数据 0x20 个字节。
作用:通过对 mp3 的帧数据进行检测,得到 mp3 文件的相关信息,并计算出该文件的帧大小和解码后数据的大小。
int MP3DEC_decode( unsigned char *pInData,
unsigned long inSize,
unsigned char *pOutData,
unsigned short *pGetSize,
MP3DEC_Params *pDecParams)
参数:pInData:mp3 的单帧起始地址
inSize :单帧的数据大小
pOutData:单帧解码后的数据存储起始地址
pGetSize :已解码的数据大小
pDecParams:解码的相关参数
返回值:1:表示该帧数据解码的数据有效
其它:表示该帧数据解码数据无效
作用:对需要解码的 mp3 数据帧进行解码;
.
片断分析:
pMp3Stream = mp3_stream;
pPCMStream = dataA;
MP3DEC_init(); //初始化相关的数据
output_file = fopen(“…/test.wav”,“wb”);//打开解码结果的存储文件
input_file = fopen(“…/test.mp3”,“rb”);//打开需要进行解码的文件
result_num = fread(mp3_stream,1,0x300000-0x1000,input_file);
//读取的大小 0x300000-0x1000 是针对本 demo 代码只给予输入 mp3 数据最大的内存容量
//来决定的
asm(“ssync;”);
mp3_stream_bufend = &mp3_stream[0] + result_num;//mp3 数据的结束地址
head_flag = find_head(pMp3Stream,mp3_stream_bufend); //寻找 mp3 数据的音频同步
//帧的位置
decode_flag = pMp3Stream+head_flag;
result = check_data(decode_flag,pPCMStream,&input_mp3,&output_mp3,output_file);
//检查音频帧和数据流
if(result == -1)
{
printf(“error mp3 file format \n”);
}
while(1)
{
result = MP3DEC_decode(decode_flag,input_mp3,pPCMStream,&decodedSize_t,&myDecParams_t);
//进行每一音频帧的解码操作
if(result == 1)
{
frame_num++;
pPCMStream += output_mp3;
if(frame_num>0x100)
{
fwrite(dataA,1,output_mp3frame_num,output_file);//保存解码结果
asm(“ssync;”);
frame_num = 0;
pPCMStream = dataA;
}
}
decode_flag += input_mp3;
if(decode_flag+input_mp3 >= mp3_stream_bufend)//判断解码是否完成
{
fwrite(dataA,1,output_mp3frame_num,output_file);
asm(“ssync;”);
break;
}
}
fclose(output_file);
fclose(input_file);
MP3DEC_exit();
注意事项:
1. 函数只能对 128kbps、44.1kHz 存储格式的 mp3 文件进行解码;
2. 用户在自己生成工程中使用该解码库,必须向工程中添加 mp3dec_lib.dlb, testbf533.ldf。 3. 如果用户更改了工程属性,那么该操作会反映给 LDF 文件,那么需要把原始的 LDF 再次拷贝到工程下。
代码实验步骤
- 编译代码
- 运行代码,查看原工程下生成的 PCM 文件,正常解码后,刷新时能看到 PCM 文件大小会慢慢增加。如,没有慢慢增加或过早退出工程,说明解码失败,可以尝试重新编译代码,然后按 F10 键,单步方式将代码运行到 MP3 循环解码的函数里,然后再按 F5 键连续运行。
- 待代码运行结束后,确认代码已执行过代码中的 fclose(output_file)函数,然后可以使用 GoldWave 软件,打开 PCM 文件。当提示文件打开格式时,按如图配置:
- 加载完数据后,即可播放解码后的 PCM 数据流。
代码实验结果
工程下生成 MP3 文件解码后的 PCM 文件,用 GoldWave 软件可以对其进行播放,听到解码后数据音乐。
程序源码
cpu.c
#include <cdefBF533.h>
void Set_PLL(int pmsel,int pssel)
{
int new_PLL_CTL;
*pPLL_DIV = pssel;
asm(“ssync;”);
new_PLL_CTL = (pmsel & 0x3f) << 9;
*pSIC_IWR |= 0xffffffff;
if (new_PLL_CTL != *pPLL_CTL)
{
*pPLL_CTL = new_PLL_CTL;
asm(“ssync;”);
asm(“idle;”);
}
}
void Init_SDRAM(void)
{
*pEBIU_SDRRC = 0x00000817;
*pEBIU_SDBCTL = 0x00000013;
*pEBIU_SDGCTL = 0x0091998d;
ssync();
}
void Init_EBIU(void)
{
*pEBIU_AMBCTL0 = 0x7bb07bb0;
*pEBIU_AMBCTL1 = 0x7bb07bb0;
*pEBIU_AMGCTL = 0x000f;
}
delay(int tem)
{
int i;
for(i=0;i<tem;i++);
}
main.c
#include <cdefBF533.h>
#include <stdio.h>
#include <sys\exception.h>
#include <ccblkfn.h>
#include “api_mp3dec.h”
MP3DEC_Params myDecParams_t;
void main(void)
{
int input_mp3,frame_num,decodedSize;
int output_mp3;
int head_flag;
unsigned short decodedSize_t;
char * decode_flag,*pMp3Stream,*pPCMStream,*mp3_stream_bufend;
char * mp3_stream;
char * dataA;
int result_num;
FILE *output_file;
FILE *input_file;
int result = 0;
frame_num = 0;
result_num = 0;
Set_PLL(16,4);
Init_EBIU();
Init_SDRAM();
mp3_stream = 0x1000;
dataA = 0x300000;
decode_flag = dataA;
int i;
for( i = 0;i<0x100*1248 * 4;i++)
{
*decode_flag++ = 0;
}
pMp3Stream = mp3_stream;
pPCMStream = dataA;
MP3DEC_init();
output_file = fopen("../test.pcm","wb");
input_file = fopen("../test.mp3","rb");
result_num = fread(mp3_stream,1,0x300000-0x1000,input_file);
asm("ssync;");
mp3_stream_bufend = &mp3_stream[0] + result_num;
head_flag = find_head(pMp3Stream,mp3_stream_bufend);
decode_flag = pMp3Stream+head_flag;
result = check_data(decode_flag,pPCMStream,&input_mp3,&output_mp3,output_file);
delay(100);
if(result == -1)
{
printf("error mp3 file format \n");
}
while(1)
{
result = MP3DEC_decode(decode_flag,input_mp3,pPCMStream,&decodedSize_t,&myDecParams_t);
if(result == 1)
{
frame_num++;
pPCMStream += output_mp3;
if(frame_num>0x100)
{
fwrite(dataA,1,output_mp3*frame_num,output_file);
asm("ssync;");
frame_num = 0;
pPCMStream = dataA;
}
// fwrite(pPCMStream,1,output_mp3,output_file);
}
decode_flag += input_mp3;
if(decode_flag+input_mp3 >= mp3_stream_bufend)
{
fwrite(dataA,1,output_mp3*frame_num,output_file);
asm("ssync;");
break;
}
}
fclose(input_file);
fclose(output_file);
printf("pcm file done!\n");
MP3DEC_exit();
}