⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp3_play.c

📁 mega64 + VS1003 + SD卡
💻 C
📖 第 1 页 / 共 2 页
字号:



#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 + -