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

📄 audio_mp3drv.c

📁 凌阳SPCE3200 系统开发板随机自带源程序。共安排了32个子目录
💻 C
字号:
//=============================================================
// 文件名称:	Audio_MP3Drv.c
// 功能描述:	mp3播放
// 维护记录:	2007-01-16	v1.0
//=============================================================

#include "SPCE3200_Register.h"
#include "SPCE3200_Constant.h"
#include ".\MP4_Codec\MP4_Codec.h"

#define	 D_VolSel_0				  0									//single channel will be 1/32 of max volume
#define	 D_VolSel_1				  0x1<<6							//1/8
#define	 D_VolSel_2				  0x2<<6							//1/2
#define	 D_VolSel_3				  0x3<<6							//1

//MP3_Status
#define	D_MP3_Play		0x0001
#define	D_MP3_Pause		0x0002
#define	D_MP3_Repeat	0x0004
#define D_MP3_Speed		0x0008
#define D_MP3_Data_End	0x0010
#define D_MP3_Encode	0x0020
#define	D_MP3_Buf_Empty	0x0040
#define	D_MP3_PCM_Empty	0x0080

#define SP4_BITSTREAM_FILL_BATCH 512

//Function definition
void SP4_FillSoftFIFO(unsigned short *TempPCM);
void SP4_EnableSoftCh(unsigned int Samplerate);
void SP4_read_bs(unsigned char *MP3_bs_buf, int temp_wp, int fill_size);
void SP4_read_bitstream(unsigned char *MP3_bs_buf, int *wp);
int SP4_get_bs_free_bytes(int wp);

//Variable definition
unsigned short	*PCMAddress;
unsigned short	*FIFOAddress;
unsigned char *g_pSP4_MP3Address;//unsigned short 	*Address;
//for KF
unsigned short  *KFAudioEnd;

unsigned short	SP4_FIFOArray[4096];
unsigned char	MP3_bs_buf[SP4_MP3_BITSTREAM_BUFFER_SIZE];
short			PCM_buf[1152*2];
short 			SP4_TempPCM[2048];	// half a SPU buffer
unsigned char decoder_instance[SP4_MP3_DECODER_WORK_SPACE];

unsigned short	SP4_FIFOCounter=0, SP4_FIFO_Offset=0;
unsigned char	SP4_TempData=0;//unsigned short	SP4_TempData=0;
unsigned 		samplerate, bitrate;
int 			wp, rp;
int 			error_msg;
int				space;
int 			pcm_cnt;
int 			pcm_wp, pcm_rp;
int 			temp_wp, temp_rp, TempPCM_ready, SP4_MP3Need_PCM_Flag;
int 			Fill_count;
int 			MP3_Status;


extern unsigned int MP4_State_Flag;

void SP4_FillSoftFIFO(unsigned short *TempPCM)
{
	unsigned short TempValue;
	unsigned short TempCounter;

	for(TempCounter=0;TempCounter<2048;TempCounter++)	// for stereo
	{
		TempValue = TempPCM[TempCounter];
		TempValue ^= 0x8000;
		SP4_FIFOArray[TempCounter+SP4_FIFO_Offset] = TempValue;
	}

	if(SP4_FIFOCounter != 0)
	{
		SP4_FIFO_Offset = 0;
		SP4_FIFOCounter = 0;
	}
	else
	{
		SP4_FIFO_Offset += 2048;
		SP4_FIFOCounter = 1;
	}
}

void SP4_EnableSoftCh(unsigned int Samplerate)
{
	unsigned int TempValue;
	*P_DAC_BUFFER_SA = 0;
	*P_DAC_FIFOBA_LOW = ((unsigned int)SP4_FIFOArray);				// Set start address of buffer for SPU soft channel
	*P_DAC_FIFOBA_HIGH = ((unsigned int)SP4_FIFOArray) >> 16;
	if((MP3_Status&D_MP3_Speed) == 0)
	{
		TempValue = 27000000/Samplerate - 1;					//Set sampling rate of current PCM file
		*P_DAC_SAMPLE_CLK = TempValue;
	}
	*P_DAC_INT_STATUS = 0xC000 | 0x0004 | 0x0003;			//Enable software channel as stereo, 8Kbytes buffer
	*P_DAC_MODE_CTRL2  = (0x0608 | D_VolSel_1 | 0x1003); // for both channel
	MP4_State_Flag |=  MASK_MP4_AUDIO_READY;
}

unsigned int *MP3_Addr;
void SP4_Play_MP3(void)
{	
	*P_DAC_INT_STATUS = 0;			//Stop SPU software channel
	*P_DAC_MODE_CTRL2  = 0;
	MP3_Status &= ~(D_MP3_Play | D_MP3_Pause);	//Reset MP3 status
	
	mp3_decoder_init(decoder_instance, MP3_bs_buf, 1);	
	g_pSP4_MP3Address = (unsigned char *)MP3_Addr; //MP3_Addr;
	
	SP4_FIFOCounter=0;
	SP4_FIFO_Offset=0;
	wp = 0;
	pcm_rp=0;
	pcm_wp=0;
	temp_wp=0;
	TempPCM_ready=0;
	
	// Fill buffer for playing. Data must be enough at first time.
	SP4_read_bs(MP3_bs_buf, wp, SP4_MP3_BITSTREAM_BUFFER_SIZE-512);
	wp = SP4_MP3_BITSTREAM_BUFFER_SIZE - 512;
	
	Fill_count = 0;
	SP4_MP3Need_PCM_Flag = 1;
	MP3_Status |= D_MP3_Play;
}


void SP4_MP3_Service_Loop(void)
{	
	if( ((MP3_Status&D_MP3_Play) != 0) && ((MP3_Status&D_MP3_Pause) == 0) )
	{
		if(SP4_MP3Need_PCM_Flag == 1)			//Check whether first or last half of FIFO need data
		{
			if(pcm_wp == pcm_rp)		//Check whether PCM buffer is empty. If yes, decode next frame.
			{
				pcm_cnt = mp3_decoder_run(decoder_instance,wp,PCM_buf+pcm_wp);	//Decode 1 frame and put data from pcm_rp.
				pcm_wp += pcm_cnt*2;
				if(pcm_wp >= 1152*2)
					pcm_wp -= 1152*2;
			}
			
			do
			{
				SP4_TempPCM[temp_wp] = PCM_buf[pcm_rp];
				pcm_rp ++;
				if(pcm_rp >= 1152*2)
					pcm_rp -= 1152*2;
				temp_wp ++;	// unit is words	//Write pointer of SP4_TempPCM buffer, which spares data for SPU FIFO
				if(temp_wp >= 2048)
				{
					temp_wp = 0;
					TempPCM_ready = 1;
					Fill_count++;
			
					break;						//Stop filling SP4_TempPCM buffer when it is full 
				}
			}while(pcm_rp != pcm_wp);			//or data in PCM buffer is empty.

			error_msg = mp3_errno(decoder_instance);
			if(error_msg != 0)
			{
				if((MP3_Status&D_MP3_Repeat) != 0)
				{
					SP4_Play_MP3();
 					SP4_MP3_Service_Loop();
					SP4_MP3_Service_Loop();
					SP4_MP3_Service_Loop();
					SP4_MP3_Service_Loop();
					SP4_MP3_Service_Loop();
					SP4_MP3_Service_Loop();
					SP4_MP3_Service_Loop();
					SP4_MP3_Service_Loop();
 				}					
			}
			
			space = SP4_get_bs_free_bytes(wp);
			if(space > SP4_BITSTREAM_FILL_BATCH)	//Check whether no. of data in MP3 buffer is lower than threshold
			{
					if(((char *)KFAudioEnd - (char *)g_pSP4_MP3Address) > 0)
					{
                        SP4_read_bitstream(MP3_bs_buf, &wp);//If yes, fill new data.
					}
					else
					{
                        MP4_State_Flag  |= MASK_MP4_AUDIO_NEXT_KF;
					}
			}
			
			if(TempPCM_ready == 1)			//Check whether data in TempPCM buffer is enough to load to SPU FIFO
			{
				TempPCM_ready = 0;
				if(Fill_count < 3)
					SP4_FillSoftFIFO(SP4_TempPCM);	//Fill data in SPU in the beginning. Spare 4K bytes data for 1st SPU IRQ.
				else
				{	
					SP4_MP3Need_PCM_Flag = 0;					
				}
				if(Fill_count == 3)
				{
					bitrate = mp3_get_bitrate(decoder_instance);
					samplerate = mp3_get_sampling_rate(decoder_instance);
					SP4_EnableSoftCh(samplerate);	// Start playing on SPU software channel
					SP4_MP3Need_PCM_Flag = 0;
				}
			}
		}
	}
}


void SP4_Stop_MP3(void)
{
	*P_DAC_INT_STATUS = 0;
	*P_DAC_MODE_CTRL2  = 0;
	MP3_Status = 0;
}

void SP4_Pause_MP3(void)
{
	*P_DAC_INT_STATUS = 0;
	*P_DAC_MODE_CTRL2  = 0;
	MP3_Status |= D_MP3_Pause;
	MP4_State_Flag &= ~MASK_MP4_AUDIO_READY;
}

void SP4_Resume_MP3(void)
{
	Fill_count = 0;
	SP4_MP3Need_PCM_Flag = 1;
	MP3_Status &= ~D_MP3_Pause;
	MP3_Status |= D_MP3_Play;
}


void SP4_Repeat_MP3(void)
{
	MP3_Status |= D_MP3_Repeat;
}

void SP4_Cancel_Repeat_MP3(void)
{
	MP3_Status &= ~D_MP3_Repeat;
}

int SP4_bs_byte_size(int wp)
{
	int size;
	int rp = mp3_decoder_read_index(decoder_instance);
	size = wp - rp;
	if(size < 0)
		size += SP4_MP3_BITSTREAM_BUFFER_SIZE;
	return(size);
}

int SP4_get_bs_free_bytes(int wp)
{
	int space;
	int rp = mp3_decoder_read_index(decoder_instance);
	space = rp - wp;
	if(space < 0)
		space += SP4_MP3_BITSTREAM_BUFFER_SIZE;
	return(space);
}

void SP4_read_bs(unsigned char *MP3_bs_buf, int temp_wp, int fill_size)
{
	int count;
	for(count=0;count<fill_size;count++)
	{
		SP4_TempData = *g_pSP4_MP3Address;
		g_pSP4_MP3Address += 1;
		if( (count+temp_wp) >= SP4_MP3_BITSTREAM_BUFFER_SIZE )
			MP3_bs_buf[count+temp_wp-SP4_MP3_BITSTREAM_BUFFER_SIZE] = SP4_TempData;
		else
			MP3_bs_buf[count+temp_wp] = SP4_TempData;
	}
}


void SP4_read_bitstream(unsigned char *MP3_bs_buf, int *wp)
{
	int space;
	int temp_wp;
	int remains;
	
	remains = (char *)KFAudioEnd - (char *)g_pSP4_MP3Address;  //remaining audio data in a KF.
	//r = remains%2;
	temp_wp = *wp;
	space = SP4_get_bs_free_bytes(temp_wp);

	while(space > SP4_BITSTREAM_FILL_BATCH)
	{
      if (remains > SP4_BITSTREAM_FILL_BATCH)
	    {
		      SP4_read_bs(MP3_bs_buf, temp_wp, SP4_BITSTREAM_FILL_BATCH);	//fill data in MP3_bs_buf
		      space -= SP4_BITSTREAM_FILL_BATCH;
		      temp_wp += SP4_BITSTREAM_FILL_BATCH;
		      if(temp_wp >= SP4_MP3_BITSTREAM_BUFFER_SIZE)
			        temp_wp -= SP4_MP3_BITSTREAM_BUFFER_SIZE;
	        
	        remains -=SP4_BITSTREAM_FILL_BATCH;
	    }
	    else
	    {
	    	  if (remains > 0)
	    	  {
	    	      SP4_read_bs(MP3_bs_buf, temp_wp, remains);	//fill data in MP3_bs_buf
		          space -= remains;
		          temp_wp += remains;
		          if(temp_wp >= SP4_MP3_BITSTREAM_BUFFER_SIZE)
			            temp_wp -= SP4_MP3_BITSTREAM_BUFFER_SIZE;
		          
		          remains -=remains;
		          break;
	    	  }
	    	  else
	    	  {
	    	  	  break;
	    	  }
	    }
  }
  *wp = temp_wp;
}


⌨️ 快捷键说明

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