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

📄 player.c

📁 WAV 数字输出播放器
💻 C
📖 第 1 页 / 共 2 页
字号:
//Player.c
#include <string.h> //memcmp
#include <stdio.h>	//sprintf
#include "SPI_SD.h"
#include "Player.h"
#include "I2S.h"

BYTE databuffer[512];
ULONG CachedSectorAddress;	//DataBuffer address

BYTE playbuffer[512];

//FAT information
BYTE FATType;			//0:FAT12, 1:FAT16
ULONG SectPerClust;		//Sectors in Cluster
ULONG RootDirEntrys; 	//Entrys in Root Sector
ULONG FATStartSect;		//Sector, FAT starts
ULONG DIRStartSect;		//Sector, Root Dir starts
ULONG DataStartSect;	//Sector, Data Area starts
FILEINFO WAVFiles[32];	//max 32 wave file can be played.

//Music Information
ULONG MusicNum;			//Playing Musics Number, from 1
ULONG TotalMusics;		//Total WAV File Num, from 1
ULONG CurrentClust;		//Playing Cluster
ULONG StartSectofClust;	//First Sector in current Playing Cluster
ULONG CurrentSectinClust;	//Playing Sector in Playing Cluster
ULONG SectorCounter;	//Counter for Sector in cluster, from 0,  < SectPerClust
ULONG RemainingSect;	//Sector remain in current music
ULONG PlayedSect;		//Sector Played in current music
						//These are 512bytes/128samples/2.9ms

//Basics of Operation
//Sector: 512Byte block, reading minimum unit from SD card.
//Cluster: 64 Sector = 32KB block in SD card.
//FAT sectors: Cluster address listing table. 256 index in one sector.
// 3 minutes of wave file size is about 31MB, it contains > 1000 cluster.

//reading one Sector needs 1.4ms.
//One Sector, 512Byte is consumed in 2.9ms.
//So reading cluster between playing can cause glitch.

//CBs will store Cluster chain listing.
// if Cluster chain is 0x0004 to 0x0024, 0x0045 to 0x0208
//	CBs[0].Start_Cluster = 0x0004
//	CBs[0].End_Cluster = 0x0024
//	CBs[1].Start_Cluster = 0x0045
//	CBs[1].End_Cluster = 0x0208

// Pros:So there are no FAT sector lookup when playing music.
// Cons:too much flagmented, chains > 128 file can not be played. maybe never happen by NORMAL operation
CLUSTERBLOCK CBs[128];
WORD CurrentCBIndex;

//DMA Flag, controlled by I2S.c
extern BYTE DMA_Flag_A;
//DMA Buffer, exists in I2S.c
extern WORD dci1TxBuffA[512] __attribute__((space(dma)));
extern WORD dci1TxBuffB[512] __attribute__((space(dma)));
//0x 00:00 buffer
char MinSec[10];

BYTE Player_Init(void)
{
	BYTE ret = 0;
	CachedSectorAddress = 0;
	
	memset(WAVFiles,0x00,sizeof(WAVFiles));

	//read FAT information, store into local variables	
	ret = read_FAT_info();
		
	if (ret != 0) return ret;
	
	//search wave files.
	ret = search_WAV(32);

	TotalMusics = ret;
	MusicNum = 1;
	//do simple sort, by file name
	SortMusic();
	//just initializing variables: set again at Player_GotoMusicHead
	CurrentClust = 0;
	CurrentSectinClust = 0;
	RemainingSect = 0;
	PlayedSect = 0;
		
	return ret;
}

void Player_NusicName(char * dest)
{
	memcpy(dest, WAVFiles[MusicNum - 1].fname, 8);	
}	
DWORD Player_FileSize(void)
{
	return WAVFiles[MusicNum -1].fsize;	
}	

UINT Player_MusicNum(void)
{
	return (UINT)MusicNum; 	
}	

//For starting info
void Player_TotalMinSec(char * dest)
{
	memset(MinSec,0x00,sizeof(MinSec));
	
	//return mm:ss as Total minutes:second
	UINT TotalSecond = 0;
	UINT Minutes = 0;
	UINT Seconds = 0;
	
	TotalSecond = ((WAVFiles[MusicNum -1].fsize)>>10) / 176;	
	Minutes = (UINT)(TotalSecond / 60);
	Seconds = TotalSecond % 60;
	
	sprintf(&MinSec[0],"%02u ", (UINT)(MusicNum & 0x00FF));
	sprintf(&MinSec[3],"%02u", Minutes);
	sprintf(&MinSec[5],":");
	sprintf(&MinSec[6],"%02u", Seconds);
	
	memcpy(dest, MinSec, 8);
}	

//Playing info, erapsed min:sec
void Player_MinSec(char * dest)
{
	memset(MinSec,0x00,sizeof(MinSec));
	
	//return mm:ss as played minutes:second
	UINT PlayedSecond = 0;
	UINT Minutes = 0;
	UINT Seconds = 0;
	
	PlayedSecond = (PlayedSect * 30) >> 10 ;	
	Minutes = (UINT)(PlayedSecond / 60);
	Seconds = PlayedSecond % 60;
	
	sprintf(&MinSec[0],"%02u ", (UINT)(MusicNum & 0x00FF));
	sprintf(&MinSec[3],"%02u", Minutes);
	sprintf(&MinSec[5],":");
	sprintf(&MinSec[6],"%02u", Seconds);
	
	memcpy(dest, MinSec, 8);
}	


void Player_GotoMusicHead(ULONG Music)
{
	WORD SearchingClust = 0;
	WORD NextClust = 0;
	
	//Go to Starting Cluster
	CurrentClust = WAVFiles[Music - 1].org_clust;
	//Get First Sector Address in Cluster
	StartSectofClust = (CurrentClust -2) * SectPerClust + DataStartSect;
	//Current Sector is starting Sector in Cluster
	CurrentSectinClust = StartSectofClust;
	//SectorCounter is 0
	SectorCounter = 0;
	//All sector is remaining
	RemainingSect = ((WAVFiles[Music - 1].fsize) >> 9);
	//Nothing Played yet
	PlayedSect = 0;
	
	//Get Cluster Listing
	memset(CBs, 0x00, sizeof(CBs));
	CurrentCBIndex = 0;
	
	CBs[CurrentCBIndex].Start_Clust = WAVFiles[Music-1].org_clust;
	SearchingClust = CBs[CurrentCBIndex].Start_Clust;
	while(CurrentCBIndex < 128 - 1 )
	{
		NextClust = GetnextClusterByFAT(SearchingClust);
		if (NextClust == (SearchingClust + 1))
		{
			//continuous cluster.
			SearchingClust += 1;
		}
		else
		{
			//case, end of cluster chain
			if ((NextClust == 0xFFFF)||(NextClust == 0x0000))
			{
				CBs[CurrentCBIndex].End_Cluster = SearchingClust;
				break;
			}
			//jump to another location
			else
			{
				CBs[CurrentCBIndex].End_Cluster = SearchingClust;
				CBs[CurrentCBIndex+1].Start_Clust = NextClust;
				CBs[CurrentCBIndex+1].End_Cluster = NextClust;	//avoid missing link
				CurrentCBIndex++;
			}
		}
	}
	CurrentCBIndex = 0;	//reset cluster-block index.
}	

void Player_Stop(void)
{
	//Stop SPDIF Stream
	initI2sBuff();	
	i2s_stop();
	//Player goes to first music, first Cluster, first sector
	MusicNum = 1;
	Player_GotoMusicHead(MusicNum);
}
void Player_Start(void)
{
	dma0_start();	//restart DMA
	//start SPDIF Stream
	i2s_start();
}	

void Player_Pause(void)
{
	//SPDIF Stream is set to all zero. keep stream.
	initI2sBuff();
}	

void Player_FF(void)
{
	//go to next music
	MusicNum += 1;
	if (MusicNum > TotalMusics)
	{
		MusicNum = TotalMusics;
	}
	//goto head of music
	Player_GotoMusicHead(MusicNum);
}

void Player_Prev(void)
{
	//go to previous music
	MusicNum -= 1;
	if (MusicNum < 1) 
	{
		MusicNum = 1;
	}
	//goto head of music
	Player_GotoMusicHead(MusicNum);
}	

BYTE Player_Play(void)
{
	ULONG TailFillerSize = 0;
	int i = 0;
	BYTE ret = 0;
	BYTE ToContinue = 1;	//initially, continue mode
	
	ret = SD_Read_Single_Block(CurrentSectinClust * 512, playbuffer);

	//Modify Head and Tail sector
	if (PlayedSect == 0)	//This is first sector, includes headder
	{
		//fill WAVE headder with 0x00
		memset(playbuffer, 0x00, 44);
	}
	if (RemainingSect < 1)	//now this is last sector.
	{
		//Fill tail of sector with 0x00
		TailFillerSize = (WAVFiles[MusicNum - 1].WaveSize + 44) % 512;
		TailFillerSize &= 0x000001FF;	//limit 512 to avoid miss-fill. just in case..
		memset(playbuffer + (512 - TailFillerSize), 0x00, (512 - TailFillerSize));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -