aboutsummaryrefslogtreecommitdiff
path: root/libavcodec/adpcm.c
diff options
context:
space:
mode:
authorZane van Iperen2020-04-18 00:20:39 +0000
committerMichael Niedermayer2020-04-24 19:43:04 +0200
commit3e22e738c0c3be96d234a55d36a01c14ce592961 (patch)
tree54803f4b47a19c5f9a679bfe952b827a076de06b /libavcodec/adpcm.c
parentf4d8fad802b59d3099eb453dcafb08219ecfa22c (diff)
avcodec: add support for Cunning Developments' ADPCM
Signed-off-by: Zane van Iperen <zane@zanevaniperen.com> Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
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 9ea6a268eb..c6735a49c9 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -16,6 +16,7 @@
* Simon & Schuster Interactive ADPCM decoder by Zane van Iperen (zane@zanevaniperen.com)
* Ubisoft ADPCM decoder by Zane van Iperen (zane@zanevaniperen.com)
* High Voltage Software ALP decoder by Zane van Iperen (zane@zanevaniperen.com)
+ * Cunning Developments decoder by Zane van Iperen (zane@zanevaniperen.com)
*
* This file is part of FFmpeg.
*
@@ -109,6 +110,9 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
unsigned int max_channels = 2;
switch(avctx->codec->id) {
+ case AV_CODEC_ID_ADPCM_IMA_CUNNING:
+ max_channels = 1;
+ break;
case AV_CODEC_ID_ADPCM_DTK:
case AV_CODEC_ID_ADPCM_EA:
min_channels = 2;
@@ -325,6 +329,26 @@ static inline int16_t adpcm_ima_mtf_expand_nibble(ADPCMChannelStatus *c, int nib
return (int16_t)c->predictor;
}
+static inline int16_t adpcm_ima_cunning_expand_nibble(ADPCMChannelStatus *c, int8_t nibble)
+{
+ int step_index;
+ int predictor;
+ int step;
+
+ nibble = sign_extend(nibble & 0xF, 4);
+
+ step = ff_adpcm_ima_cunning_step_table[c->step_index];
+ step_index = c->step_index + ff_adpcm_ima_cunning_index_table[abs(nibble)];
+ step_index = av_clip(step_index, 0, 60);
+
+ predictor = c->predictor + step * nibble;
+
+ c->predictor = av_clip_int16(predictor);
+ c->step_index = step_index;
+
+ return 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;
@@ -713,6 +737,7 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
/* simple 4-bit adpcm */
case AV_CODEC_ID_ADPCM_CT:
case AV_CODEC_ID_ADPCM_IMA_APC:
+ case AV_CODEC_ID_ADPCM_IMA_CUNNING:
case AV_CODEC_ID_ADPCM_IMA_EA_SEAD:
case AV_CODEC_ID_ADPCM_IMA_OKI:
case AV_CODEC_ID_ADPCM_IMA_WS:
@@ -1304,6 +1329,13 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
samples += avctx->channels;
}
break;
+ case AV_CODEC_ID_ADPCM_IMA_CUNNING:
+ for (n = 0; n < nb_samples / 2; n++) {
+ int v = bytestream2_get_byteu(&gb);
+ *samples++ = adpcm_ima_cunning_expand_nibble(&c->status[0], v & 0x0F);
+ *samples++ = adpcm_ima_cunning_expand_nibble(&c->status[0], v >> 4);
+ }
+ break;
case AV_CODEC_ID_ADPCM_IMA_OKI:
for (n = nb_samples >> (1 - st); n > 0; n--) {
int v = bytestream2_get_byteu(&gb);
@@ -2053,6 +2085,7 @@ ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_XAS, sample_fmts_s16p, adpcm_ea_xas,
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_AMV, sample_fmts_s16, adpcm_ima_amv, "ADPCM IMA AMV");
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_APC, sample_fmts_s16, adpcm_ima_apc, "ADPCM IMA CRYO APC");
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_APM, sample_fmts_s16, adpcm_ima_apm, "ADPCM IMA Ubisoft APM");
+ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_CUNNING, sample_fmts_s16, adpcm_ima_cunning, "ADPCM IMA Cunning Developments");
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_DAT4, sample_fmts_s16, adpcm_ima_dat4, "ADPCM IMA Eurocom DAT4");
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_DK3, sample_fmts_s16, adpcm_ima_dk3, "ADPCM IMA Duck DK3");
ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_DK4, sample_fmts_s16, adpcm_ima_dk4, "ADPCM IMA Duck DK4");