#include "audiodecoder.h" #include "aulaw.h" #include "adpcm_impl.h" #include "xa_gsm_state.h" #include "fillplugins.h" #include "avm_output.h" #include "utils.h" #include "plugin.h" #include #include #include AVM_BEGIN_NAMESPACE; PLUGIN_TEMP(audiodec); class ADPCM_Decoder : public IAudioDecoder { adpcm_state state; public: ADPCM_Decoder(const CodecInfo& info, const WAVEFORMATEX* wf) :IAudioDecoder(info, wf) { adpcm_init_table(); Flush(); } uint_t GetMinSize() const { return m_pFormat->nBlockAlign * m_pFormat->nChannels; } void Flush() { state.valprev = 0; state.index = 0; } int Convert(const void* in_data, uint_t in_size, void* out_data, uint_t out_size, uint_t* size_read, uint_t* size_written) { uint_t nblocks = in_size / m_pFormat->nBlockAlign; int smpl = 2 * m_pFormat->nBlockAlign / m_pFormat->nChannels - 4 * m_pFormat->nChannels; // 4 bytes per channel int16_t* out_ptr = (int16_t*) out_data; uint_t minosmpl = out_size / (2 * (smpl + 1) * m_pFormat->nChannels); if (nblocks > minosmpl) nblocks = minosmpl; const int* in_ptr = (const int*) in_data; //printf("in: %d al: %d ch: %d ns %d sampl %d\n", // in_size, m_pFormat.nBlockAlign, m_pFormat.nChannels, nblocks, smpl); for (unsigned i = 0; i < nblocks; i++) { for (int c = 0; c < m_pFormat->nChannels; c++) { const int32_t* inp = in_ptr + m_pFormat->nChannels + c; const uint8_t* hdr = (const uint8_t*) (in_ptr + c); state.valprev = (hdr[1] << 8) | hdr[0]; state.index = hdr[2]; if (hdr[3] != 0) { AVM_WRITE("ADPCM_Decoder", "out of sync()\n"); //printf("Data 0x08%x 0x%08x %d\n", in_ptr[c], state.valprev, state.index); } else adpcm_decoder(out_ptr + c, inp, smpl, &state, m_pFormat->nChannels); } in_ptr += m_pFormat->nBlockAlign / sizeof(int); out_ptr += (smpl + 0) * m_pFormat->nChannels; } if (size_read) *size_read = nblocks * m_pFormat->nBlockAlign; if (size_written) *size_written = nblocks * 2 * smpl * m_pFormat->nChannels; //printf("### %d %d\n", *size_read, *size_written); return 0; } }; class AULAW_Decoder : public IAudioDecoder { const short* table; public: AULAW_Decoder(const CodecInfo& info, const WAVEFORMATEX* wf) :IAudioDecoder(info, wf) { table = (info.fourcc == 0x06) ? alaw2short : ulaw2short; } int Convert(const void* in_data, uint_t in_size, void* out_data, uint_t out_size, uint_t* size_read, uint_t* size_written) { uint_t csize = (in_size < out_size / 2) ? in_size : out_size / 2; const uint8_t* in = (const uint8_t*) in_data; short* o = (short*) out_data; short* end = o + csize; while (o < end) *o++ = table[*in++]; if (size_read) *size_read = csize; if (size_written) *size_written = 2 * csize; return 0; } }; class MSGSM_Decoder : public IAudioDecoder { public: MSGSM_Decoder::MSGSM_Decoder(const CodecInfo& info, const WAVEFORMATEX* wf) :IAudioDecoder(info, wf) { GSM_Init(); } virtual uint_t GetMinSize() const { return 640; } virtual int Convert(const void* in_data, uint_t in_size, void* out_data, uint_t out_size, uint_t* size_read, uint_t* size_written) { unsigned num_samples=in_size/65; if(out_size<640*num_samples) num_samples=out_size/640; if(num_samples==0) { if(size_read)*size_read=0; if(size_written)*size_written=0; return -1; } int ocnt=XA_ADecode_GSMM_PCMxM(num_samples*65, num_samples, (char*)in_data, // no const - interface (uint8_t*)out_data, out_size); /* if(format) { format->is_stereo=0;//mono format->freq=local_wf.nSamplesPerSec;//unsure //format->freq=44100; format->valid=OUT_FORMAT_VALID; } */ // if(ocnt