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

📄 mp3.cpp

📁 EM8511s中使用的mp3播放器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "mp3.h"// 1 to enable verbose debug output#define MP3_VERBOSE	0#if 0static void debug_break (void){}#define ASSERT(exp)					((void)((exp)?1:(printf ("ASSERT failed: line %d, file %s\n", __LINE__,__FILE__), debug_break(), 0)))#define DEBUGMSG(cond,printf_exp)	((void)((cond)?(printf printf_exp),1:0))#else#define ASSERT(exp)#define DEBUGMSG(cond,printf_exp)#endif#define MP3_STATE_INIT					0#define MP3_STATE_DECODING_FILE			1	#define MP3_SUBSTATE_GET_MP3_BUFFER	0	#define MP3_SUBSTATE_GET_PCM_BUFFER	1	#define MP3_SUBSTATE_DECODE_DATA	2	#define MP3_SUBSTATE_PUT_PCM_1		3	#define MP3_SUBSTATE_PUT_PCM_2		4#define MP3_STATE_DECODING_BUFFER		2#define MP3_STATE_EOF					3MP3Decoder::MP3Decoder (){	DEBUGMSG (1, ("MP3Decoder::MP3Decoder\n"));	m_CallbackTable.fclose = 0;	Init ();	resetEqualizer (&m_Equalizer);}MP3Decoder::~MP3Decoder (){	DEBUGMSG (1, ("MP3Decoder::~MP3Decoder\n"));	if (m_handle)	{		ASSERT (m_CallbackTable.fclose);		m_CallbackTable.fclose (m_handle, m_CallbackTable.context);	}}MP3_DECODER_ERROR MP3Decoder::EnableMP3BufferQ (RMint32 enable){	m_enableMP3Q = enable;	return MP3_DECODER_ERROR_NO_ERROR;}MP3_DECODER_ERROR MP3Decoder::Init (void){	DEBUGMSG (1, ("MP3Decoder::Init\n"));	if (m_handle)	{		if (m_CallbackTable.fclose)			m_CallbackTable.fclose (m_handle, m_CallbackTable.context);	}	m_handle = 0;	m_CallbackTable.context = 0;	m_CallbackTable.fopen = 0;	m_CallbackTable.fseek = 0;	m_CallbackTable.ftell = 0;	m_CallbackTable.fread = 0;	m_CallbackTable.fclose = 0;	m_CallbackTable.addref = 0;	m_CallbackTable.release = 0;	m_CallbackTable.info = 0;	m_CallbackTable.putPCM = 0;	m_CallbackTable.getPCM = 0;	m_CallbackTable.getMP3 = 0;	m_State = MP3_STATE_INIT;	m_MP3DataUsed = 0;	m_pcmbuffer = 0;	m_mp3buffer = 0;	m_TotalBytesProcessed = 0;	m_mutePCM = 0;	m_enableMP3Q = 0;	return MP3_DECODER_ERROR_NO_ERROR;}MP3_DECODER_ERROR MP3Decoder::InitCallbackTable (MP3_CALLBACK_TABLE *pCallbackTable){	DEBUGMSG (1, ("MP3Decoder::InitCallbackTable\n"));	m_CallbackTable.context = pCallbackTable->context;	m_CallbackTable.fopen = pCallbackTable->fopen;		m_CallbackTable.fseek = pCallbackTable->fseek;		m_CallbackTable.ftell = pCallbackTable->ftell;		m_CallbackTable.fread = pCallbackTable->fread;	m_CallbackTable.fclose = pCallbackTable->fclose;	m_CallbackTable.addref = pCallbackTable->addref;	m_CallbackTable.release = pCallbackTable->release;	m_CallbackTable.info = pCallbackTable->info;	m_CallbackTable.putPCM = pCallbackTable->putPCM;	m_CallbackTable.getPCM = pCallbackTable->getPCM;	m_CallbackTable.getMP3 = pCallbackTable->getMP3;	return MP3_DECODER_ERROR_NO_ERROR;}MP3_DECODER_ERROR MP3Decoder::DecodeFile (RMint8 *filename){	DEBUGMSG (1, ("MP3Decoder::DecodeFile (%s)\n", filename));	ASSERT (m_handle == 0);	ASSERT (m_CallbackTable.fopen);#if 0	// XXX code disabled ...	// purpose: check that this really is an mp3 file	// why disabled? this method is crappy - what is a better method?	RMint32 length = strlen (filename);	if (filename[length-4] != '.')	{		return MP3_DECODER_ERROR_NOT_A_MP3_FILE;	}	if ((filename[length-3] != 'm') && (filename[length-3] != 'M'))	{		return MP3_DECODER_ERROR_NOT_A_MP3_FILE;	}	if ((filename[length-2] != 'p') && (filename[length-2] != 'P'))	{		return MP3_DECODER_ERROR_NOT_A_MP3_FILE;	}	if (filename[length-1] != '3')	{		return MP3_DECODER_ERROR_NOT_A_MP3_FILE;	}#endif	ASSERT (m_CallbackTable.fopen);	m_handle = m_CallbackTable.fopen (filename, m_CallbackTable.context);	ASSERT (m_handle);	if (m_handle == 0)	{		return MP3_DECODER_ERROR_NOT_A_MP3_FILE;	}		mad_stream_init (&m_Stream);	mad_frame_init (&m_Frame);	mad_synth_init (&m_Synth);	mad_timer_reset (&m_mp3Timer);	ASSERT (m_MP3DataUsed == 0);	m_MP3DataUsed = 0;	m_State = MP3_STATE_DECODING_FILE;	m_SubState = MP3_SUBSTATE_GET_MP3_BUFFER;	ASSERT (m_CallbackTable.fseek);	ASSERT (m_CallbackTable.ftell);	m_CallbackTable.fseek (m_handle, 0, SEEK_END, m_CallbackTable.context);	m_filelength = m_CallbackTable.ftell (m_handle, m_CallbackTable.context);	ASSERT ((RMint32)m_filelength > 0);	DEBUGMSG (1, ("MP3 filelength: %d bytes\n", (int)m_filelength));	m_CallbackTable.fseek (m_handle, 0, SEEK_SET, m_CallbackTable.context);	m_mp3Q.reset ();	m_eof = 0;	return MP3_DECODER_ERROR_NO_ERROR;}MP3_DECODER_ERROR MP3Decoder::Schedule (){	RMint32 n;	RMuint32 ok;	MP3_BUFFER *pqueuedbuffer;	if (m_State == MP3_STATE_INIT)	{		DEBUGMSG (MP3_VERBOSE, ("MP3Decoder::Schedule (MP3_STATE_INIT)\n"));		return MP3_DECODER_ERROR_NO_ERROR;	}	else if (m_State == MP3_STATE_EOF)	{		return MP3_DECODER_ERROR_FILE_DONE;	}	switch (m_SubState)	{	case MP3_SUBSTATE_GET_MP3_BUFFER:		DEBUGMSG (MP3_VERBOSE, ("MP3Decoder::Schedule (MP3_SUBSTATE_GET_MP3_BUFFER)\n"));		ASSERT (m_mp3buffer == 0);		ASSERT (m_CallbackTable.getMP3);		// shall we get another buffer or is one already queued?		pqueuedbuffer = m_mp3Q.dequeue ();		if (pqueuedbuffer)		{			m_mp3buffer = pqueuedbuffer->buffer;			m_mp3length = pqueuedbuffer->length;			ok = 0;			ASSERT (m_CallbackTable.release);			ASSERT (m_mp3buffer);		}		else		{			ok = m_CallbackTable.getMP3 (&m_mp3buffer, &m_mp3length, m_CallbackTable.context);			ASSERT (m_CallbackTable.addref);			m_CallbackTable.addref (m_mp3buffer, m_CallbackTable.context);			ASSERT (m_CallbackTable.fread);			ASSERT (m_handle);			m_mp3length = m_CallbackTable.fread (m_handle, m_mp3buffer, m_mp3length, m_CallbackTable.context);		}		if (ok == 0)		{			m_pmp3 = m_mp3buffer;			m_TotalBytesProcessed += m_mp3length;			if (m_mp3length == 0)			{				mad_synth_finish (&m_Synth);					mad_frame_finish (&m_Frame);				mad_stream_finish (&m_Stream);				ASSERT (m_handle);				ASSERT (m_CallbackTable.fclose);				m_CallbackTable.fclose (m_handle, m_CallbackTable.context);				m_handle = 0;				m_State = MP3_STATE_EOF;				return MP3_DECODER_ERROR_FILE_DONE; 			}			else			{				m_SubState = MP3_SUBSTATE_GET_PCM_BUFFER;			}			mad_stream_buffer (&m_Stream, m_pmp3, m_mp3length);		}		break;	case MP3_SUBSTATE_GET_PCM_BUFFER:			DEBUGMSG (MP3_VERBOSE, ("MP3Decoder::Schedule (MP3_SUBSTATE_GET_PCM_BUFFER)\n"));		ASSERT (m_pcmbuffer == 0);		ASSERT (m_CallbackTable.getPCM);		if (m_CallbackTable.getPCM (&m_pcmbuffer, &m_pcmlength, m_CallbackTable.context) == 0)		{			ASSERT (m_pcmlength >= (1152 * 4));			ASSERT (m_CallbackTable.addref);			m_CallbackTable.addref (m_pcmbuffer, m_CallbackTable.context);			m_SubState = MP3_SUBSTATE_DECODE_DATA;		}		break;	case MP3_SUBSTATE_DECODE_DATA:		DEBUGMSG (MP3_VERBOSE, ("MP3Decoder::Schedule (MP3_SUBSTATE_DECODE_DATA)\n"));		// decode one mp3 frame				if (m_MP3DataUsed)		{			n = sizeof (m_MP3Data) - m_MP3DataUsed;			if ((RMint32)m_mp3length < n)				n = m_mp3length;			memcpy (m_MP3Data + m_MP3DataUsed, m_pmp3, n);			m_pBufferStart = m_MP3Data + m_MP3DataUsed;			m_MP3DataUsed += n;			ASSERT (m_MP3Data[0] == 0xff);			ASSERT ((m_MP3Data[1] & 0xf0) == 0xf0);			mad_stream_buffer (&m_Stream, m_MP3Data, m_MP3DataUsed);			do			{				m_Stream.error = MAD_ERROR_NONE;				mad_frame_decode (&m_Frame, &m_Stream);				if (m_Stream.error != MAD_ERROR_NONE)				{					if (MAD_RECOVERABLE (m_Stream.error))					{						m_mutePCM = MUTE_TIMEOUT;						DEBUGMSG (1, ("recoverable mp3 frame error: 0x%08lx\n", m_Stream.error));						m_decodeError = 1;						continue;					}				}				break;			} while (1);			if (m_Stream.error == MAD_ERROR_BUFLEN || m_Stream.buffer == 0)			{				ASSERT (n == (RMint32)m_mp3length);				n = m_Stream.bufend - m_Stream.next_frame;				memmove (m_MP3Data, m_Stream.next_frame, n);				m_MP3DataUsed = n;				if (m_mp3buffer)				{					ASSERT (m_CallbackTable.release);					ASSERT (m_mp3buffer);					m_CallbackTable.release (m_mp3buffer, m_CallbackTable.context);					m_mp3buffer = 0;				}				ASSERT (m_pcmbuffer);				ASSERT (m_CallbackTable.release);				m_CallbackTable.release (m_pcmbuffer, m_CallbackTable.context);				m_pcmbuffer = 0;				m_SubState = MP3_SUBSTATE_GET_MP3_BUFFER;				return MP3_DECODER_ERROR_NO_ERROR;			}			ASSERT (m_Stream.error == MAD_ERROR_NONE);			MP3_DECODE_INFO mp3info;			mp3info.NumberOfBitsPerSample = 16;			mp3info.NumberOfChannels = MAD_NCHANNELS(&m_Frame.header);			mp3info.SamplesPerSecond = m_Frame.header.samplerate;			DEBUGMSG (0, ("mp3info: %lu bits/sample\n", mp3info.NumberOfBitsPerSample));			DEBUGMSG (0, ("mp3info: %lu channels\n", mp3info.NumberOfChannels));			DEBUGMSG (0, ("mp3info: %lu samples/second\n", mp3info.SamplesPerSecond));			if (m_CallbackTable.info)				m_CallbackTable.info (MP3_MSG_MP3_DECODE_INFO, &mp3info, m_CallbackTable.context);			Equalize (&m_Frame, &m_Equalizer);						mad_synth_frame (&m_Synth, &m_Frame, (short*)m_pcmbuffer);			m_SubState = MP3_SUBSTATE_PUT_PCM_2;			return MP3_DECODER_ERROR_NO_ERROR;		}				do		{			m_Stream.error = MAD_ERROR_NONE;			mad_frame_decode (&m_Frame, &m_Stream);			if (m_Stream.error != MAD_ERROR_NONE)			{				if (MAD_RECOVERABLE (m_Stream.error))				{

⌨️ 快捷键说明

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