?? mp3_play.c
字號:
#include"sys_config.h"
#include"lrc/lrc.h"
extern struct LrcStructHead_s LrcStructHead; /* Gloable struct variable to record the lyric info */
/* Use to record the time tag info */
extern uint8 lrcbuffer[sizeof(struct LrcStruct_s) * MAXITEM];
/* Use to record the lyric data */
extern uint8 lrcdatbuf[MAXLRCDATSIZE];
extern volatile uint8 key_value;
/* enum for ICON */
enum IconTag
{
Playing,Pause,RepetAll,RepetOne,Shuffle,Time,Music,Speaker
};
/* Long name buffer and flag */
extern unsigned char LongNameBuffer[MAX_LONG_NAME_SIZE];
extern unsigned char LongNameFlag;
/* indicate if the file system is FAT32 , ortherwise it is FAT16, note FAT12 is not supported */
extern BYTE FAT32_Enable;
extern WORD SectorsPerClust;//每簇扇區數
extern WORD FirstDataSector;//第一個數據扇區數
//struct FileInfoStruct FileInfo;//文件信息
struct direntry MusicInfo; /* Music file information, 32Bytes short directory record, contain the short name and others */
//void (*BootLoaderEntry)(void) = 0xf800; /* boot loader entry, bootloader size: 2048Bytes */
uint16 totalsongs; /* total number of songs*/
uint8 type; /* current song's file type, mp3 wma mid or wav */
extern uint8 lrc; /* Gloable variable to indicate wether the songs has a lyric file, 1 means have */
extern uint8 HanziEnable; /* Gloable variable to indicate wether the firmware are exist, and 1 means exist */
uint8 Volume_Table[32] PROGMEM = \
{
255,225,206,188,161,145,130,116,103,91,80,70,61,53,46,40,35,30,26,22,19,16,13,11,9,7,5,4,3,2,1,0
};
uint8 track[128]; /* stroe the information of songs (bit set indicate songs has been played) */
void ClearTrackInfo() /* cleare the array track[128] */
{
uint8 i;
for(i=0;i<128;i++)track[i] = 0;
}
uint8 SetTrack(uint16 songs)/* set the track bit, return 1 means the song has been played */
{
uint8 byte_offset;
uint8 bit_offset;
songs--;
byte_offset = songs/8;
bit_offset = songs%8;
if(track[byte_offset] & (1<<bit_offset))return 1;
else
{
track[byte_offset] |= 1<<bit_offset;
return 0;
}
}
/*void nextline()
{
USART_putchar(0x0d);
USART_putchar(0x0a);
}*/
void Delay(uint16 n)//延時
{
while(n--)asm("nop");
}
uint8 PlayMusicwithKey()//播放音樂函數,一旦執行不會退出
{
uint16 count; //數據計數 //data counting
uint8 i; //循環變量 //loop variable
uint16 j; //循環變量 //loop variable
DWORD p; //簇指示值 //cluster
DWORD totalsect; //文件擁有的扇區數 //cotain the total sector number of a file
uint16 leftbytes; //剩余字節 //cotain the left bytes number of a file //the last cluster usually not fully occupied by the file
uint8 *buffer; //緩沖 //buffer
DWORD sector; //扇區 //recor the current sector to judge the end sector
uint8 flag; //播放/暫停標志 //flag of pause
uint16 vol= DEFAULT_VOLUME;//初始音量,應與vs1003函數里的初始音量相同 //default volume
uint8 vol_temp;
uint16 songs=1; //默認放第一首歌 //play the fist songs by default
uint16 songs_cnt = 0; //how many songs have been played
uint8 mode=0; //單曲重復 //repet all by default
unsigned long rand_val;
uint8 total[6]; /* for total songs indication */
uint8 current[12]; /* Current songs number */
uint16 temp = totalsongs;
uint8 time[6];
uint16 decodetime;
uint8 volume[3];
uint8 min,sec;
struct LrcStruct_s * LrcStruct_pp;
uint16 lrcaddr;
/* the display buffer (characters) */
#define MAX_LRC_DISP 52
uint8 lrcdata[MAX_LRC_DISP];
uint8 lrcDisFlag = 0; /* indicate if it need display lyric on the lcd */
uint8 lrcCnt = 0; /* lrcdata buffer count */
ClearTrackInfo();
//printf_P(PSTR("\r\nCurrent mode : "));
/*switch(mode)
{
case REPET_ALL: printf_P(PSTR("repet all"));break;
case REPET_ONE:printf_P(PSTR("repet one"));break;
case RANDOM:printf_P(PSTR("shuffle"));break;
}*/
if(totalsongs==0)//如果沒有歌曲則異常退出 //if no music file return
{
lcdClrDisBuf();
LCD_print12_P(0,20,PSTR("File not found!"));
lcdUpdateDisplay();
return;
}
/**********************************************/
for(i=0;i<5;i++)
{
total[4-i] = temp%10;
temp /= 10;
}
for(i=0;i<5;i++)
{
if(total[i])break;
}
for(j=0;j<5-i;j++)
{
total[j] = total[j+i] + 0x30;
}
total[j] = 0;
/**********************************************/
vol_temp = 15;
volume[0] = vol_temp/10 + 0x30;
volume[1] = vol_temp%10 +0x30;
volume[2] = '\0';
/**********************************************/
//Timer1_Initial();//啟動定時器,用于產生隨機函數的種子 //initialize the timer
next://下一首歌的起始地方 //label for "goto"
if(mode==RANDOM)//隨機播放歌曲 //if the mode is shuffle the songs
{
songs_cnt++;
if(songs_cnt == totalsongs && totalsongs<1025)
{
ClearTrackInfo();
songs_cnt = 0;
}
rand_val = TCNT1;
Delay((random() && 0x00ff));
rand_val <<= 16;
rand_val += TCNT1;
srandom(rand_val);
if(totalsongs>1024)
{
songs = (uint16)(((random()/214749)*(uint32)totalsongs)/10000)+1;//隨機產生歌曲序號 //create random song number
}
while(totalsongs<1025)
{
songs = (uint16)(((random()/214749)*(uint32)totalsongs)/10000)+1;//隨機產生歌曲序號 //create random song number
if(SetTrack(songs) == 0)break;
}
}
count=0;//清基數 //clear count
flag=1;
if(type != MID)VS1003B_Fill2048Zero();
lrcDisFlag = 0; /* clear the flag in case some lyric is not displayed of last songs */
lrcCnt = 0; /* clear the lrc count, maybe more lyric will display on one screen, for sometimes cpu do not have time to display the last one */
//decodetime = -1;
//lcdInit(); /* the connection of the 3310lcd is not stable, so we reinitialize it every time */
VS1003B_SoftReset();//soft reset //in case of playing wma files//軟件復位
#if FIX_DIRECTORY
Search((unsigned char *)(MUSIC_PATH),&MusicInfo,&songs,&type); //找到相應的文件 //find the file
#else
Search(&lrcaddr,&MusicInfo,&songs,&type); //找到相應的文件 //find the file
#endif
/* here we use lrcaddr to get the record address in the eeprom which the file placed */
for(j=0;j<MAX_LONG_NAME_SIZE/2;j++) /* cut off the extension, only leave the name*/
{
if(((unsigned int*)LongNameBuffer)[j] == 0)
{
((unsigned int*)LongNameBuffer)[j-4] = 0;
break;
}
}
/****************************************************/
time[0] = '0';
time[1] = '0';
time[2] = ':';
time[3] = '0';
time[4] = '0';
time[5] = '\0';
decodetime = -1; /* for display the lyric which is at time 00:00 */
/******************************************************/
temp = songs;
for(i=0;i<5;i++)
{
current[4-i] = temp%10;
temp /= 10;
}
for(i=0;i<5;i++)
{
if(current[i])break;
}
for(j=0;j<5-i;j++)
{
current[j] = current[j+i] + 0x30;
}
current[j++] = '/';
for(i=0;i<6;i++)
{
current[j+i] = total[i];
}
/********************************************************/
lcdClrDisBuf();
switch(type)
{
case MP3:LCD_print12_P(0,0,PSTR("mp3"));break;
case WMA:LCD_print12_P(0,0,PSTR("wma"));break;
case MID:LCD_print12_P(0,0,PSTR("mid"));break;
case WAV:LCD_print12_P(0,0,PSTR("wav"));break;
default:break;
}
Print_ICON_12(18,0,Playing);
LCD_print12(30,0,current);
switch(mode)
{
case REPET_ALL:Print_ICON_12(72,0,RepetAll);break;
case REPET_ONE:Print_ICON_12(72,0,RepetOne);break;
case RANDOM :Print_ICON_12(72,0,Shuffle);break;
default:break;
}
/*****************************************************/
//LCD_print12(30,36,time);
//LCD_print12(72,36,volume);
//Print_ICON_12(60,36,Speaker);
//Print_ICON_12(0,12,Music);
/******************************************************/
if(LongNameFlag)
{
if(HanziEnable) /* if HanziEnable, convert the long name from unicode to GBK */
{
buffer = malloc(MAX_LONG_NAME_SIZE);
if(buffer == 0)return 1;
i = 0;
j=0;
while(1)
{
temp = ((unsigned int *)LongNameBuffer)[i++];
/* you may confused about following code, because at previous we set "." to 0 for lry search*/
if(temp == 0 )
{
buffer[j++] = '.';
while(1) /*copy the extention */
{
temp = ((unsigned int *)LongNameBuffer)[i++];
if(temp == 0)break; /* end */
buffer[j++] = (uint8)temp;
}
break;
}
else if (temp<0x80)
{
buffer[j++]=(uint8)temp;
}
else if(temp<0x4e00)
{
*((unsigned int*)&(buffer[j])) = "?";
j+=2;
}
else if(temp<0x9fa6)
{
if(Unicode_to_GBK((unsigned char *)&temp))return 1;
*((unsigned int*)&(buffer[j])) = temp;
j+=2;
}
else
{
*((unsigned int*)&(buffer[j])) = "?";
j+=2;
}
}
buffer[j] = 0;
LCD_print12(12,12,buffer);
//LCD_print_unicode12(12,12,(unsigned int *)LongNameBuffer);
}
else
{
LCD_print12_P(0,12,PSTR("-- --By bozai\nFirmware lost!"));
}
}
else /* short name */
{
for(j=0;j<8;j++)
{
if(MusicInfo.deName[j]==0x20)break;
LongNameBuffer[j]=MusicInfo.deName[j];
}
//LongNameBuffer[j++]='\0';
LongNameBuffer[j++]='.';
count = j+3;
for(count=0;count<3;count++)LongNameBuffer[j+count]=MusicInfo.deExtension[count];
LongNameBuffer[j+count]='\0';
if(HanziEnable)LCD_print12(12,12,LongNameBuffer);
else
{
LCD_print12_P(0,12,PSTR(" --By Michael Firmware lost!"));
}
}
/*************************************************************/
LCD_print12(30,36,time);
LCD_print12(72,36,volume);
Print_ICON_12(60,36,Speaker);
Print_ICON_12(0,12,Music);
lcdUpdateDisplay();
/**************************************************************/
// printf_P(PSTR("\r\nNow playing "));
// printf_P(PSTR("%s :"),current);
if(LongNameFlag && HanziEnable)
{
// printf_P(PSTR("%s"),buffer);
free(buffer);
}
else
{
for(j=0;j<8;j++)
{
if(MusicInfo.deName[j]==0x20)break;
USART_putchar(MusicInfo.deName[j]);
}
USART_putchar('.');
for(j=0;j<3;j++)
{
//if(MusicInfo.deName[j]==0x20)break;
USART_putchar(MusicInfo.deExtension[j]);
}
}
/**************************************************************/
#if FIX_DIRECTORY
LrcProc(LongNameBuffer,LongNameFlag);
#else
LrcProc(LongNameBuffer,lrcaddr,LongNameFlag); /* search lyc file */
/* lrcaddr indicate the record address of eeprom */
/* first search the current folder then the default */
#endif
LrcStruct_pp = LrcStructHead.header;
/**************************************************************/
p = MusicInfo.deStartCluster+(((unsigned long)MusicInfo.deHighClust)<<16);//讀文件首簇 //the first cluster of the file
totalsect = MusicInfo.deFileSize/512; //計算扇區數 //calculate the total sectors
leftbytes = MusicInfo.deFileSize%512; //計算剩余的字節數 //calculate the left bytes
i=0;
sector=0;
if(lrc && HanziEnable) /* clear the previous time area */
{
if(LrcStruct_pp->time/1000 == 0 && LrcStruct_pp != 0)/* see if it has lyric at time 00:00 */
{
decodetime = -1; /* for display the lyric which is at time 00:00 */
}
else
{
decodetime = 0; /* otherwise, it will not flush screen when 00:00, then you can see the filename and other info for 1 second */
}
LCD_print12_P(36,36,PSTR(" "));
lcdClrDisBuf();
}
while(1)
{
for(;i<SectorsPerClust;i++) //一個簇 //a cluster
{
buffer=malloc(512);
FAT_LoadPartCluster(p,i,buffer);//讀一個扇區 //read a sector
count=0;
while(count<512)
{
if(VS1003B_NeedData() && flag) //根據需要送數據 //send data honoring DREQ
{
VS1003B_Write32B(&buffer[count]);
count += 32;
if(sector == totalsect && count >= leftbytes) //如果文件已結束 //if this is the end of the file
{
if(type == MID)//waiting the midi file was decoded
VS1003B_Fill2048Zero();
i=SectorsPerClust;
break;
}//文件結束 //file ended
if(count == 511){break;}//512字節送完跳出 //break if a sector was sent
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -