summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormelanson <melanson@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-02-25 02:48:37 +0000
committermelanson <melanson@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-02-25 02:48:37 +0000
commitba4694f4bb6e456868a22d927d8f34f93625a2af (patch)
treef005da803d8573493e4b4f92e9c213eb8aaa4e0e
parent3605aa4ec8d0130984aeb402d8f5e9df5d747bfe (diff)
downloadmpv-ba4694f4bb6e456868a22d927d8f34f93625a2af.tar.bz2
mpv-ba4694f4bb6e456868a22d927d8f34f93625a2af.tar.xz
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
-rw-r--r--adpcm.c249
-rw-r--r--adpcm.h19
-rw-r--r--codec-cfg.c4
-rw-r--r--codec-cfg.h4
-rw-r--r--dec_audio.c55
-rw-r--r--etc/codecs.conf8
6 files changed, 165 insertions, 174 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;
+ }
+
+ decode_nibbles(&output[channels],
+ (block_size - DK4_ADPCM_PREAMBLE_SIZE * channels) * 2 - channels,
+ channels,
+ predictor_l, index_l,
+ predictor_r, index_r);
- return FOX61_ADPCM_SAMPLES_PER_BLOCK;
+ 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;
-
- step = adpcm_step[index1];
-
- 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)
- pred1 -= diff;
- else
- pred1 += diff;
-
- CLAMP_S16(pred1);
+ // process the first predictor of the sum channel
+ DK3_GET_NEXT_NIBBLE();
- index1 += adpcm_index[nibble];
- CLAMP_0_TO_88(index1);
+ step = adpcm_step[sum_index];
- if (flag1)
- flag2 = 0;
- else
- {
- nibble = (last_byte >> 4) & 0x0F;
+ sign = nibble & 8;
+ delta = nibble & 7;
- step = adpcm_step[index2];
+ diff = step >> 3;
+ if (delta & 4) diff += step;
+ if (delta & 2) diff += step >> 1;
+ if (delta & 1) diff += step >> 2;
- sign = nibble & 8;
- delta = nibble & 7;
+ if (sign)
+ sum_pred -= diff;
+ else
+ sum_pred += diff;
- diff = step >> 3;
- if (delta & 4) diff += step;
- if (delta & 2) diff += step >> 1;
- if (delta & 1) diff += step >> 2;
+ CLAMP_S16(sum_pred);
- if (sign)
- pred2 -= diff;
- else
- pred2 += diff;
+ sum_index += adpcm_index[nibble];
+ CLAMP_0_TO_88(sum_index);
+
+ // process the diff channel predictor
+ DK3_GET_NEXT_NIBBLE();
- CLAMP_S16(pred2);
+ step = adpcm_step[diff_index];
- index2 += adpcm_index[nibble];
- CLAMP_0_TO_88(index2);
+ sign = nibble & 8;
+ delta = nibble & 7;
- sum = (sum + pred2) / 2;
- }
- output[out_ptr++] = pred1 + sum;
- output[out_ptr++] = pred1 - sum;
+ diff = step >> 3;
+ if (delta & 4) diff += step;
+ if (delta & 2) diff += step >> 1;
+ if (delta & 1) diff += step >> 2;
- flag1 ^= 1;
- if (in_ptr >= 2048)
- break;
- }
+ if (sign)
+ diff_pred -= diff;
else
- {
- nibble = (last_byte >> 4) & 0x0F;
-
- step = adpcm_step[index1];
-
- sign = nibble & 8;
- delta = nibble & 7;
+ diff_pred += diff;
- diff = step >> 3;
- if (delta & 4) diff += step;
- if (delta & 2) diff += step >> 1;
- if (delta & 1) diff += step >> 2;
+ CLAMP_S16(diff_pred);
- if (sign)
- pred1 -= diff;
- else
- pred1 += diff;
+ diff_index += adpcm_index[nibble];
+ CLAMP_0_TO_88(diff_index);
- CLAMP_S16(pred1);
+ // 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;
- index1 += adpcm_index[nibble];
- CLAMP_0_TO_88(index1);
+ // process the second predictor of the sum channel
+ DK3_GET_NEXT_NIBBLE();
- if (flag1)
- flag2 = 1;
- else
- {
- last_byte = input[in_ptr++];
- nibble = last_byte & 0x0F;
+ step = adpcm_step[sum_index];
- step = adpcm_step[index2];
+ 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)
- pred2 -= diff;
- else
- pred2 += diff;
-
- CLAMP_S16(pred2);
-
- index2 += adpcm_index[nibble];
- CLAMP_0_TO_88(index2);
+ if (sign)
+ sum_pred -= diff;
+ else
+ sum_pred += diff;
- sum = (sum + pred2) / 2;
- }
+ CLAMP_S16(sum_pred);
- output[out_ptr++] = pred1 + sum;
- output[out_ptr++] = pred1 - sum;
+ sum_index += adpcm_index[nibble];
+ CLAMP_0_TO_88(sum_index);
- flag1 ^= 1;
- if (in_ptr >= 2048)
- break;
- }
+ // 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"