0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-20 12:02:23 +02:00

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
This commit is contained in:
melanson 2002-02-25 02:48:37 +00:00
parent 3605aa4ec8
commit ba4694f4bb
6 changed files with 166 additions and 175 deletions

251
adpcm.c
View File

@ -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;

19
adpcm.h
View File

@ -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

View File

@ -224,8 +224,8 @@ static short get_driver(char *s,int audioflag)
"liba52",
"g72x",
"imaadpcm",
"fox61adpcm",
"fox62adpcm",
"dk4adpcm",
"dk3adpcm",
"roqaudio",
NULL
};

View File

@ -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

View File

@ -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;
}

View File

@ -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"