summaryrefslogtreecommitdiff
path: root/libavcodec/adpcm.c
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2020-03-14 11:55:58 +0100
committerPaul B Mahol <onemda@gmail.com>2020-03-17 16:03:39 +0100
commit230703a9fa48a93b7ec54903584e9ec9c947eefc (patch)
tree0dab383dc4c4789a560a10823e165357be7cc41b /libavcodec/adpcm.c
parentc149f16db14a82bbbd95482060403dde823af184 (diff)
avcodec: add ADPCM IMA MTF decoder
Diffstat (limited to 'libavcodec/adpcm.c')
-rw-r--r--libavcodec/adpcm.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index 4f5980f7d5..e9abddc43c 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -89,6 +89,11 @@ static const int8_t zork_index_table[8] = {
-1, -1, -1, 1, 4, 7, 10, 12,
};
+static const int8_t mtf_index_table[16] = {
+ 8, 6, 4, 2, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2, 4, 6, 8,
+};
+
/* end of tables */
typedef struct ADPCMDecodeContext {
@@ -304,6 +309,22 @@ static inline int16_t adpcm_ima_alp_expand_nibble(ADPCMChannelStatus *c, int8_t
return (int16_t)c->predictor;
}
+static inline int16_t adpcm_ima_mtf_expand_nibble(ADPCMChannelStatus *c, int nibble)
+{
+ int step_index, step, delta, predictor;
+
+ step = ff_adpcm_step_table[c->step_index];
+
+ delta = step * (2 * nibble - 15);
+ predictor = c->predictor + delta;
+
+ step_index = c->step_index + mtf_index_table[(unsigned)nibble];
+ c->predictor = av_clip_int16(predictor >> 4);
+ c->step_index = av_clip(step_index, 0, 88);
+
+ return (int16_t)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;
@@ -700,6 +721,7 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
case AV_CODEC_ID_ADPCM_IMA_SSI:
case AV_CODEC_ID_ADPCM_IMA_APM:
case AV_CODEC_ID_ADPCM_IMA_ALP:
+ case AV_CODEC_ID_ADPCM_IMA_MTF:
nb_samples = buf_size * 2 / ch;
break;
}
@@ -1956,6 +1978,16 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
*samples++ = adpcm_zork_expand_nibble(&c->status[n % avctx->channels], v);
}
break;
+ case AV_CODEC_ID_ADPCM_IMA_MTF:
+ for (n = nb_samples / 2; n > 0; n--) {
+ for (channel = 0; channel < avctx->channels; channel++) {
+ int v = bytestream2_get_byteu(&gb);
+ *samples++ = adpcm_ima_mtf_expand_nibble(&c->status[channel], v >> 4);
+ samples[st] = adpcm_ima_mtf_expand_nibble(&c->status[channel], v & 0x0F);
+ }
+ samples += avctx->channels;
+ }
+ break;
default:
av_assert0(0); // unsupported codec_id should not happen
}
@@ -2027,6 +2059,7 @@ ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_DK4, sample_fmts_s16, adpcm_ima_dk4,
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_EA_EACS, sample_fmts_s16, adpcm_ima_ea_eacs, "ADPCM IMA Electronic Arts EACS");
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_EA_SEAD, sample_fmts_s16, adpcm_ima_ea_sead, "ADPCM IMA Electronic Arts SEAD");
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_ISS, sample_fmts_s16, adpcm_ima_iss, "ADPCM IMA Funcom ISS");
+ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_MTF, sample_fmts_s16, adpcm_ima_mtf, "ADPCM IMA Capcom's MT Framework");
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_OKI, sample_fmts_s16, adpcm_ima_oki, "ADPCM IMA Dialogic OKI");
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_QT, sample_fmts_s16p, adpcm_ima_qt, "ADPCM IMA QuickTime");
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_RAD, sample_fmts_s16, adpcm_ima_rad, "ADPCM IMA Radical");