659 lines
19 KiB
C
659 lines
19 KiB
C
#include "mp3play.h"
|
||
#include "dac.h"
|
||
#include "delay.h"
|
||
#include "ftfile.h"
|
||
#include "mymem.h"
|
||
#include "rtthread.h"
|
||
#include "stm32f4xx.h"
|
||
#include "string.h"
|
||
#include "usart.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; }
|