?? mp3.cpp
字號(hào):
#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)) {
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -