mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
ADPCM IMA WAV 2, 3 and 5 bits decoder
Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
parent
48f2750de8
commit
6516a25f04
@ -118,10 +118,8 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
|
||||
c->status[0].step = c->status[1].step = 511;
|
||||
break;
|
||||
case AV_CODEC_ID_ADPCM_IMA_WAV:
|
||||
if (avctx->bits_per_coded_sample != 4) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Only 4-bit ADPCM IMA WAV files are supported\n");
|
||||
return -1;
|
||||
}
|
||||
if (avctx->bits_per_coded_sample < 2 || avctx->bits_per_coded_sample > 5)
|
||||
return AVERROR_INVALIDDATA;
|
||||
break;
|
||||
case AV_CODEC_ID_ADPCM_IMA_APC:
|
||||
if (avctx->extradata && avctx->extradata_size >= 8) {
|
||||
@ -188,6 +186,29 @@ static inline short adpcm_ima_expand_nibble(ADPCMChannelStatus *c, char nibble,
|
||||
return (short)c->predictor;
|
||||
}
|
||||
|
||||
static inline int16_t adpcm_ima_wav_expand_nibble(ADPCMChannelStatus *c, GetBitContext *gb, int bps)
|
||||
{
|
||||
int nibble, step_index, predictor, sign, delta, diff, step, shift;
|
||||
|
||||
shift = bps - 1;
|
||||
nibble = get_bits_le(gb, bps),
|
||||
step = ff_adpcm_step_table[c->step_index];
|
||||
step_index = c->step_index + ff_adpcm_index_tables[bps - 2][nibble];
|
||||
step_index = av_clip(step_index, 0, 88);
|
||||
|
||||
sign = nibble & (1 << shift);
|
||||
delta = nibble & ((1 << shift) - 1);
|
||||
diff = ((2 * delta + 1) * step) >> shift;
|
||||
predictor = c->predictor;
|
||||
if (sign) predictor -= diff;
|
||||
else predictor += diff;
|
||||
|
||||
c->predictor = av_clip_int16(predictor);
|
||||
c->step_index = step_index;
|
||||
|
||||
return (int16_t)c->predictor;
|
||||
}
|
||||
|
||||
static inline int adpcm_ima_qt_expand_nibble(ADPCMChannelStatus *c, int nibble, int shift)
|
||||
{
|
||||
int step_index;
|
||||
@ -557,10 +578,14 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
|
||||
nb_samples = (buf_size - 4 * ch) * 2 / ch;
|
||||
break;
|
||||
case AV_CODEC_ID_ADPCM_IMA_WAV:
|
||||
{
|
||||
int bsize = ff_adpcm_ima_block_sizes[avctx->bits_per_coded_sample - 2];
|
||||
int bsamples = ff_adpcm_ima_block_samples[avctx->bits_per_coded_sample - 2];
|
||||
if (avctx->block_align > 0)
|
||||
buf_size = FFMIN(buf_size, avctx->block_align);
|
||||
nb_samples = 1 + (buf_size - 4 * ch) / (4 * ch) * 8;
|
||||
nb_samples = 1 + (buf_size - 4 * ch) / (bsize * ch) * bsamples;
|
||||
break;
|
||||
}
|
||||
case AV_CODEC_ID_ADPCM_MS:
|
||||
if (avctx->block_align > 0)
|
||||
buf_size = FFMIN(buf_size, avctx->block_align);
|
||||
@ -720,6 +745,23 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
|
||||
}
|
||||
}
|
||||
|
||||
if (avctx->bits_per_coded_sample != 4) {
|
||||
int samples_per_block = ff_adpcm_ima_block_samples[avctx->bits_per_coded_sample - 2];
|
||||
GetBitContext g;
|
||||
|
||||
init_get_bits8(&g, gb.buffer, bytestream2_get_bytes_left(&gb));
|
||||
for (n = 0; n < (nb_samples - 1) / samples_per_block; n++) {
|
||||
for (i = 0; i < avctx->channels; i++) {
|
||||
cs = &c->status[i];
|
||||
samples = &samples_p[i][1 + n * samples_per_block];
|
||||
for (m = 0; m < samples_per_block; m++) {
|
||||
samples[m] = adpcm_ima_wav_expand_nibble(cs, &g,
|
||||
avctx->bits_per_coded_sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
bytestream2_skip(&gb, avctx->block_align - avctx->channels * 4);
|
||||
} else {
|
||||
for (n = 0; n < (nb_samples - 1) / 8; n++) {
|
||||
for (i = 0; i < avctx->channels; i++) {
|
||||
cs = &c->status[i];
|
||||
@ -731,6 +773,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AV_CODEC_ID_ADPCM_4XM:
|
||||
for (i = 0; i < avctx->channels; i++)
|
||||
|
@ -27,12 +27,33 @@
|
||||
|
||||
/* ff_adpcm_step_table[] and ff_adpcm_index_table[] are from the ADPCM
|
||||
reference source */
|
||||
/* This is the index table: */
|
||||
static const int8_t adpcm_index_table2[4] = {
|
||||
-1, 2,
|
||||
-1, 2,
|
||||
};
|
||||
|
||||
static const int8_t adpcm_index_table3[8] = {
|
||||
-1, -1, 1, 2,
|
||||
-1, -1, 1, 2,
|
||||
};
|
||||
|
||||
const int8_t ff_adpcm_index_table[16] = {
|
||||
-1, -1, -1, -1, 2, 4, 6, 8,
|
||||
-1, -1, -1, -1, 2, 4, 6, 8,
|
||||
};
|
||||
|
||||
static const int8_t adpcm_index_table5[32] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16,
|
||||
};
|
||||
|
||||
const int8_t const *ff_adpcm_index_tables[4] = {
|
||||
&adpcm_index_table2[0],
|
||||
&adpcm_index_table3[0],
|
||||
&ff_adpcm_index_table[0],
|
||||
&adpcm_index_table5[0],
|
||||
};
|
||||
|
||||
/**
|
||||
* This is the step table. Note that many programs use slight deviations from
|
||||
* this table, but such deviations are negligible:
|
||||
|
@ -28,6 +28,10 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static const uint8_t ff_adpcm_ima_block_sizes[4] = { 4, 12, 4, 20 };
|
||||
static const uint8_t ff_adpcm_ima_block_samples[4] = { 16, 32, 8, 32 };
|
||||
|
||||
extern const int8_t const *ff_adpcm_index_tables[4];
|
||||
extern const int8_t ff_adpcm_index_table[16];
|
||||
extern const int16_t ff_adpcm_step_table[89];
|
||||
extern const int16_t ff_adpcm_oki_step_table[49];
|
||||
|
@ -2899,7 +2899,9 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes)
|
||||
int blocks = frame_bytes / ba;
|
||||
switch (avctx->codec_id) {
|
||||
case AV_CODEC_ID_ADPCM_IMA_WAV:
|
||||
return blocks * (1 + (ba - 4 * ch) / (4 * ch) * 8);
|
||||
if (bps < 2 || bps > 5)
|
||||
return 0;
|
||||
return blocks * (1 + (ba - 4 * ch) / (bps * ch) * 8);
|
||||
case AV_CODEC_ID_ADPCM_IMA_DK3:
|
||||
return blocks * (((ba - 16) * 2 / 3 * 4) / ch);
|
||||
case AV_CODEC_ID_ADPCM_IMA_DK4:
|
||||
|
Loading…
Reference in New Issue
Block a user