📄 mp3.cpp
字号:
m_mutePCM = MUTE_TIMEOUT; DEBUGMSG (1, ("recoverable mp3 frame error: 0x%08lx\n", m_Stream.error)); m_decodeError = 1; continue; } else { break; } } break; } while (1); if (m_Stream.error == MAD_ERROR_NONE) { 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_1; } else if (m_Stream.error == MAD_ERROR_BUFLEN || m_Stream.buffer == NULL) { n = m_Stream.bufend - m_Stream.next_frame; memmove (m_MP3Data, m_Stream.next_frame, n); m_MP3DataUsed = n; 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; } break; case MP3_SUBSTATE_PUT_PCM_1: DEBUGMSG (MP3_VERBOSE, ("MP3Decoder::Schedule (MP3_SUBSTATE_PUT_PCM_1)\n")); n = (MAD_NCHANNELS(&m_Frame.header)) * (MAD_NSBSAMPLES(&m_Frame.header)) * 32 * sizeof(RMuint16); ASSERT (m_CallbackTable.putPCM); if (m_mutePCM) { memset (m_pcmbuffer, 0, 1152*4); m_mutePCM--; } if (m_CallbackTable.putPCM (m_pcmbuffer, n, m_CallbackTable.context) == 0) { ASSERT (m_CallbackTable.release); ASSERT (m_pcmbuffer); m_CallbackTable.release (m_pcmbuffer, m_CallbackTable.context); m_pcmbuffer = 0; m_SubState = MP3_SUBSTATE_GET_PCM_BUFFER; } break; case MP3_SUBSTATE_PUT_PCM_2: DEBUGMSG (MP3_VERBOSE, ("MP3Decoder::Schedule (MP3_SUBSTATE_PUT_PCM_2)\n")); n = (MAD_NCHANNELS(&m_Frame.header)) * (MAD_NSBSAMPLES(&m_Frame.header)) * 32 * sizeof(RMuint16); ASSERT (m_CallbackTable.putPCM); if (m_mutePCM) { memset (m_pcmbuffer, 0, 1152*4); m_mutePCM--; } if (m_CallbackTable.putPCM (m_pcmbuffer, n, m_CallbackTable.context) == 0) { ASSERT (m_CallbackTable.release); ASSERT (m_pcmbuffer); m_CallbackTable.release (m_pcmbuffer, m_CallbackTable.context); m_pcmbuffer = 0; m_SubState = MP3_SUBSTATE_GET_PCM_BUFFER; n = m_Stream.next_frame - m_pBufferStart; if (n >= 0) { m_pmp3 += n; m_mp3length -= n; m_MP3DataUsed = 0; ASSERT (m_pmp3[0] == 0xff); ASSERT ((m_pmp3[1] & 0xf0) == 0xf0); mad_stream_buffer (&m_Stream, m_pmp3, m_mp3length); } else { m_MP3DataUsed = -n; memmove (m_MP3Data, m_Stream.next_frame, m_MP3DataUsed); m_SubState = MP3_SUBSTATE_GET_PCM_BUFFER; } } break; default: ASSERT (0); break; } // get an mp3 buffer and read data into it RMuint8 *pmp3buffer; RMuint32 mp3bufferlength; if ((m_enableMP3Q) && (m_eof == 0) && m_mp3Q.canqueue ()) { if (m_CallbackTable.getMP3 (&pmp3buffer, &mp3bufferlength, m_CallbackTable.context) == 0) { mp3bufferlength = m_CallbackTable.fread (m_handle, pmp3buffer, mp3bufferlength, m_CallbackTable.context); if (mp3bufferlength) { m_mp3Q.queue (pmp3buffer, mp3bufferlength); ASSERT (m_CallbackTable.addref); m_CallbackTable.addref (pmp3buffer, m_CallbackTable.context); } else m_eof = 1; } } return MP3_DECODER_ERROR_NO_ERROR;}MP3_DECODER_ERROR MP3Decoder::Seek (RMint32 seconds){ if (m_Frame.header.bitrate) { RMint32 byte_rate; RMuint32 seek_position; byte_rate = (RMint32)m_Frame.header.bitrate / 8; seek_position = seconds * byte_rate; if ((RMint32)seek_position > (RMint32)(m_filelength - 4096)) { DEBUGMSG (1, ("can not seek to %d, max is %d\n", (int)seek_position, (int)(m_filelength - 4096))); return MP3_DECODER_ERROR_INVALID_PARAMETER; } DEBUGMSG (1, ("seeking to position byte %d\n", (int)seek_position)); m_CallbackTable.fseek (m_handle, seek_position, SEEK_SET, m_CallbackTable.context); if (m_mp3buffer) { ASSERT (m_CallbackTable.release); m_CallbackTable.release (m_mp3buffer, m_CallbackTable.context); m_mp3buffer = 0; } if (m_pcmbuffer) { ASSERT (m_CallbackTable.release); m_CallbackTable.release (m_pcmbuffer, m_CallbackTable.context); m_pcmbuffer = 0; } // reset internal variables mad_stream_init (&m_Stream); mad_frame_init (&m_Frame); mad_synth_init (&m_Synth); mad_timer_reset (&m_mp3Timer); m_MP3DataUsed = 0; m_State = MP3_STATE_DECODING_FILE; m_SubState = MP3_SUBSTATE_GET_MP3_BUFFER; return MP3_DECODER_ERROR_NO_ERROR; } return MP3_DECODER_ERROR_NOT_IMPLEMENTED;}MP3_DECODER_ERROR MP3Decoder::DecodeBufferStart (void){ DEBUGMSG (1, ("MP3Decoder::DecodeBufferStart ()\n")); ASSERT (m_State == MP3_STATE_INIT); 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_BUFFER; m_SubState = MP3_SUBSTATE_GET_MP3_BUFFER; m_mutePCM = 0; return MP3_DECODER_ERROR_NO_ERROR;}MP3_DECODER_ERROR MP3Decoder::DecodeBuffer (RMuint8 *pBuffer, RMuint32 length){ DEBUGMSG (0, ("MP3Decoder::DecodeBuffer ()\n")); MP3_DECODER_ERROR err; ASSERT (m_State == MP3_STATE_DECODING_BUFFER); ASSERT (m_SubState == MP3_SUBSTATE_GET_MP3_BUFFER); ASSERT (pBuffer); ASSERT (length); m_mp3buffer = pBuffer; m_pmp3 = pBuffer; m_mp3length = length; mad_stream_buffer (&m_Stream, m_pmp3, m_mp3length); m_SubState = MP3_SUBSTATE_GET_PCM_BUFFER; ASSERT (m_CallbackTable.addref); m_CallbackTable.addref (m_mp3buffer, m_CallbackTable.context); m_decodeError = 0; // XXX yuck - this can potentially hang if // the getting a pcm buffer never returns a valid // buffer _or_ if writing the pcm never succeeds while (m_SubState != MP3_SUBSTATE_GET_MP3_BUFFER) { err = Schedule (); ASSERT (err == MP3_DECODER_ERROR_NO_ERROR); } ASSERT (m_SubState == MP3_SUBSTATE_GET_MP3_BUFFER); if (m_decodeError) { ASSERT (0); return MP3_DECODER_ERROR_BAD_MP3_BUFFER; } return MP3_DECODER_ERROR_NO_ERROR;}MP3_DECODER_ERROR MP3Decoder::DecodeBufferEnd (void){ DEBUGMSG (1, ("MP3Decoder::DecodeBufferEnd ()\n")); ASSERT (m_State = MP3_STATE_DECODING_BUFFER); mad_synth_finish (&m_Synth); mad_frame_finish (&m_Frame); mad_stream_finish (&m_Stream); m_State = MP3_STATE_INIT; return MP3_DECODER_ERROR_NO_ERROR;}void MP3Decoder::SetEqualizer (RMint32 Band, RMint32 Gain){ setEqualizer (Band, Gain, &m_Equalizer);}//////////////////////////////////////////////////////////////////////////mp3Q::mp3Q (){}mp3Q::~mp3Q (){}void mp3Q::reset (){ RMint32 i; m_headBusy = 0; m_headFree = &m_Elements[0]; for (i=0; i<MAX_QUEUED_MP3_BUFFERS-1; i++) { m_Elements[i].buffer = 0; m_Elements[i].length = 0; m_Elements[i].next = &m_Elements[i+1]; } m_Elements[i].buffer = 0; m_Elements[i].length = 0; m_Elements[i].next = 0;}RMint32 mp3Q::queue (RMuint8 *pbuffer, RMuint32 length){ // dequeue something from the freeQ MP3_BUFFER *tmp, *p; tmp = m_headFree; if (m_headFree) m_headFree = m_headFree->next; if (tmp == 0) { // no free elements left ASSERT (0); return 1; } tmp->buffer = pbuffer; tmp->length = length; tmp->next = 0; // queue to tail of busyQ p = m_headBusy; if (p) { while (p->next) p = p->next; p->next = tmp; } else { m_headBusy = tmp; } return 0;}MP3_BUFFER *mp3Q::dequeue (void){ MP3_BUFFER *tmp; // dequeue from busyQ tmp = m_headBusy; if (m_headBusy) m_headBusy = m_headBusy->next; // requeue back to freeQ if (tmp) { tmp->next = m_headFree; m_headFree = tmp; } return tmp;}MP3_BUFFER *mp3Q::canqueue (){ return m_headFree;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -