# HG changeset patch # User melanson # Date 1009429783 0 # Node ID 55603340d1b2748677616aef62b383bc3c2d8f5e # Parent 7ebf504c92d615e3f8915c13590fd761c5f3a2f0 implemented open source MS ADPCM decoder diff -r 7ebf504c92d6 -r 55603340d1b2 adpcm.c --- a/adpcm.c Thu Dec 27 02:08:31 2001 +0000 +++ b/adpcm.c Thu Dec 27 05:09:43 2001 +0000 @@ -1,6 +1,11 @@ /* Unified ADPCM Decoder for MPlayer + This file is in charge of decoding all of the various ADPCM data + formats that various entities have created. Details about the data + formats can be found here: + http://www.pcisys.net/~melanson/codecs/ + (C) 2001 Mike Melanson */ @@ -13,13 +18,60 @@ #define LE_16(x) (le2me_16(*(unsigned short *)(x))) #define LE_32(x) (le2me_32(*(unsigned int *)(x))) +// pertinent tables +static int adpcm_step[89] = +{ + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, + 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, + 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, + 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, + 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, + 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, + 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, + 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 +}; + +static int adpcm_index[16] = +{ + -1, -1, -1, -1, 2, 4, 6, 8, + -1, -1, -1, -1, 2, 4, 6, 8 +}; + +static int format_0x62_table[16] = +{ + 1, 3, 5, 7, 9, 11, 13, 15, + -1, -3, -5, -7, -9, -11, -13, -15 +}; + +static int ms_adapt_table[] = +{ + 230, 230, 230, 230, 307, 409, 512, 614, + 768, 614, 512, 409, 307, 230, 230, 230 +}; + +static int ms_adapt_coeff1[] = +{ + 256, 512, 0, 192, 240, 460, 392 +}; + +static int ms_adapt_coeff2[] = +{ + 0, -256, 0, 64, 0, -208, -232 +}; + +// useful macros // clamp a number between 0 and 88 #define CLAMP_0_TO_88(x) if (x < 0) x = 0; else if (x > 88) x = 88; // clamp a number within a signed 16-bit range #define CLAMP_S16(x) if (x < -32768) x = -32768; \ else if (x > 32767) x = 32767; +// clamp a number above 16 +#define CLAMP_ABOVE_16(x) if (x < 16) x = 16; // sign extend a 16-bit value #define SE_16BIT(x) if (x & 0x8000) x -= 0x10000; +// sign extend a 4-bit value +#define SE_4BIT(x) if (x & 0x8) x -= 0x10; void ima_dvi_decode_nibbles(unsigned short *output, int channels, int predictor_l, int index_l, @@ -129,3 +181,91 @@ return IMA_ADPCM_SAMPLES_PER_BLOCK * channels; } + +int ms_adpcm_decode_block(unsigned short *output, unsigned char *input, + int channels) +{ + int current_channel = 0; + int idelta[2]; + int sample1[2]; + int sample2[2]; + int coeff1[2]; + int coeff2[2]; + int stream_ptr = 0; + int out_ptr = 0; + int upper_nibble = 1; + int nibble; + int snibble; // signed nibble + int predictor; + + // fetch the header information, in stereo if both channels are present + coeff1[0] = ms_adapt_coeff1[input[stream_ptr]]; + coeff2[0] = ms_adapt_coeff2[input[stream_ptr]]; + stream_ptr++; + if (channels == 2) + { + coeff1[1] = ms_adapt_coeff1[input[stream_ptr]]; + coeff2[1] = ms_adapt_coeff2[input[stream_ptr]]; + stream_ptr++; + } + + idelta[0] = LE_16(&input[stream_ptr]); + stream_ptr += 2; + SE_16BIT(idelta[0]); + if (channels == 2) + { + idelta[1] = LE_16(&input[stream_ptr]); + stream_ptr += 2; + SE_16BIT(idelta[1]); + } + + sample1[0] = LE_16(&input[stream_ptr]); + stream_ptr += 2; + SE_16BIT(sample1[0]); + if (channels == 2) + { + sample1[1] = LE_16(&input[stream_ptr]); + stream_ptr += 2; + SE_16BIT(sample1[1]); + } + + sample2[0] = LE_16(&input[stream_ptr]); + stream_ptr += 2; + SE_16BIT(sample2[0]); + if (channels == 2) + { + sample2[1] = LE_16(&input[stream_ptr]); + stream_ptr += 2; + SE_16BIT(sample2[1]); + } + + while (stream_ptr < MS_ADPCM_BLOCK_SIZE * channels) + { + // get the next nibble + if (upper_nibble) + nibble = snibble = input[stream_ptr] >> 4; + else + nibble = snibble = input[stream_ptr++] & 0x0F; + upper_nibble ^= 1; + SE_4BIT(snibble); + + predictor = ( + ((sample1[current_channel] * coeff1[current_channel]) + + (sample2[current_channel] * coeff2[current_channel])) / 256) + + (snibble * idelta[current_channel]); + CLAMP_S16(predictor); + sample2[current_channel] = sample1[current_channel]; + sample1[current_channel] = predictor; + output[out_ptr++] = predictor; + + // compute the next adaptive scale factor (a.k.a. the variable idelta) + idelta[current_channel] = + (ms_adapt_table[nibble] * idelta[current_channel]) / 256; + CLAMP_ABOVE_16(idelta[current_channel]); + + // toggle the channel + current_channel ^= channels - 1; + } + + return MS_ADPCM_SAMPLES_PER_BLOCK * channels; +} diff -r 7ebf504c92d6 -r 55603340d1b2 adpcm.h --- a/adpcm.h Thu Dec 27 02:08:31 2001 +0000 +++ b/adpcm.h Thu Dec 27 05:09:43 2001 +0000 @@ -4,29 +4,12 @@ #define IMA_ADPCM_BLOCK_SIZE 0x22 #define IMA_ADPCM_SAMPLES_PER_BLOCK 0x40 -static int adpcm_step[89] = -{ - 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, - 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, - 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, - 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, - 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, - 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, - 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, - 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, - 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 -}; +#define MS_ADPCM_BLOCK_SIZE 256 +#define MS_ADPCM_SAMPLES_PER_BLOCK ((256 - 7) * 2) -static int adpcm_index[16] = -{ - -1, -1, -1, -1, 2, 4, 6, 8, - -1, -1, -1, -1, 2, 4, 6, 8 -}; - -static int format_0x62_table[16] = -{ - 1, 3, 5, 7, 9, 11, 13, 15, - -1, -3, -5, -7, -9, -11, -13, -15 -}; +int ima_adpcm_decode_block(unsigned short *output, unsigned char *input, + int channels); +int ms_adpcm_decode_block(unsigned short *output, unsigned char *input, + int channels); #endif diff -r 7ebf504c92d6 -r 55603340d1b2 codec-cfg.c --- a/codec-cfg.c Thu Dec 27 02:08:31 2001 +0000 +++ b/codec-cfg.c Thu Dec 27 05:09:43 2001 +0000 @@ -212,10 +212,10 @@ "libvorbis", "ffmpeg", "libmad", - "ima4", + "msadpcm", "liba52", "g72x", - "adpcm", + "imaadpcm", NULL }; static char *videodrv[] = { diff -r 7ebf504c92d6 -r 55603340d1b2 codec-cfg.h --- a/codec-cfg.h Thu Dec 27 02:08:31 2001 +0000 +++ b/codec-cfg.h Thu Dec 27 05:09:43 2001 +0000 @@ -30,10 +30,10 @@ #define AFM_VORBIS 10 #define AFM_FFMPEG 11 #define AFM_MAD 12 -#define AFM_IMA4 13 +#define AFM_MSADPCM 13 #define AFM_A52 14 #define AFM_G72X 15 -#define AFM_ADPCM 16 +#define AFM_IMAADPCM 16 #define VFM_MPEG 1 #define VFM_VFW 2 diff -r 7ebf504c92d6 -r 55603340d1b2 dec_audio.c --- a/dec_audio.c Thu Dec 27 02:08:31 2001 +0000 +++ b/dec_audio.c Thu Dec 27 05:09:43 2001 +0000 @@ -278,13 +278,16 @@ // MS-GSM audio codec: sh_audio->audio_out_minsize=4*320; break; -case AFM_IMA4: -case AFM_ADPCM: - // IMA-ADPCM 4:1 audio codec: +case AFM_IMAADPCM: sh_audio->audio_out_minsize=4096; sh_audio->ds->ss_div=IMA_ADPCM_SAMPLES_PER_BLOCK; sh_audio->ds->ss_mul=IMA_ADPCM_BLOCK_SIZE; break; +case AFM_MSADPCM: + sh_audio->audio_out_minsize=4096; + sh_audio->ds->ss_div=MS_ADPCM_SAMPLES_PER_BLOCK; + sh_audio->ds->ss_mul=MS_ADPCM_BLOCK_SIZE; + break; case AFM_MPEG: // MPEG Audio: sh_audio->audio_out_minsize=4608; @@ -503,15 +506,19 @@ sh_audio->i_bps=65*(sh_audio->channels*sh_audio->samplerate)/320; // 1:10 break; } -case AFM_ADPCM: -case AFM_IMA4: { +case AFM_IMAADPCM: // IMA-ADPCM 4:1 audio codec: sh_audio->channels=sh_audio->wf->nChannels; sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; // decodes 34 byte -> 64 short sh_audio->i_bps=IMA_ADPCM_BLOCK_SIZE*(sh_audio->channels*sh_audio->samplerate)/IMA_ADPCM_SAMPLES_PER_BLOCK; // 1:4 break; -} +case AFM_MSADPCM: + sh_audio->channels=sh_audio->wf->nChannels; + sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; + sh_audio->i_bps=MS_ADPCM_BLOCK_SIZE* + (sh_audio->channels*sh_audio->samplerate)/MS_ADPCM_SAMPLES_PER_BLOCK; + break; case AFM_MPEG: { // MPEG Audio: dec_audio_sh=sh_audio; // save sh_audio for the callback: @@ -906,15 +913,22 @@ memcpy(buf,g72x_data.samples,len); break; } - case AFM_ADPCM: - case AFM_IMA4: // IMA-ADPCM 4:1 audio codec: + case AFM_IMAADPCM: { unsigned char ibuf[IMA_ADPCM_BLOCK_SIZE * 2]; // bytes / stereo frame if (demux_read_data(sh_audio->ds, ibuf, - IMA_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels) != + IMA_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels) != IMA_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels) break; // EOF len=2*ima_adpcm_decode_block((unsigned short*)buf,ibuf, sh_audio->wf->nChannels); -// len=2*ima4_decode_block((unsigned short*)buf,ibuf,2*IMA_ADPCM_SAMPLES_PER_BLOCK); + break; + } + case AFM_MSADPCM: + { unsigned char ibuf[MS_ADPCM_BLOCK_SIZE * 2]; // bytes / stereo frame + if (demux_read_data(sh_audio->ds, ibuf, + MS_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels) != + MS_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels) + break; // EOF + len=2*ms_adpcm_decode_block((unsigned short*)buf,ibuf, sh_audio->wf->nChannels); break; } case AFM_AC3: // AC3 decoder diff -r 7ebf504c92d6 -r 55603340d1b2 etc/codecs.conf --- a/etc/codecs.conf Thu Dec 27 02:08:31 2001 +0000 +++ b/etc/codecs.conf Thu Dec 27 05:09:43 2001 +0000 @@ -315,8 +315,13 @@ status working format 0x11 format 0x34616d69 ; "ima4" (MOV files) - driver adpcm - dll "imaadpcm" + driver imaadpcm + +audiocodec msadpcm + info "MS ADPCM" + status working + format 0x2 + driver msadpcm ; =============== WINDOWS DLL's ============== @@ -792,12 +797,12 @@ dll "divxa32.acm" cpuflags mmx -audiocodec msadpcm - info "MS ADPCM" - status working - format 0x2 - driver acm - dll "msadp32.acm" +;audiocodec msadpcm +; info "MS ADPCM" +; status working +; format 0x2 +; driver acm +; dll "msadp32.acm" audiocodec mp3 info "MPEG layer-2, layer-3" @@ -948,14 +953,6 @@ ; driver acm ; dll "vorbis.acm" -audiocodec ima4 - info "IMA4:1" - status working - comment "MONO only" - format 0x34616d69 ; "ima4" (MOV files) - driver ima4 - dll "ima4.c" - audiocodec vivoaudio info "Vivo G.723/Siren Audio Codec" status working