From 9505de02504cf9d3ce28425f615533eafd4d4fc1 Mon Sep 17 00:00:00 2001 From: melanson Date: Tue, 1 Jan 2002 20:04:54 +0000 Subject: added initial support for format 0x61 ADPCM (sounds good, but still pops) git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@3934 b3059339-0415-0410-9bf9-f77b7e298cf2 --- adpcm.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ adpcm.h | 7 ++++++- codec-cfg.c | 1 + codec-cfg.h | 3 ++- dec_audio.c | 22 +++++++++++++++++++- etc/codecs.conf | 6 ++++++ 6 files changed, 98 insertions(+), 3 deletions(-) diff --git a/adpcm.c b/adpcm.c index 37bbd64461..8239dfd9c5 100644 --- a/adpcm.c +++ b/adpcm.c @@ -298,6 +298,68 @@ int ms_adpcm_decode_block(unsigned short *output, unsigned char *input, return (block_size - (MS_ADPCM_PREAMBLE_SIZE * channels)) * 2; } +// note: This decoder assumes the format 0x61 data always comes in +// mono flavor +int fox61_adpcm_decode_block(unsigned short *output, unsigned char *input) +{ + int i; + int out_ptr = 0; + + int predictor; + int index; + int nibble; + int sign; + int delta; + int diff; + int step; + + predictor = output[out_ptr++] = LE_16(&input[0]); + index = input[2]; + + // iterate through and decode the rest of the bytes + for (i = 4; i < FOX61_ADPCM_BLOCK_SIZE; i++) + { + nibble = (input[i] >> 4) & 0x0F; + + step = adpcm_step[index]; + sign = nibble & 8; + delta = nibble & 7; + diff = step >> 3; + if (delta & 4) diff += step; + if (delta & 2) diff += step >> 1; + if (delta & 1) diff += step >> 2; + if (sign) + predictor -= diff; + else + predictor += diff; + CLAMP_S16(predictor); + output[out_ptr++] = predictor; + index += adpcm_index[nibble]; + CLAMP_0_TO_88(index); + + nibble = input[i] & 0x0F; + + step = adpcm_step[index]; + sign = nibble & 8; + delta = nibble & 7; + diff = step >> 3; + if (delta & 4) diff += step; + if (delta & 2) diff += step >> 1; + if (delta & 1) diff += step >> 2; + if (sign) + predictor -= diff; + else + predictor += diff; + CLAMP_S16(predictor); + output[out_ptr++] = predictor; + index += adpcm_index[nibble]; + CLAMP_0_TO_88(index); + } + + return FOX61_ADPCM_SAMPLES_PER_BLOCK; +} + + // note: This decoder assumes the format 0x62 data always comes in // stereo flavor int fox62_adpcm_decode_block(unsigned short *output, unsigned char *input, diff --git a/adpcm.h b/adpcm.h index d20dbc5717..939f7656b6 100644 --- a/adpcm.h +++ b/adpcm.h @@ -10,6 +10,11 @@ #define MS_ADPCM_SAMPLES_PER_BLOCK \ ((sh_audio->wf->nBlockAlign - MS_ADPCM_PREAMBLE_SIZE) * 2) +#define FOX61_ADPCM_PREAMBLE_SIZE 4 +#define FOX61_ADPCM_BLOCK_SIZE 0x200 +#define FOX61_ADPCM_SAMPLES_PER_BLOCK \ + (((FOX61_ADPCM_BLOCK_SIZE - FOX61_ADPCM_PREAMBLE_SIZE) * 2) + 1) + // pretend there's such a thing as mono for this format #define FOX62_ADPCM_PREAMBLE_SIZE 8 #define FOX62_ADPCM_BLOCK_SIZE 0x400 @@ -20,7 +25,7 @@ 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, int block_size); +int fox61_adpcm_decode_block(unsigned short *output, unsigned char *input); int fox62_adpcm_decode_block(unsigned short *output, unsigned char *input, int channels); - #endif diff --git a/codec-cfg.c b/codec-cfg.c index 0af0c91abe..909607ff3f 100644 --- a/codec-cfg.c +++ b/codec-cfg.c @@ -219,6 +219,7 @@ static short get_driver(char *s,int audioflag) "liba52", "g72x", "imaadpcm", + "fox61adpcm", "fox62adpcm", NULL }; diff --git a/codec-cfg.h b/codec-cfg.h index f09a205826..b28f748c38 100644 --- a/codec-cfg.h +++ b/codec-cfg.h @@ -34,7 +34,8 @@ #define AFM_A52 14 #define AFM_G72X 15 #define AFM_IMAADPCM 16 -#define AFM_FOX62ADPCM 17 +#define AFM_FOX61ADPCM 17 +#define AFM_FOX62ADPCM 18 #define VFM_MPEG 1 #define VFM_VFW 2 diff --git a/dec_audio.c b/dec_audio.c index bcc6c3577e..c16b07c252 100644 --- a/dec_audio.c +++ b/dec_audio.c @@ -412,6 +412,11 @@ case AFM_MSADPCM: sh_audio->ds->ss_div = MS_ADPCM_SAMPLES_PER_BLOCK; sh_audio->ds->ss_mul = sh_audio->wf->nBlockAlign; break; +case AFM_FOX61ADPCM: + sh_audio->audio_out_minsize=FOX61_ADPCM_SAMPLES_PER_BLOCK * 4; + sh_audio->ds->ss_div=FOX61_ADPCM_SAMPLES_PER_BLOCK; + sh_audio->ds->ss_mul=FOX61_ADPCM_BLOCK_SIZE; + break; case AFM_FOX62ADPCM: sh_audio->audio_out_minsize=FOX62_ADPCM_SAMPLES_PER_BLOCK * 4; sh_audio->ds->ss_div=FOX62_ADPCM_SAMPLES_PER_BLOCK; @@ -693,6 +698,12 @@ case AFM_MSADPCM: sh_audio->i_bps = sh_audio->wf->nBlockAlign * (sh_audio->channels*sh_audio->samplerate) / MS_ADPCM_SAMPLES_PER_BLOCK; break; +case AFM_FOX61ADPCM: + sh_audio->channels=sh_audio->wf->nChannels; + sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; + sh_audio->i_bps=FOX61_ADPCM_BLOCK_SIZE* + (sh_audio->channels*sh_audio->samplerate) / FOX61_ADPCM_SAMPLES_PER_BLOCK; + break; case AFM_FOX62ADPCM: sh_audio->channels=sh_audio->wf->nChannels; sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; @@ -1122,13 +1133,22 @@ int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen){ sh_audio->wf->nBlockAlign); break; } + case AFM_FOX61ADPCM: + { unsigned char ibuf[FOX61_ADPCM_BLOCK_SIZE]; // bytes / stereo frame + if (demux_read_data(sh_audio->ds, ibuf, FOX61_ADPCM_BLOCK_SIZE) != + FOX61_ADPCM_BLOCK_SIZE) + break; // EOF + len=2*fox61_adpcm_decode_block((unsigned short*)buf,ibuf); + break; + } case AFM_FOX62ADPCM: { unsigned char ibuf[FOX62_ADPCM_BLOCK_SIZE * 2]; // bytes / stereo frame if (demux_read_data(sh_audio->ds, ibuf, FOX62_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels) != FOX62_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels) break; // EOF - len=2*fox62_adpcm_decode_block((unsigned short*)buf,ibuf, sh_audio->wf->nChannels); + len = 2 * fox62_adpcm_decode_block( + (unsigned short*)buf,ibuf, sh_audio->wf->nChannels); break; } #ifdef USE_LIBAC3 diff --git a/etc/codecs.conf b/etc/codecs.conf index 86a5d5869a..49b9fb59c7 100644 --- a/etc/codecs.conf +++ b/etc/codecs.conf @@ -331,6 +331,12 @@ audiocodec msadpcm format 0x2 driver msadpcm +audiocodec fox61adpcm + info "Format 0x61 ADPCM" + status working + format 0x61 + driver fox61adpcm + audiocodec fox62adpcm info "Format 0x62 ADPCM" status buggy -- cgit v1.2.3