693 lines
18 KiB
C
693 lines
18 KiB
C
#include "mp3play.h"
|
||
#include "stm32f4xx.h"
|
||
#include "dac.h"
|
||
#include "delay.h"
|
||
#include "mymem.h"
|
||
#include "usart.h"
|
||
#include "string.h"
|
||
#include "rtthread.h"
|
||
#include "ftfile.h"
|
||
|
||
//包含这个文件用于文字编码转换
|
||
#include "char_encode.h"
|
||
|
||
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////
|
||
//本程序移植自helix MP3解码库
|
||
//ALIENTEK STM32F407开发板
|
||
//MP3 解码代码
|
||
//正点原子@ALIENTEK
|
||
//技术论坛:www.openedv.com
|
||
//创建日期:2014/6/29
|
||
//版本:V1.0
|
||
//********************************************************************************
|
||
//V1.0 说明
|
||
//1,支持16位单声道/立体声MP3的解码
|
||
//2,支持CBR/VBR格式MP3解码
|
||
//3,支持ID3V1和ID3V2标签解析
|
||
//4,支持所有比特率(MP3最高是320Kbps)解码
|
||
//////////////////////////////////////////////////////////////////////////////////
|
||
|
||
static __mp3ctrl * mp3ctrl; //mp3控制结构体
|
||
static __audiodev audiodev; //音频控制结构体
|
||
static vu8 g_buff_Invalid=0; //数据无效时要重新填充数据
|
||
static vu8 g_buff_useing; //当前DMA在使用哪个缓冲区
|
||
static int g_vol=5; //音量 0~10级
|
||
#define MP3_VOL_MAX 10
|
||
|
||
|
||
//MP3 DMA发送回调函数
|
||
static void dma_tx_callback(DAC_UserStruct *dac)
|
||
{
|
||
u16 i;
|
||
if (dac->buff_useing==1)
|
||
{
|
||
if((audiodev.status&0X01)==0)//暂停了,填充0
|
||
{
|
||
for(i=0;i<2304*2;i++)audiodev.i2sbuf1[i]=0;
|
||
}
|
||
}else
|
||
{
|
||
if((audiodev.status&0X01)==0)//暂停了,填充0
|
||
{
|
||
for(i=0;i<2304*2;i++)audiodev.i2sbuf2[i]=0;
|
||
}
|
||
}
|
||
g_buff_useing=dac->buff_useing;
|
||
g_buff_Invalid=1;
|
||
}
|
||
//填充PCM数据到DAC
|
||
//buf:PCM数据首地址
|
||
//size:pcm数据量(16位为单位)
|
||
//nch:声道数(1,单声道,2立体声)
|
||
void mp3_fill_buffer(u16* buf,u16 size,u8 nch)
|
||
{
|
||
u16 i;
|
||
s16 *p;
|
||
while(g_buff_Invalid==0)//等待传输完成
|
||
{
|
||
rt_thread_delay(5);//
|
||
};
|
||
if(g_buff_useing==0)
|
||
{
|
||
p=(s16*)audiodev.i2sbuf2;
|
||
}else
|
||
{
|
||
p=(s16*)audiodev.i2sbuf1;
|
||
}
|
||
if(nch==2)
|
||
{
|
||
for(i=0;i<size;i++)
|
||
{
|
||
// p[i]=((buf[i]+0x8000)>>4);
|
||
int temp=(int16_t)buf[i];
|
||
temp=temp*g_vol/MP3_VOL_MAX;
|
||
p[i]=((temp+0x8000)>>4);
|
||
}
|
||
}
|
||
else //单声道
|
||
{
|
||
for(i=0;i<size;i++)
|
||
{
|
||
int temp=(int16_t)buf[i];
|
||
temp=temp*g_vol/MP3_VOL_MAX;
|
||
p[2*i]=((temp+0x8000)>>4);
|
||
p[2*i+1]=p[2*i];
|
||
}
|
||
}
|
||
//填充了数据之后设置为有效
|
||
g_buff_Invalid=0;
|
||
}
|
||
|
||
|
||
|
||
static void mp3_get_string (u8 type,u8 *out,u8 *in,int size);
|
||
|
||
|
||
|
||
|
||
//解析ID3V1
|
||
//buf:输入数据缓存区(大小固定是128字节)
|
||
//pctrl:MP3控制器
|
||
//返回值:0,获取正常
|
||
// 其他,获取失败
|
||
u8 mp3_id3v1_decode(u8* buf,__mp3ctrl *pctrl)
|
||
{
|
||
ID3V1_Tag *id3v1tag;
|
||
id3v1tag=(ID3V1_Tag*)buf;
|
||
if (strncmp("TAG",(char*)id3v1tag->id,3)==0)//是MP3 ID3V1 TAG
|
||
{
|
||
mp3_get_string(0,pctrl->title,id3v1tag->title,30);
|
||
mp3_get_string(0,pctrl->artist,id3v1tag->artist,30);
|
||
}else return 1;
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
static void mp3_get_string (u8 type,u8 *out,u8 *in,int size)
|
||
{
|
||
if (type==1)//UNICODE16
|
||
{
|
||
u8 *char_uni=mymalloc (128);
|
||
mymemset(char_uni,0,128);
|
||
strncpy((char*)char_uni,(char*)(in),size);
|
||
//Unicode转GBK
|
||
uni2gbk_str(char_uni,out);
|
||
myfree(char_uni);
|
||
}
|
||
else if (type==3)//UTF8
|
||
{
|
||
u8 *char_utf8=mymalloc (128);
|
||
mymemset(char_utf8,0,128);
|
||
strncpy((char*)char_utf8,(char*)(in),size);
|
||
|
||
//UTF8转GBK
|
||
utf82gbk_str (char_utf8,out);
|
||
|
||
myfree(char_utf8);
|
||
}
|
||
else //(type==0)//ASCII
|
||
{
|
||
strncpy((char*)out,(char*)(in),size);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
//解析ID3V2
|
||
//buf:输入数据缓存区
|
||
//size:数据大小
|
||
//pctrl:MP3控制器
|
||
//返回值:0,获取正常
|
||
// 其他,获取失败
|
||
u8 mp3_id3v2_decode(u8* buf,u32 size,__mp3ctrl *pctrl)
|
||
{
|
||
ID3V2_TagHead *taghead;
|
||
ID3V23_FrameHead *framehead;
|
||
u32 t;
|
||
u32 tagsize; //tag大小
|
||
u32 frame_size; //帧大小
|
||
taghead=(ID3V2_TagHead*)buf;
|
||
if(strncmp("ID3",(const char*)taghead->id,3)==0)//存在ID3?
|
||
{
|
||
tagsize=((u32)taghead->size[0]<<21)|((u32)taghead->size[1]<<14)|((u16)taghead->size[2]<<7)|taghead->size[3];//得到tag 大小
|
||
pctrl->datastart=tagsize; //得到mp3数据开始的偏移量
|
||
if(tagsize>size)tagsize=size; //tagsize大于输入bufsize的时候,只处理输入size大小的数据
|
||
if(taghead->mversion<3)
|
||
{
|
||
printf("not supported mversion!\r\n");
|
||
return 1;
|
||
}
|
||
t=10;
|
||
while(t<tagsize)
|
||
{
|
||
framehead=(ID3V23_FrameHead*)(buf+t);
|
||
frame_size=((u32)framehead->size[0]<<24)|((u32)framehead->size[1]<<16)|((u32)framehead->size[2]<<8)|framehead->size[3];//得到帧大小
|
||
if (strncmp("TT2",(char*)framehead->id,3)==0||strncmp("TIT2",(char*)framehead->id,4)==0)//找到歌曲标题帧,不支持unicode格式!!
|
||
{
|
||
u8 *dat_ptr=(buf+t+sizeof(ID3V23_FrameHead));
|
||
int size=AUDIO_MIN(frame_size-1,MP3_TITSIZE_MAX-1);
|
||
mp3_get_string(dat_ptr[0],pctrl->title,dat_ptr+1,size);
|
||
}
|
||
if (strncmp("TP1",(char*)framehead->id,3)==0||strncmp("TPE1",(char*)framehead->id,4)==0)//找到歌曲艺术家帧
|
||
{
|
||
u8 *dat_ptr=(buf+t+sizeof(ID3V23_FrameHead));
|
||
int size=AUDIO_MIN(frame_size-1,MP3_ARTSIZE_MAX-1);
|
||
mp3_get_string(dat_ptr[0],pctrl->artist,dat_ptr+1,size);
|
||
}
|
||
// if (strncmp("APIC",(char*)framehead->id,4)==0)
|
||
// {
|
||
// //专辑封面
|
||
// u8 *dat_ptr=(buf+t+sizeof(ID3V23_FrameHead));
|
||
// if (pctrl->jpeg_data) myfree(pctrl->jpeg_data);
|
||
// pctrl->jpeg_data=mymalloc(frame_size);
|
||
// pctrl->jpeg_len=frame_size;
|
||
// mymemcpy (pctrl->jpeg_data,dat_ptr,frame_size);
|
||
// }
|
||
t+=frame_size+sizeof(ID3V23_FrameHead);
|
||
}
|
||
return 0;
|
||
}else
|
||
{ pctrl->datastart=0;//不存在ID3,mp3数据是从0开始
|
||
return (u8)-1;
|
||
}
|
||
}
|
||
|
||
//获取MP3基本信息
|
||
//pname:MP3文件路径
|
||
//pctrl:MP3控制信息结构体
|
||
//返回值:0,成功
|
||
// 其他,失败
|
||
u8 mp3_get_info(u8 *data,u32 size,__mp3ctrl* pctrl)
|
||
{
|
||
HMP3Decoder decoder={0};
|
||
MP3FrameInfo frame_info={0};
|
||
MP3_FrameXing* fxing=0;
|
||
MP3_FrameVBRI* fvbri=0;
|
||
u8 *buf=0;
|
||
u8 *data_ptr=0;
|
||
//u32 br;
|
||
u8 res=0;
|
||
int offset=0;
|
||
u32 p=0;
|
||
short samples_per_frame=0; //一帧的采样个数
|
||
u32 totframes=0; //总帧数
|
||
|
||
buf=mymalloc(MP3_FILE_BUF_SZ); //申请5K内存
|
||
if(buf)//内存申请成功
|
||
{
|
||
data_ptr=data;
|
||
mymemcpy (buf,data_ptr,MP3_FILE_BUF_SZ);
|
||
if(res==0)//读取文件成功,开始解析ID3V2/ID3V1以及获取MP3信息
|
||
{
|
||
if (mp3_id3v2_decode(buf,MP3_FILE_BUF_SZ,pctrl)!=0) //解析ID3V2数据
|
||
{
|
||
data_ptr=data+size-128;
|
||
mymemcpy (buf,data_ptr,128);
|
||
mp3_id3v1_decode(buf,pctrl); //解析ID3V1数据
|
||
}
|
||
decoder=MP3InitDecoder(); //MP3解码申请内存
|
||
data_ptr=data+pctrl->datastart;
|
||
mymemcpy (buf,data_ptr,MP3_FILE_BUF_SZ);
|
||
offset=MP3FindSyncWord(buf,MP3_FILE_BUF_SZ); //查找帧同步信息
|
||
if(offset>=0&&MP3GetNextFrameInfo(decoder,&frame_info,&buf[offset])==0)//找到帧同步信息了,且下一阵信息获取正常
|
||
{
|
||
p=offset+4+32;
|
||
fvbri=(MP3_FrameVBRI*)(buf+p);
|
||
if(strncmp("VBRI",(char*)fvbri->id,4)==0)//存在VBRI帧(VBR格式)
|
||
{
|
||
if (frame_info.version==MPEG1)samples_per_frame=1152;//MPEG1,layer3每帧采样数等于1152
|
||
else samples_per_frame=576;//MPEG2/MPEG2.5,layer3每帧采样数等于576
|
||
totframes=((u32)fvbri->frames[0]<<24)|((u32)fvbri->frames[1]<<16)|((u16)fvbri->frames[2]<<8)|fvbri->frames[3];//得到总帧数
|
||
pctrl->totsec=totframes*samples_per_frame/frame_info.samprate;//得到文件总长度
|
||
}else //不是VBRI帧,尝试是不是Xing帧(VBR格式)
|
||
{
|
||
if (frame_info.version==MPEG1) //MPEG1
|
||
{
|
||
p=frame_info.nChans==2?32:17;
|
||
samples_per_frame = 1152; //MPEG1,layer3每帧采样数等于1152
|
||
}else
|
||
{
|
||
p=frame_info.nChans==2?17:9;
|
||
samples_per_frame=576; //MPEG2/MPEG2.5,layer3每帧采样数等于576
|
||
}
|
||
p+=offset+4;
|
||
fxing=(MP3_FrameXing*)(buf+p);
|
||
if(strncmp("Xing",(char*)fxing->id,4)==0||strncmp("Info",(char*)fxing->id,4)==0)//是Xng帧
|
||
{
|
||
if(fxing->flags[3]&0X01)//存在总frame字段
|
||
{
|
||
totframes=((u32)fxing->frames[0]<<24)|((u32)fxing->frames[1]<<16)|((u16)fxing->frames[2]<<8)|fxing->frames[3];//得到总帧数
|
||
pctrl->totsec=totframes*samples_per_frame/frame_info.samprate;//得到文件总长度
|
||
}else //不存在总frames字段
|
||
{
|
||
pctrl->totsec=size/(frame_info.bitrate/8);
|
||
}
|
||
}else //CBR格式,直接计算总播放时间
|
||
{
|
||
pctrl->totsec=size/(frame_info.bitrate/8);
|
||
}
|
||
}
|
||
pctrl->bitrate=frame_info.bitrate; //得到当前帧的码率
|
||
mp3ctrl->samplerate=frame_info.samprate; //得到采样率.
|
||
if(frame_info.nChans==2)mp3ctrl->outsamples=frame_info.outputSamps; //输出PCM数据量大小
|
||
else mp3ctrl->outsamples=frame_info.outputSamps*2; //输出PCM数据量大小,对于单声道MP3,直接*2,补齐为双声道输出
|
||
}else res=0XFE;//未找到同步帧
|
||
MP3FreeDecoder(decoder);//释放内存
|
||
}
|
||
}else res=0XFF;
|
||
myfree(buf);
|
||
return res;
|
||
}
|
||
//得到当前播放时间
|
||
//fx:文件指针
|
||
//mp3x:mp3播放控制器
|
||
//void mp3_get_curtime(FIL*fx, FILINFO *finfo,__mp3ctrl *mp3x)
|
||
//{
|
||
// u32 fpos=0;
|
||
// if(fx->fptr>mp3x->datastart)fpos=fx->fptr-mp3x->datastart; //得到当前文件播放到的地方
|
||
// mp3x->cursec=fpos*mp3x->totsec/(finfo->fsize-mp3x->datastart); //当前播放到第多少秒了?
|
||
//}
|
||
//mp3文件快进快退函数
|
||
//pos:需要定位到的文件位置
|
||
//返回值:当前文件位置(即定位后的结果)
|
||
u32 mp3_file_seek(u32 pos)
|
||
{
|
||
// if(pos>audiodev.file->fsize)
|
||
// {
|
||
// pos=audiodev.file->fsize;
|
||
// }
|
||
// f_lseek(audiodev.file,pos);
|
||
// return audiodev.file->fptr;
|
||
return pos;
|
||
}
|
||
|
||
|
||
|
||
|
||
//判断mp3是否支持
|
||
//读取 MP3_FILE_BUF_SZ 大小的数据就行了
|
||
//返回0 支持,非0 不支持
|
||
int mp3_get_support (u8* data,u32 size)
|
||
{
|
||
int res=0;
|
||
__mp3ctrl *mp3ctrl=mymalloc(sizeof(__mp3ctrl));
|
||
mymemset(mp3ctrl,0,sizeof(__mp3ctrl));//数据清零
|
||
res=mp3_get_info(data,size,mp3ctrl);
|
||
if (mp3ctrl->jpeg_data) myfree(mp3ctrl->jpeg_data);
|
||
myfree(mp3ctrl);
|
||
mp3ctrl=0;
|
||
return res;
|
||
}
|
||
|
||
//返回0 支持,非0 不支持
|
||
int mp3_get_support_name (const char *name)
|
||
{
|
||
//定义返回变量
|
||
int res=0;
|
||
|
||
//初始化mp3结构体
|
||
__mp3ctrl *mp3ctrl=mymalloc(sizeof(__mp3ctrl));
|
||
mymemset(mp3ctrl,0,sizeof(__mp3ctrl));//数据清零
|
||
|
||
//申请缓存
|
||
u32 buf_size=1024*5;
|
||
u8 *buf=mymalloc (buf_size);
|
||
|
||
//打开文件
|
||
ft_file_struct *file=ft_if_fopen(name,"rw");
|
||
|
||
//获取头大小
|
||
ft_if_fseek(file,0,SEEK_SET);
|
||
ft_if_fread(buf,1,buf_size,file);
|
||
ID3V2_TagHead *taghead;
|
||
u32 tagsize=0; //tag大小
|
||
taghead=(ID3V2_TagHead*)buf;
|
||
if(strncmp("ID3",(const char*)taghead->id,3)==0)//存在ID3?
|
||
{
|
||
tagsize=((u32)taghead->size[0]<<21)|((u32)taghead->size[1]<<14)|((u16)taghead->size[2]<<7)|taghead->size[3];//得到tag 大小
|
||
}
|
||
|
||
//校验格式是否支持
|
||
HMP3Decoder decoder={0};
|
||
MP3FrameInfo frame_info={0};
|
||
int offset=0;
|
||
decoder=MP3InitDecoder(); //MP3解码申请内存
|
||
ft_if_fseek(file,tagsize,SEEK_SET);
|
||
ft_if_fread(buf,1,buf_size,file);
|
||
offset=MP3FindSyncWord(buf,buf_size); //查找帧同步信息
|
||
if(offset>=0&&MP3GetNextFrameInfo(decoder,&frame_info,&buf[offset])==0)//找到帧同步信息了,且下一阵信息获取正常
|
||
{ res=0; }
|
||
else res=-1;
|
||
MP3FreeDecoder(decoder);//释放内存
|
||
|
||
//关闭文件
|
||
ft_if_fclose(file);
|
||
|
||
//释放缓存
|
||
myfree(buf);
|
||
|
||
//释放mp3结构体
|
||
myfree(mp3ctrl);
|
||
|
||
//返回结果
|
||
return res;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
//播放一曲MP3音乐
|
||
//fname:MP3文件路径.
|
||
//返回值:0,正常播放完成
|
||
//[b7]:0,正常状态;1,错误状态
|
||
//[b6:0]:b7=0时,表示操作码
|
||
// b7=1时,表示有错误(这里不判定具体错误,0X80~0XFF,都算是错误)
|
||
u8 mp3_play_song(u8* data,u32 size)
|
||
{
|
||
|
||
if (mp3ctrl) return AP_ERR;//不可重入!
|
||
HMP3Decoder mp3decoder={0};
|
||
MP3FrameInfo mp3frameinfo={0};
|
||
u8 res=0;
|
||
u8* buffer=0; //输入buffer
|
||
u8* readptr=0; //MP3解码读指针
|
||
u8 *data_ptr=0;
|
||
int offset=0; //偏移量
|
||
int outofdata=0;//超出数据范围
|
||
int bytesleft=0;//buffer还剩余的有效数据
|
||
u32 br=0;
|
||
int err=0;
|
||
DAC_UserStruct dac={0};
|
||
|
||
mp3ctrl=mymalloc(sizeof(__mp3ctrl));
|
||
buffer=mymalloc(MP3_FILE_BUF_SZ); //申请解码buf大小
|
||
audiodev.i2sbuf1=mymalloc(2304*2);
|
||
audiodev.i2sbuf2=mymalloc(2304*2);
|
||
audiodev.tbuf=mymalloc(2304*2);
|
||
audiodev.file_seek=mp3_file_seek;
|
||
|
||
if(!mp3ctrl||!buffer||!audiodev.i2sbuf1||!audiodev.i2sbuf2||!audiodev.tbuf)//内存申请失败
|
||
{
|
||
myfree(mp3ctrl);
|
||
myfree(buffer);
|
||
myfree(audiodev.i2sbuf1);
|
||
myfree(audiodev.i2sbuf2);
|
||
myfree(audiodev.tbuf);
|
||
return AP_ERR; //错误
|
||
}
|
||
mymemset(audiodev.i2sbuf1,0,2304*2); //数据清零
|
||
mymemset(audiodev.i2sbuf2,0,2304*2); //数据清零
|
||
mymemset(mp3ctrl,0,sizeof(__mp3ctrl));//数据清零
|
||
res=mp3_get_info(data,size,mp3ctrl);
|
||
if(res==0)
|
||
{
|
||
|
||
//初始化DAC
|
||
dac.buff1=(u32 *)audiodev.i2sbuf1;
|
||
dac.buff2=(u32 *)audiodev.i2sbuf2;
|
||
//dac.buff_size=2304*2;
|
||
dac.buff_size=mp3ctrl->outsamples*2;
|
||
dac.rate=DAC_GetRate(mp3ctrl->samplerate);
|
||
dac.call_back=dma_tx_callback;
|
||
DAC_NormalInit (&dac);
|
||
mp3decoder=MP3InitDecoder(); //MP3解码申请内存
|
||
audiodev.status|=1<<1; //开启播放
|
||
audiodev.status|=1<<0; //非暂停状态
|
||
}
|
||
if(res==0&&mp3decoder!=0)//打开文件成功
|
||
{
|
||
//f_lseek(audiodev.file,mp3ctrl->datastart); //跳过文件头中tag信息
|
||
data_ptr=data+mp3ctrl->datastart;
|
||
//audio_start(); //开始播放
|
||
while(res==0)
|
||
{
|
||
readptr=buffer; //MP3读指针指向buffer
|
||
offset=0; //偏移量为0
|
||
outofdata=0; //数据正常
|
||
bytesleft=0;
|
||
//res=f_read(audiodev.file,buffer,MP3_FILE_BUF_SZ,&br);//一次读取MP3_FILE_BUF_SZ字节
|
||
br=MP3_FILE_BUF_SZ;
|
||
if (br>data+size-data_ptr) br=data+size-data_ptr;
|
||
mymemcpy (buffer,data_ptr,br);
|
||
data_ptr+=br;
|
||
if(res)//读数据出错了
|
||
{
|
||
res=AP_ERR;
|
||
break;
|
||
}
|
||
if(br==0) //读数为0,说明解码完成了.
|
||
{
|
||
res=AP_OK; //播放完成
|
||
break;
|
||
}
|
||
bytesleft+=br; //buffer里面有多少有效MP3数据?
|
||
err=0;
|
||
while(!outofdata)//没有出现数据异常(即可否找到帧同步字符)
|
||
{
|
||
offset=MP3FindSyncWord(readptr,bytesleft);//在readptr位置,开始查找同步字符
|
||
if(offset<0) //没有找到同步字符,跳出帧解码循环
|
||
{
|
||
outofdata=1;//没找到帧同步字符
|
||
}else //找到同步字符了
|
||
{
|
||
readptr+=offset; //MP3读指针偏移到同步字符处.
|
||
bytesleft-=offset; //buffer里面的有效数据个数,必须减去偏移量
|
||
err=MP3Decode(mp3decoder,&readptr,&bytesleft,(short*)audiodev.tbuf,0);//解码一帧MP3数据
|
||
|
||
if(err!=0)
|
||
{
|
||
//printf("decode error:%d\r\n",err);
|
||
break;
|
||
}else
|
||
{
|
||
MP3GetLastFrameInfo(mp3decoder,&mp3frameinfo); //得到刚刚解码的MP3帧信息
|
||
if(mp3ctrl->bitrate!=mp3frameinfo.bitrate) //更新码率
|
||
{
|
||
mp3ctrl->bitrate=mp3frameinfo.bitrate;
|
||
}
|
||
mp3_fill_buffer((u16*)audiodev.tbuf,mp3frameinfo.outputSamps,mp3frameinfo.nChans);//填充pcm数据
|
||
}
|
||
if(bytesleft<MAINBUF_SIZE*2)//当数组内容小于2倍MAINBUF_SIZE的时候,必须补充新的数据进来.
|
||
{
|
||
memmove(buffer,readptr,bytesleft);//移动readptr所指向的数据到buffer里面,数据量大小为:bytesleft
|
||
//f_read(audiodev.file,buffer+bytesleft,MP3_FILE_BUF_SZ-bytesleft,&br);//补充余下的数据
|
||
br=MP3_FILE_BUF_SZ-bytesleft;
|
||
if (br>data+size-data_ptr) br=data+size-data_ptr;
|
||
mymemcpy (buffer+bytesleft,data_ptr,br);
|
||
data_ptr+=br;
|
||
if(br<MP3_FILE_BUF_SZ-bytesleft)
|
||
{
|
||
mymemset(buffer+bytesleft+br,0,MP3_FILE_BUF_SZ-bytesleft-br);
|
||
}
|
||
bytesleft=MP3_FILE_BUF_SZ;
|
||
readptr=buffer;
|
||
}
|
||
while(audiodev.status&(1<<1))//正常播放中
|
||
{
|
||
rt_thread_delay (5);
|
||
//mp3_get_curtime(audiodev.file,mp3ctrl);
|
||
u32 fpos=0;
|
||
if(data_ptr>data)fpos=data_ptr-data; //得到当前文件播放到的地方
|
||
mp3ctrl->cursec=fpos*mp3ctrl->totsec/(size-mp3ctrl->datastart); //当前播放到第多少秒了?
|
||
audiodev.totsec=mp3ctrl->totsec; //参数传递
|
||
audiodev.cursec=mp3ctrl->cursec;
|
||
audiodev.bitrate=mp3ctrl->bitrate;
|
||
audiodev.samplerate=mp3ctrl->samplerate;
|
||
audiodev.bps=16;//MP3仅支持16位
|
||
if(audiodev.status&0X01)break;//没有按下暂停
|
||
}
|
||
if((audiodev.status&(1<<1))==0)//请求结束播放/播放完成
|
||
{
|
||
res=AP_NEXT;//跳出上上级循环
|
||
outofdata=1;//跳出上一级循环
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//audio_stop();//关闭音频输出
|
||
}else res=AP_ERR;//错误
|
||
MP3FreeDecoder(mp3decoder); //释放内存
|
||
if (mp3ctrl->jpeg_data) myfree(mp3ctrl->jpeg_data);
|
||
myfree(mp3ctrl);
|
||
myfree(buffer);
|
||
myfree(audiodev.i2sbuf1);
|
||
myfree(audiodev.i2sbuf2);
|
||
myfree(audiodev.tbuf);
|
||
DAC_NormalDeInit (&dac);
|
||
mp3ctrl=0;
|
||
audiodev.cursec=0;
|
||
audiodev.totsec=0;
|
||
return res;
|
||
}
|
||
|
||
|
||
// 获取当前播放的曲目名,返回非0成功
|
||
char *mp3_get_name(void)
|
||
{
|
||
if(mp3ctrl)
|
||
return (char *)mp3ctrl->title;
|
||
else return 0;
|
||
}
|
||
|
||
|
||
// 获取当前播放的艺术家,返回非0成功
|
||
char *mp3_get_artist(void)
|
||
{
|
||
if(mp3ctrl)
|
||
return (char *)mp3ctrl->artist;
|
||
else return 0;
|
||
}
|
||
|
||
|
||
// 获取当前播放的时间,返回1成功
|
||
int mp3_get_time(int *totsec,int *cursec)
|
||
{
|
||
if(mp3ctrl)
|
||
{
|
||
if(totsec) *totsec=mp3ctrl->totsec;
|
||
if(cursec) *cursec=mp3ctrl->cursec;
|
||
return 1;
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
__audiodev *mp3_getAudiodev (void)
|
||
{
|
||
return &audiodev;
|
||
}
|
||
|
||
__mp3ctrl *mp3_getMp3Info (void)
|
||
{
|
||
return mp3ctrl;
|
||
}
|
||
|
||
|
||
|
||
void mp3_stop (void)
|
||
{
|
||
mp3_getAudiodev()->status=0;
|
||
}
|
||
|
||
|
||
void mp3_play (void)
|
||
{
|
||
//暂停中
|
||
if (mp3_getAudiodev()->status&1)
|
||
{
|
||
mp3_getAudiodev()->status&=(~1);
|
||
}
|
||
//播放中
|
||
else
|
||
{
|
||
mp3_getAudiodev()->status|=1;
|
||
}
|
||
}
|
||
|
||
|
||
void mp3_suspend (void)
|
||
{
|
||
mp3_getAudiodev()->status|=1;
|
||
}
|
||
|
||
// 设置音量
|
||
int mp3_set_vol(int vol)
|
||
{
|
||
if(vol>MP3_VOL_MAX) vol=MP3_VOL_MAX;
|
||
else if(vol<0) vol=0;
|
||
|
||
g_vol=vol;
|
||
return 0;
|
||
}
|
||
|
||
// 增加音量
|
||
int mp3_add_val(int vol)
|
||
{
|
||
vol=vol+g_vol;
|
||
if(vol>MP3_VOL_MAX) vol=MP3_VOL_MAX;
|
||
else if(vol<0) vol=0;
|
||
|
||
g_vol=vol;
|
||
return 0;
|
||
}
|
||
|
||
|
||
// 减少音量
|
||
int mp3_sub_val(int vol)
|
||
{
|
||
vol=g_vol-vol;
|
||
if(vol>MP3_VOL_MAX) vol=MP3_VOL_MAX;
|
||
else if(vol<0) vol=0;
|
||
|
||
g_vol=vol;
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
// 获取音量
|
||
int mp3_get_vol(void)
|
||
{
|
||
return g_vol;
|
||
}
|
||
|
||
|