📄 sndmsad.cpp
字号:
// --------------------------------------------------------------------------// Name: sndulaw.cpp// Purpose:// Date: 08/11/1999// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999// CVSID: $Id: sndmsad.cpp,v 1.10 2005/09/23 12:47:51 MR Exp $// wxWindows licence// --------------------------------------------------------------------------#include "wx/wxprec.h"#ifndef WX_PRECOMP #include "wx/defs.h" #include "wx/memory.h" #include "wx/log.h"#endif#include "wx/mmedia/sndbase.h"#include "wx/mmedia/sndfile.h"#include "wx/mmedia/sndpcm.h"#include "wx/mmedia/sndmsad.h"// --------------------------------------------------------------------------// wxSoundFormatMSAdpcm// --------------------------------------------------------------------------wxSoundFormatMSAdpcm::wxSoundFormatMSAdpcm() : m_srate(22050){ m_ncoefs = 0; m_coefs_len = 0; m_coefs = NULL;}wxSoundFormatMSAdpcm::~wxSoundFormatMSAdpcm(){ if (m_ncoefs) { wxUint16 i; for (i=0;i<m_ncoefs;i++) delete[] m_coefs[i]; delete[] m_coefs; } }void wxSoundFormatMSAdpcm::SetSampleRate(wxUint32 srate){ m_srate = srate;}wxUint32 wxSoundFormatMSAdpcm::GetSampleRate() const{ return m_srate;}void wxSoundFormatMSAdpcm::SetChannels(wxUint16 nchannels){ m_nchannels = nchannels;}wxUint16 wxSoundFormatMSAdpcm::GetChannels() const{ return m_nchannels; }void wxSoundFormatMSAdpcm::SetCoefs(wxInt16 **WXUNUSED(coefs), wxUint16 ncoefs, wxUint16 coefs_len){ wxUint16 i; if (m_ncoefs) { for (i=0;i<m_ncoefs;i++) delete[] (m_coefs[i]); delete[] m_coefs; } // TODO: Add some memory checking here m_coefs = new wxInt16 *[ncoefs]; for (i=0;i<ncoefs;i++) m_coefs[i] = new wxInt16[coefs_len]; m_ncoefs = ncoefs; m_coefs_len = coefs_len;}void wxSoundFormatMSAdpcm::GetCoefs(wxInt16 **& coefs, wxUint16& ncoefs, wxUint16& coefs_len) const{ coefs = m_coefs; ncoefs = m_ncoefs; coefs_len = m_coefs_len;}void wxSoundFormatMSAdpcm::SetBlockSize(wxUint16 block_size){ m_block_size = block_size;}wxUint16 wxSoundFormatMSAdpcm::GetBlockSize() const{ return m_block_size;}wxSoundFormatBase *wxSoundFormatMSAdpcm::Clone() const{ wxSoundFormatMSAdpcm *adpcm = new wxSoundFormatMSAdpcm(); adpcm->m_srate = m_srate; adpcm->SetCoefs(m_coefs, m_ncoefs, m_coefs_len); adpcm->m_nchannels = m_nchannels; adpcm->m_block_size = m_block_size; return adpcm;}wxUint32 wxSoundFormatMSAdpcm::GetTimeFromBytes(wxUint32 bytes) const{ return 2 * bytes / (m_nchannels * m_srate);}wxUint32 wxSoundFormatMSAdpcm::GetBytesFromTime(wxUint32 time) const{ return time * m_nchannels * m_srate / 2;}bool wxSoundFormatMSAdpcm::operator !=(const wxSoundFormatBase& frmt2) const{ const wxSoundFormatMSAdpcm *adpcm = (const wxSoundFormatMSAdpcm *)&frmt2; if (frmt2.GetType() != wxSOUND_MSADPCM) return true; return (adpcm->m_srate != m_srate) && (adpcm->m_nchannels != m_nchannels);}// --------------------------------------------------------------------------// wxSoundStreamMSAdpcm// --------------------------------------------------------------------------wxSoundStreamMSAdpcm::wxSoundStreamMSAdpcm(wxSoundStream& sndio) : wxSoundStreamCodec(sndio){ // PCM converter m_router = new wxSoundRouterStream(sndio); m_got_header = false; m_stereo = false;}wxSoundStreamMSAdpcm::~wxSoundStreamMSAdpcm(){ delete m_router;}wxSoundStream& wxSoundStreamMSAdpcm::Read(void *WXUNUSED(buffer), wxUint32 WXUNUSED(len)){ m_snderror = wxSOUND_NOCODEC; m_lastcount = 0; return *this;}static wxInt16 gl_ADPCMcoeff_delta[] = { 230, 230, 230, 230, 307, 409, 512, 614, 768, 614, 512, 409, 307, 230, 230, 230};wxUint32 wxSoundStreamMSAdpcm::DecodeMonoADPCM(const void *in_buffer, void *out_buffer, wxUint32 in_len){ wxUint8 *ADPCMdata; wxInt16 *PCMdata; AdpcmState *state; wxUint32 out_len; ADPCMdata = (wxUint8 *)in_buffer; PCMdata = (wxInt16 *)out_buffer; state = &m_state[0]; #define GET_DATA_16(i) i = *ADPCMdata++, i |= ((wxUint32)(*ADPCMdata++) << 8)#define GET_DATA_8(i) i = (*ADPCMdata++) out_len = 0; while (in_len != 0) { if (m_next_block == 0) { GET_DATA_8(state->predictor); GET_DATA_16(state->iDelta); GET_DATA_16(state->samp1); GET_DATA_16(state->samp2); state->coeff[0] = state->coeff[1] = m_coefs[0][ state->predictor ]; *PCMdata++ = state->samp2; *PCMdata++ = state->samp1; in_len -= 7; out_len += 4; m_next_block = m_block_size; continue; } while (in_len != 0 && m_next_block != 0) { wxUint8 nib[2]; GET_DATA_8(nib[0]); nib[1] = (nib[0] >> 4) & 0x0f; nib[0] &= 0x0f; Nibble(nib[0], state, &PCMdata); Nibble(nib[1], state, &PCMdata); in_len -= 4; out_len += 4; m_next_block -= 4; } } return out_len;#undef GET_DATA_16#undef GET_DATA_8}wxUint32 wxSoundStreamMSAdpcm::DecodeStereoADPCM(const void *in_buffer, void *out_buffer, wxUint32 in_len){ wxUint8 *ADPCMdata; wxInt16 *PCMdata; AdpcmState *state0, *state1; wxUint32 out_len; ADPCMdata = (wxUint8 *)in_buffer; PCMdata = (wxInt16 *)out_buffer; state0 = &m_state[0]; state1 = &m_state[1]; #define GET_DATA_16(i) i = *ADPCMdata++, i |= ((wxUint32)(*ADPCMdata++) << 8)#define GET_DATA_8(i) i = (*ADPCMdata++) out_len = 0; while (in_len != 0) { if (!m_next_block) { GET_DATA_8(state0->predictor); GET_DATA_8(state1->predictor); GET_DATA_16(state0->iDelta); GET_DATA_16(state1->iDelta); GET_DATA_16(state0->samp1); GET_DATA_16(state1->samp1); GET_DATA_16(state0->samp2); GET_DATA_16(state1->samp2); *PCMdata++ = state0->samp2; *PCMdata++ = state1->samp2; *PCMdata++ = state0->samp1; *PCMdata++ = state1->samp1; in_len -= 14; out_len += 8; m_next_block = m_block_size; continue; } while (in_len != 0 && m_next_block > 0) { wxUint8 nib[2]; GET_DATA_8(nib[0]); nib[1] = (nib[0] >> 4) & 0x0f; nib[0] &= 0x0f; Nibble(nib[0], state0, &PCMdata); Nibble(nib[1], state1, &PCMdata); in_len -= 4; out_len += 4; m_next_block -= 4; } } return out_len;#undef GET_DATA_16#undef GET_DATA_8}void wxSoundStreamMSAdpcm::Nibble(wxInt8 nyb, AdpcmState *state, wxInt16 **out_buffer){ wxUint32 new_delta; wxInt32 new_sample; // First: compute the next delta value new_delta = (state->iDelta * gl_ADPCMcoeff_delta[nyb]) >> 8; // If null, minor it by 16 if (!new_delta) new_delta = 16; // Barycentre new_sample = (state->samp1 * state->coeff[0] + state->samp2 * state->coeff[1]) / 256; // Regenerate the sign if (nyb & 0x08) nyb -= 0x10; new_sample += state->iDelta * nyb; // Samples must be in [-32767, 32768] if (new_sample < -32768) new_sample = -32768; else if (new_sample > 32767) new_sample = 32767; state->iDelta = new_delta; state->samp2 = state->samp1; state->samp1 = new_sample; *(*out_buffer)++ = new_sample;}wxSoundStream& wxSoundStreamMSAdpcm::Write(const void *buffer, wxUint32 len){ wxUint8 *out_buf; wxUint32 new_len; // TODO: prealloc the output buffer out_buf = new wxUint8[len*2]; if (!m_stereo) new_len = DecodeMonoADPCM(buffer, out_buf, len); else new_len = DecodeStereoADPCM(buffer, out_buf, len); m_router->Write(out_buf, new_len); m_lastcount = len; m_snderror = wxSOUND_NOERROR; delete[] out_buf; return *this;}wxUint32 wxSoundStreamMSAdpcm::GetBestSize() const{ return m_sndio->GetBestSize() / 2;}bool wxSoundStreamMSAdpcm::SetSoundFormat(const wxSoundFormatBase& format){ if (format.GetType() != wxSOUND_MSADPCM) { m_snderror = wxSOUND_INVFRMT; return false; } wxSoundFormatPcm pcm; wxSoundFormatMSAdpcm *adpcm; wxUint16 ncoefs, coefs_len; wxSoundStreamCodec::SetSoundFormat(format); adpcm = (wxSoundFormatMSAdpcm *)m_sndformat; adpcm->GetCoefs(m_coefs, ncoefs, coefs_len); if (!ncoefs) { wxLogError(wxT("Number of ADPCM coefficients must be non null")); return false; } pcm.SetSampleRate(adpcm->GetSampleRate()); pcm.SetBPS(16); pcm.SetChannels(adpcm->GetChannels()); pcm.Signed(true); pcm.SetOrder(wxBYTE_ORDER); m_stereo = (adpcm->GetChannels() == 2); m_block_size = adpcm->GetBlockSize(); m_next_block = 0; m_router->SetSoundFormat(pcm); return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -