📄 mp3player.c
字号:
#include "COMM.h"
u16 f_kbps=0;//歌曲文件位率
//进度条,时间,比特率 等事实信息显示控制
void MP3_PROG(u32 pos,u32 lenth)
{
static u16 playtime=0;//播放时间标记
float propos=0;
u16 time=0;// 时间变量
u16 temp=0;
if(f_kbps==0xffff)//未更新过
{
playtime=0;
f_kbps=GetHeadInfo(); //获得比特率
}
POINT_COLOR=GREEN;
BACK_COLOR=MP3COLOR4;
if(lenth)
{
propos=(float)pos*512/lenth;//得到百分比
if(propos>1)propos=1;//限制propos的范围
}else return;//文件为空,返回
if(f_kbps)//对位率不为0 的文件
{
time=(lenth/f_kbps)/125;//总时间
time=propos*time; //得到当前比例时间
}else time=GetDecodeTime(); //对位率为0的文件,得到解码时间
propos=propos*180;//得到实际长度
TFT_ProBar((u8)propos);//显示进度条
if(time!=playtime)//1s时间到,更新显示数据
{
temp=GetHeadInfo(); //获得比特率
if(temp)
{
f_kbps=temp;//更新KBPS
time=(((float)lenth/f_kbps)/125)*(propos/180);//更新时间
}
playtime=time;//更新时间
//显示播放时间
TFT_ShowNum(87,72,time/60,12,0); //分钟
TFT_ShowChar(99,72,':',12,0);
TFT_ShowNum(105,72,time%60,12,0);//秒钟
TFT_ShowChar(117,72,'/',12,0);
//显示总时间
if(f_kbps)time=(lenth/f_kbps)/125;//得到秒钟数 (文件长度(字节)/(1000/8)/比特率=持续秒钟数
else time=0;//非法位率
TFT_ShowNum(123,72,time/60,12,0);//显示总分钟数
TFT_ShowChar(135,72,':',12,0);
TFT_ShowNum(141,72,time%60,12,0);//显示总秒钟数
//显示位率
TFT_Show3Num(168,72,f_kbps,12,0);
TFT_ShowChar(186,72,'k',12,0);
TFT_ShowChar(192,72,'b',12,0);
TFT_ShowChar(198,72,'p',12,0);
TFT_ShowChar(204,72,'s',12,0);
}
}
u8 *MP3_VOL[5]={" 音量 "," 高音 "," 低音 ","左声道","右声道"};
u8 *MP3_OTHER[3]={"频谱显示","歌词显示","退出播放"};
//检测数据合法性
void VOL_Data_Check(u8 volx,u8 *datax)
{
switch(volx)
{
case 0: //主音量
if(*datax>64)*datax=64;
if(*datax<1)*datax=1;
break;
case 1: //高音
case 2: //低音
if(*datax>15)*datax=15;
if(*datax<1)*datax=1;
break;
case 3: //左声道
case 4: //右声道
if(*datax>32)*datax=32;
if(*datax<1)*datax=1;
break;
case 5://超重音
if(*datax>1)*datax=1;
break;
}
}
//显示数据
void MP3_MsgBox_Data(u16 *sysmsg,u8 menu,u8 key)
{
u16 volx;
BACK_COLOR=MP3COLOR6;//背景色
POINT_COLOR=RED;
TFT_Fill(58,259,138,275,MP3COLOR6);//抹掉上次数据
switch(menu)
{
case 0://音效模式
if(key==7)INITDSP++;
else if(key==8)
{
if(INITDSP==0)INITDSP=4;//数据合法性判断
else INITDSP--;
}
if(INITDSP>4)INITDSP=0;
TFT_ShowNum(82,259,INITDSP+1,16,0);//显示数据
break;
case 1:
volx=(*sysmsg>>2)&0x07;
if(key==7)voltemp[volx]++;
else if(key==8)voltemp[volx]--;
VOL_Data_Check(volx,&voltemp[volx]);//数据合法性判断
TFT_ShowNum(82,259,voltemp[volx],16,0);//显示数据
break;
case 2:
volx=(*sysmsg>>5)&0x03;
if(key==7){volx++;if(volx>2)volx=0;}
else if(key==8)
{
if(volx)volx--;
else volx=2;
}
*sysmsg&=0XFF9F;
*sysmsg|=volx<<5;
Show_Str(58,259,MP3_OTHER[volx],0);
break;
}
//第三栏信息更新
BACK_COLOR=MP3COLOR3;//背景色
POINT_COLOR=GRED;
for(volx=0;volx<3;volx++)TFT_ShowNum(26+60*volx,47,voltemp[volx],16,0);//显示音量信息
TFT_ShowNum(206,47,INITDSP+1,16,0);//显示音效信息
}
//显示MP3目录表的信息
//*menu :先前的目录号
//*sysmsg :但前运行标志信息
//curmenu:当前目录号
void MP3_MsgBox_Menu(u16 *sysmsg,u8 *menu,u8 curmenu)
{
u16 temp;
BACK_COLOR=MP3COLOR6;
//显示音效部分
temp=(*sysmsg>>9)&0x01;
if(curmenu==0)
{
POINT_COLOR=RED;
if(*menu==curmenu)//再次点击
{
temp=!temp;
*sysmsg&=0XFDFF;
*sysmsg|=temp<<9;
}
*menu=curmenu;
}
else POINT_COLOR=GREEN;
if(temp)Show_Str_Mid(8,227,"存音效",0,48);
else Show_Str_Mid(8,227," 音效 ",0,48);
//显示音量
temp=(*sysmsg>>2)&0x07;
if(curmenu==1)
{
POINT_COLOR=RED;
if(*menu==curmenu)//再次点击
{
temp++;
if(temp>=5)temp=0;
*sysmsg&=0XFFE3;
*sysmsg|=temp<<2;
temp=(*sysmsg>>2)&0x07;
}
*menu=curmenu;
}
else POINT_COLOR=GREEN;
Show_Str_Mid(64,227,MP3_VOL[temp],0,48);
//其他选择
if(curmenu==2)
{
*menu=curmenu;
POINT_COLOR=RED;
}
else POINT_COLOR=GREEN;
Show_Str_Mid(120,227," 其他 ",0,48);
}
//RGB音乐彩灯控制
//val:0~100的数据
void Mus_RGB_LED(u8 rval,u8 gval,u8 bval)
{
float ftemp;
ftemp=(float)MAX_Red/100;
rval=ftemp*rval;//得到红色分量值
ftemp=(float)255/100;
gval=ftemp*gval;//得到红色分量值
bval=ftemp*bval;//得到红色分量值
LED_R=rval;
LED_G=gval;
LED_B=bval;
}
//播放选定的歌曲
//index:当前播放的歌曲索引
//total:总共音乐文件的个数
//关于音乐的几乎所有控制都在这个里面
u8 Mus_Play(FileInfoStruct *FileName,u16 index,u16 total)
{
unsigned long bfactor=0; //物理扇区,绝对地址
unsigned long bcluster=0;//物理簇号
u32 file_pos=0; //记录文件播放的长度
u8 count=0; //扇区计数器,用于换簇
u16 i,n;
u8 key,menux=1;
u8 keycnt; //按键计数器
u8 FFT_LRC=0;//默认FFT
u8 *BUFFER=(u8*)MCUBuffer;//指向JPEG的开始512字节
u8 *spedate=(u8*)MCUBuffer+512;//当前频谱分析的结果寄存器
u8 *topval=(u8*)MCUBuffer+526; //FFT柱的最高点记录表
u8 *flyval=(u8*)MCUBuffer+540; //FFT柱的悬浮点记录表
u8 mark=1; //标记
u8 timer=0; //频谱定时器
u32 topstay1; //最高点频点延时1
u32 topstay2; //最高点频点延时2
//bit0~9用来标记功能 ,默认全部循环
//bit0,1:循环模式;bit2,3,4:音量设置;bit5,6:其他设置
//bit7:超重低音标记;bit8:是否有歌词;bit9:音效存/取标记
u16 sysfun=1;
u16 temp;
u8 forpreclust;//快进快退需要的簇数
timer3_init();//初始化歌词显示定时器
INITDSP=FM24C16_ReadOneByte(30);//调用DSP值
if(INITDSP>4)//未初始化,则初始化
{
INITDSP=0;
for(temp=0;temp<31;temp++)FM24C16_WriteOneByte(temp,0);//全部清空
}else read_dsp(); //已经初始化过了 读取DSP效果
init_pt2314(MP3_Audio);//设置声音
MUS_RGB_Status=FM24C16_ReadOneByte(487);//读取音乐彩灯标志
if(FFT_LRC==0)
{
LED_R=0;
LED_G=0;
LED_B=0;
ENRGB(MUS_RGB_Status);//使能音乐彩灯(如果设置MUS_RGB_Status位的话)
}else ENRGB(0); //关闭彩灯
Read_VS_Set();//读取VS1003的设置
RESTART:
forpreclust=FileName->F_Size/(SectorsPerClust*BytesPerSector*50);//每次前进/后退 2%所需要的簇数
if(forpreclust<2)forpreclust=2;//最少也要两个簇
//fft部分,变量清空
topstay1=0;
topstay2=0;
file_pos=0;
keycnt=0;
f_kbps=0xffff;//文件位率设置为不可能值
count=0; //扇区计数器
bfactor=fatClustToSect(FileName->F_StartCluster);//得到开始簇对应的扇区
bcluster=FileName->F_StartCluster; //得到文件开始簇号
printf("F_StartCluster:%d\n",FileName->F_StartCluster);
//从当前目录下找歌词文件,有,则标记.
if(FindLrcFile(Cur_Dir_Cluster,FileName->F_ShortName))
{
sysfun|=1<<8; //标记有歌词
Lrc_Read_Init(); //初始化歌词读取
}else sysfun&=~(1<<8);//标记没有歌词
Mp3Reset(); //硬复位
Vs1003SoftReset();//软复位VS1003
LoadPatch(); //加载频谱分析代码
Load_Gui_Mp3(sysfun);//加载播放界面
timer=5;//设置到一个不可能的值,初始化信息栏
MP3_MsgBox_Menu(&sysfun,&timer,menux);//加载信息栏
MP3_MsgBox_Data(&sysfun,menux,1); //加载数据
//显示但前文件夹下的歌曲数目,及当前歌曲的索引
BACK_COLOR=MP3COLOR4;
POINT_COLOR=GREEN;
TFT_Show3Num(30,72,index,12,0);
TFT_ShowChar(48,72,'/',12,0);
TFT_Show3Num(54,72,total,12,0);
//显示歌曲标题
POINT_COLOR=WHITE;
Show_Str_Mid(0,24,FileName->F_Name,0x01,240); //显示歌曲名字
//FFT数据清空
for(i=0;i<14;i++)//清空相关数据
{
topval[i]=0;
flyval[i]=0;
spedate[i]=0;
}
key=0;
Pen_Point.Key_Sta=Key_Up;//释放按键
while(1) //播放音乐的主循环
{
if(SD_ReadSingleBlock(bfactor,BUFFER))break;//读取一个扇区的数据
i=0;
count++;//扇区计数器
do //主播放循环
{
while((GPIOC->IDR&MP3_DREQ)==0&&((sysfun&0X0400)==0)) //等待高/进行频谱显示/非暂停
{
if(FFT_LRC==0)//频谱模式
{
if(mark)
{
GetSpec(spedate);//得到频谱数据
if(MUS_RGB_Status==1)Mus_RGB_LED(topval[1],topval[10],topval[7]);//使能了渐变模式
else if(MUS_RGB_Status==2)Mus_RGB_LED(spedate[1],spedate[10],spedate[7]);//使能了跳变模式
MP3_PROG(file_pos,FileName->F_Size);//MP3进度显示/播放时间
}
else TFT_ShowFFT(spedate,topval,flyval,&topstay1,&topstay2);//频谱显示
timer++;
if(timer>=3)//FFT最高的悬浮点控制
{
Top_Delet_FFT(flyval,&topstay1,&topstay2);//删除高端
timer=0;
}
}else //歌词模式
{
if(mark&&sysfun&(1<<8))LyricDisplayCtrl();//存在歌词,则显示
else if(mark==0)MP3_PROG(file_pos,FileName->F_Size);//MP3进度显示/播放时间
//printf("end\n");
}
mark=!mark;
}
if((GPIOC->IDR&MP3_DREQ)!=0&&((sysfun&0X0400)==0)) //非暂停,送数据给VS1003
{
for(n=0;n<32;n++)Vs1003_DATA_Write(BUFFER[i++]);//发送音乐数据
}
if((Pen_Point.Key_Sta==Key_Down||NPEN)&&Pen_Point.Key_LSta)key=Touch_To_Num(3);//得到按键值
if(PEN)//按键松开了,状态改变(状态机)
{
Pen_Point.Key_LSta=1;
keycnt=0;
Pen_Point.Key_Sta=Key_Up;
}
if(key)//有按键按下
{
Pen_Point.Key_LSta=0;
switch(key)
{
case 1://循环模式更改
temp=sysfun&0x03;
temp++;
if(temp>1)temp=0;//只用其中两个,单曲循环/全部循环
//显示循环模式
BACK_COLOR=MP3COLOR4;
POINT_COLOR=GREEN;
TFT_ShowButton(214,72,temp+2);//加载循环模式
sysfun&=0XFFFC;
sysfun|=temp;//更改标志位
break;
case 2://Supper Bass 部分
temp=(sysfun>>7)&0x01;
voltemp[5]=temp;//记录超重低音值
temp=!temp;
init_pt2314(MP3_Audio);//设置生效
//显示超重低音部分
BACK_COLOR=MP3COLOR5;
POINT_COLOR=GRED;
if(temp)Show_Str_Mid(0,102,"Supper Bass",0,240);
else Show_Str_Mid(0,102," ",0,240);//清除显
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -