From ba4694f4bb6e456868a22d927d8f34f93625a2af Mon Sep 17 00:00:00 2001 From: melanson Date: Mon, 25 Feb 2002 02:48:37 +0000 Subject: [PATCH] fixed, strengthened, rewrote, and renamed a variety of the ADPCM decoders (including MS, DK4 and DK3 ADPCM) git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@4855 b3059339-0415-0410-9bf9-f77b7e298cf2 --- adpcm.c | 251 +++++++++++++++++++++++------------------------- adpcm.h | 19 ++-- codec-cfg.c | 4 +- codec-cfg.h | 4 +- dec_audio.c | 55 ++++++----- etc/codecs.conf | 8 +- 6 files changed, 166 insertions(+), 175 deletions(-) diff --git a/adpcm.c b/adpcm.c index 204a54126a..fc1e857653 100644 --- a/adpcm.c +++ b/adpcm.c @@ -12,6 +12,7 @@ #include "config.h" #include "bswap.h" #include "adpcm.h" +#include "mp_msg.h" #define BE_16(x) (be2me_16(*(unsigned short *)(x))) #define BE_32(x) (be2me_32(*(unsigned int *)(x))) @@ -196,11 +197,19 @@ int ms_adpcm_decode_block(unsigned short *output, unsigned char *input, int predictor; // fetch the header information, in stereo if both channels are present + if (input[stream_ptr] > 6) + mp_msg(MSGT_DECAUDIO, MSGL_WARN, + "MS ADPCM: coefficient (%d) out of range (should be [0..6])\n", + input[stream_ptr]); coeff1[0] = ms_adapt_coeff1[input[stream_ptr]]; coeff2[0] = ms_adapt_coeff2[input[stream_ptr]]; stream_ptr++; if (channels == 2) { + if (input[stream_ptr] > 6) + mp_msg(MSGT_DECAUDIO, MSGL_WARN, + "MS ADPCM: coefficient (%d) out of range (should be [0..6])\n", + input[stream_ptr]); coeff1[1] = ms_adapt_coeff1[input[stream_ptr]]; coeff2[1] = ms_adapt_coeff2[input[stream_ptr]]; stream_ptr++; @@ -267,49 +276,71 @@ 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 dk4_adpcm_decode_block(unsigned short *output, unsigned char *input, + int channels, int block_size) { int i; - int predictor; - int index; + int output_ptr; + int predictor_l = 0; + int predictor_r = 0; + int index_l = 0; + int index_r = 0; // the first predictor value goes straight to the output - predictor = output[0] = LE_16(&input[0]); - SE_16BIT(predictor); - index = input[2]; - - // unpack the nibbles - for (i = 4; i < FOX61_ADPCM_BLOCK_SIZE; i++) + predictor_l = output[0] = LE_16(&input[0]); + SE_16BIT(predictor_l); + index_l = input[2]; + if (channels == 2) { - output[1 + (i - 4) * 2 + 0] = (input[i] >> 4) & 0x0F; - output[1 + (i - 4) * 2 + 1] = input[i] & 0x0F; + predictor_r = output[1] = LE_16(&input[4]); + SE_16BIT(predictor_r); + index_r = input[6]; } - decode_nibbles(&output[1], FOX61_ADPCM_SAMPLES_PER_BLOCK - 1, 1, - predictor, index, - 0, 0); + output_ptr = channels; + for (i = DK4_ADPCM_PREAMBLE_SIZE * channels; i < block_size; i++) + { + output[output_ptr++] = input[i] >> 4; + output[output_ptr++] = input[i] & 0x0F; + } - return FOX61_ADPCM_SAMPLES_PER_BLOCK; + decode_nibbles(&output[channels], + (block_size - DK4_ADPCM_PREAMBLE_SIZE * channels) * 2 - channels, + channels, + predictor_l, index_l, + predictor_r, index_r); + + return (block_size - DK4_ADPCM_PREAMBLE_SIZE * channels) * 2 - channels; } +#define DK3_GET_NEXT_NIBBLE() \ + if (decode_top_nibble_next) \ + { \ + nibble = (last_byte >> 4) & 0x0F; \ + decode_top_nibble_next = 0; \ + } \ + else \ + { \ + last_byte = input[in_ptr++]; \ + nibble = last_byte & 0x0F; \ + decode_top_nibble_next = 1; \ + } + // note: This decoder assumes the format 0x62 data always comes in // stereo flavor -int fox62_adpcm_decode_block(unsigned short *output, unsigned char *input) +int dk3_adpcm_decode_block(unsigned short *output, unsigned char *input) { - int pred1; - int pred2; - int index1; - int index2; + int sum_pred; + int diff_pred; + int sum_index; + int diff_index; + int diff_channel; int in_ptr = 0x10; int out_ptr = 0; - int flag1 = 0; - int flag2 = 1; - int sum; unsigned char last_byte = 0; unsigned char nibble; + int decode_top_nibble_next = 0; // ADPCM work variables int sign; @@ -317,137 +348,93 @@ int fox62_adpcm_decode_block(unsigned short *output, unsigned char *input) int step; int diff; - pred1 = LE_16(&input[10]); - pred2 = LE_16(&input[12]); - SE_16BIT(pred1); - SE_16BIT(pred2); - sum = pred2; - index1 = input[14]; - index2 = input[15]; + sum_pred = LE_16(&input[10]); + diff_pred = LE_16(&input[12]); + SE_16BIT(sum_pred); + SE_16BIT(diff_pred); + diff_channel = diff_pred; + sum_index = input[14]; + diff_index = input[15]; while (in_ptr < 2048) { - if (flag2) - { - last_byte = input[in_ptr++]; - nibble = last_byte & 0x0F; + // process the first predictor of the sum channel + DK3_GET_NEXT_NIBBLE(); - step = adpcm_step[index1]; + step = adpcm_step[sum_index]; - sign = nibble & 8; - delta = nibble & 7; + 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; + diff = step >> 3; + if (delta & 4) diff += step; + if (delta & 2) diff += step >> 1; + if (delta & 1) diff += step >> 2; - if (sign) - pred1 -= diff; - else - pred1 += diff; - - CLAMP_S16(pred1); - - index1 += adpcm_index[nibble]; - CLAMP_0_TO_88(index1); - - if (flag1) - flag2 = 0; - else - { - nibble = (last_byte >> 4) & 0x0F; - - step = adpcm_step[index2]; - - 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) - pred2 -= diff; - else - pred2 += diff; - - CLAMP_S16(pred2); - - index2 += adpcm_index[nibble]; - CLAMP_0_TO_88(index2); - - sum = (sum + pred2) / 2; - } - output[out_ptr++] = pred1 + sum; - output[out_ptr++] = pred1 - sum; - - flag1 ^= 1; - if (in_ptr >= 2048) - break; - } + if (sign) + sum_pred -= diff; else - { - nibble = (last_byte >> 4) & 0x0F; + sum_pred += diff; - step = adpcm_step[index1]; + CLAMP_S16(sum_pred); - sign = nibble & 8; - delta = nibble & 7; + sum_index += adpcm_index[nibble]; + CLAMP_0_TO_88(sum_index); + + // process the diff channel predictor + DK3_GET_NEXT_NIBBLE(); - diff = step >> 3; - if (delta & 4) diff += step; - if (delta & 2) diff += step >> 1; - if (delta & 1) diff += step >> 2; + step = adpcm_step[diff_index]; - if (sign) - pred1 -= diff; - else - pred1 += diff; + sign = nibble & 8; + delta = nibble & 7; - CLAMP_S16(pred1); + diff = step >> 3; + if (delta & 4) diff += step; + if (delta & 2) diff += step >> 1; + if (delta & 1) diff += step >> 2; - index1 += adpcm_index[nibble]; - CLAMP_0_TO_88(index1); + if (sign) + diff_pred -= diff; + else + diff_pred += diff; - if (flag1) - flag2 = 1; - else - { - last_byte = input[in_ptr++]; - nibble = last_byte & 0x0F; + CLAMP_S16(diff_pred); - step = adpcm_step[index2]; + diff_index += adpcm_index[nibble]; + CLAMP_0_TO_88(diff_index); - sign = nibble & 8; - delta = nibble & 7; + // output the first pair of stereo PCM samples + diff_channel = (diff_channel + diff_pred) / 2; + output[out_ptr++] = sum_pred + diff_channel; + output[out_ptr++] = sum_pred - diff_channel; - diff = step >> 3; - if (delta & 4) diff += step; - if (delta & 2) diff += step >> 1; - if (delta & 1) diff += step >> 2; + // process the second predictor of the sum channel + DK3_GET_NEXT_NIBBLE(); - if (sign) - pred2 -= diff; - else - pred2 += diff; + step = adpcm_step[sum_index]; - CLAMP_S16(pred2); + sign = nibble & 8; + delta = nibble & 7; - index2 += adpcm_index[nibble]; - CLAMP_0_TO_88(index2); + diff = step >> 3; + if (delta & 4) diff += step; + if (delta & 2) diff += step >> 1; + if (delta & 1) diff += step >> 2; - sum = (sum + pred2) / 2; - } + if (sign) + sum_pred -= diff; + else + sum_pred += diff; - output[out_ptr++] = pred1 + sum; - output[out_ptr++] = pred1 - sum; + CLAMP_S16(sum_pred); - flag1 ^= 1; - if (in_ptr >= 2048) - break; - } + sum_index += adpcm_index[nibble]; + CLAMP_0_TO_88(sum_index); + + // output the second pair of stereo PCM samples + output[out_ptr++] = sum_pred + diff_channel; + output[out_ptr++] = sum_pred - diff_channel; } return out_ptr; diff --git a/adpcm.h b/adpcm.h index 7ccfcb7424..9fe7c8676a 100644 --- a/adpcm.h +++ b/adpcm.h @@ -10,21 +10,22 @@ #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) +#define DK4_ADPCM_PREAMBLE_SIZE 4 +#define DK4_ADPCM_SAMPLES_PER_BLOCK \ + (((sh_audio->wf->nBlockAlign - DK4_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 +#define DK3_ADPCM_PREAMBLE_SIZE 8 +#define DK3_ADPCM_BLOCK_SIZE 0x400 // this isn't exact -#define FOX62_ADPCM_SAMPLES_PER_BLOCK 6000 +#define DK3_ADPCM_SAMPLES_PER_BLOCK 6000 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 dk4_adpcm_decode_block(unsigned short *output, unsigned char *input, + int channels, int block_size); +int dk3_adpcm_decode_block(unsigned short *output, unsigned char *input); + #endif diff --git a/codec-cfg.c b/codec-cfg.c index 1b9f5eb1a4..c18d99f265 100644 --- a/codec-cfg.c +++ b/codec-cfg.c @@ -224,8 +224,8 @@ static short get_driver(char *s,int audioflag) "liba52", "g72x", "imaadpcm", - "fox61adpcm", - "fox62adpcm", + "dk4adpcm", + "dk3adpcm", "roqaudio", NULL }; diff --git a/codec-cfg.h b/codec-cfg.h index d9a0a65532..ebb3e3704f 100644 --- a/codec-cfg.h +++ b/codec-cfg.h @@ -35,8 +35,8 @@ #define AFM_A52 14 #define AFM_G72X 15 #define AFM_IMAADPCM 16 -#define AFM_FOX61ADPCM 17 -#define AFM_FOX62ADPCM 18 +#define AFM_DK4ADPCM 17 +#define AFM_DK3ADPCM 18 #define AFM_ROQAUDIO 19 #define VFM_MPEG 1 diff --git a/dec_audio.c b/dec_audio.c index d2f651f3c3..ce36738554 100644 --- a/dec_audio.c +++ b/dec_audio.c @@ -425,21 +425,21 @@ 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; +case AFM_DK4ADPCM: + sh_audio->audio_out_minsize=DK4_ADPCM_SAMPLES_PER_BLOCK * 4; + sh_audio->ds->ss_div=DK4_ADPCM_SAMPLES_PER_BLOCK; + sh_audio->ds->ss_mul=sh_audio->wf->nBlockAlign; 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; - sh_audio->ds->ss_mul=FOX62_ADPCM_BLOCK_SIZE; +case AFM_DK3ADPCM: + sh_audio->audio_out_minsize=DK3_ADPCM_SAMPLES_PER_BLOCK * 4; + sh_audio->ds->ss_div=DK3_ADPCM_SAMPLES_PER_BLOCK; + sh_audio->ds->ss_mul=DK3_ADPCM_BLOCK_SIZE; break; case AFM_ROQAUDIO: // minsize was stored in wf->nBlockAlign by the RoQ demuxer sh_audio->audio_out_minsize=sh_audio->wf->nBlockAlign; - sh_audio->ds->ss_div=FOX62_ADPCM_SAMPLES_PER_BLOCK; - sh_audio->ds->ss_mul=FOX62_ADPCM_BLOCK_SIZE; + sh_audio->ds->ss_div=DK3_ADPCM_SAMPLES_PER_BLOCK; + sh_audio->ds->ss_mul=DK3_ADPCM_BLOCK_SIZE; sh_audio->context = roq_decode_audio_init(); break; case AFM_MPEG: @@ -724,17 +724,17 @@ 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: +case AFM_DK4ADPCM: 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; + sh_audio->i_bps = sh_audio->wf->nBlockAlign * + (sh_audio->channels*sh_audio->samplerate) / DK4_ADPCM_SAMPLES_PER_BLOCK; break; -case AFM_FOX62ADPCM: +case AFM_DK3ADPCM: sh_audio->channels=sh_audio->wf->nChannels; sh_audio->samplerate=sh_audio->wf->nSamplesPerSec; - sh_audio->i_bps=FOX62_ADPCM_BLOCK_SIZE* - (sh_audio->channels*sh_audio->samplerate) / FOX62_ADPCM_SAMPLES_PER_BLOCK; + sh_audio->i_bps=DK3_ADPCM_BLOCK_SIZE* + (sh_audio->channels*sh_audio->samplerate) / DK3_ADPCM_SAMPLES_PER_BLOCK; break; case AFM_ROQAUDIO: sh_audio->channels=sh_audio->wf->nChannels; @@ -1163,21 +1163,24 @@ 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) + case AFM_DK4ADPCM: + { static unsigned char *ibuf = NULL; + if (!ibuf) + ibuf = (unsigned char *)malloc(sh_audio->wf->nBlockAlign); + if (demux_read_data(sh_audio->ds, ibuf, sh_audio->wf->nBlockAlign) != + sh_audio->wf->nBlockAlign) break; // EOF - len=2*fox61_adpcm_decode_block((unsigned short*)buf,ibuf); + len=2*dk4_adpcm_decode_block((unsigned short*)buf,ibuf, + sh_audio->wf->nChannels, sh_audio->wf->nBlockAlign); break; } - case AFM_FOX62ADPCM: - { unsigned char ibuf[FOX62_ADPCM_BLOCK_SIZE * 2]; // bytes / stereo frame + case AFM_DK3ADPCM: + { unsigned char ibuf[DK3_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) + DK3_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels) != + DK3_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels) break; // EOF - len = 2 * fox62_adpcm_decode_block( + len = 2 * dk3_adpcm_decode_block( (unsigned short*)buf,ibuf); break; } diff --git a/etc/codecs.conf b/etc/codecs.conf index f52ec0d285..2e14580be1 100644 --- a/etc/codecs.conf +++ b/etc/codecs.conf @@ -384,19 +384,19 @@ audiocodec msadpcm format 0x2 driver msadpcm -audiocodec fox61adpcm +audiocodec dk4adpcm info "Duck DK4 ADPCM (rogue format number)" status working comment "This format number was used by Duck Corp. but not officially registered with Microsoft" format 0x61 - driver fox61adpcm + driver dk4adpcm -audiocodec fox62adpcm +audiocodec dk3adpcm info "Duck DK3 ADPCM (rogue format number)" status working comment "This format number was used by Duck Corp. but not officially registered with Microsoft" format 0x62 - driver fox62adpcm + driver dk3adpcm audiocodec roqaudio info "Id RoQ File Audio Decoder"