avcodec: add ADPCM Circus decoder

(cherry picked from commit cdd3d794c7e01e4d6f485e7b975a4b9107d3f2fd)
This commit is contained in:
Paul B Mahol 2025-02-28 16:05:05 +00:00 committed by michaelni
parent f6dfb20302
commit 5d6c9a15eb
6 changed files with 42 additions and 0 deletions

View file

@ -958,6 +958,7 @@ OBJS-$(CONFIG_ADPCM_AGM_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_AICA_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_ARGO_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_ARGO_ENCODER) += adpcm.o adpcm_data.o adpcmenc.o
OBJS-$(CONFIG_ADPCM_CIRCUS_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_CT_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_DTK_DECODER) += adpcm.o adpcm_data.o
OBJS-$(CONFIG_ADPCM_EA_DECODER) += adpcm.o adpcm_data.o

View file

@ -740,6 +740,27 @@ static inline int16_t adpcm_mtaf_expand_nibble(ADPCMChannelStatus *c, uint8_t ni
return c->predictor;
}
static inline int16_t adpcm_circus_expand_nibble(ADPCMChannelStatus *c, uint8_t nibble)
{
int32_t sample = c->predictor;
int32_t scale = c->step;
int32_t code = sign_extend(nibble, 8);
sample += code * (1 << scale);
if (code == 0) {
scale--;
} else if (code == 127 || code == -128) {
scale++;
}
scale = av_clip(scale, 0, 8);
sample = av_clip_int16(sample);
c->predictor = sample;
c->step = scale;
return sample;
}
static inline int16_t adpcm_zork_expand_nibble(ADPCMChannelStatus *c, uint8_t nibble)
{
int16_t index = c->step_index;
@ -1365,6 +1386,7 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
case AV_CODEC_ID_ADPCM_ARGO:
nb_samples = buf_size / avctx->block_align * 32;
break;
case AV_CODEC_ID_ADPCM_CIRCUS:
case AV_CODEC_ID_ADPCM_ZORK:
nb_samples = buf_size / ch;
break;
@ -2796,6 +2818,14 @@ static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame,
}
}
) /* End of CASE */
CASE(ADPCM_CIRCUS,
for (int n = 0; n < nb_samples; n++) {
for (int ch = 0; ch < channels; ch++) {
int v = bytestream2_get_byteu(&gb);
*samples++ = adpcm_circus_expand_nibble(&c->status[ch], v);
}
}
) /* End of CASE */
CASE(ADPCM_ZORK,
for (int n = 0; n < nb_samples * channels; n++) {
int v = bytestream2_get_byteu(&gb);
@ -2909,6 +2939,7 @@ ADPCM_DECODER(ADPCM_AFC, sample_fmts_s16p, adpcm_afc, "ADPCM Nin
ADPCM_DECODER(ADPCM_AGM, sample_fmts_s16, adpcm_agm, "ADPCM AmuseGraphics Movie")
ADPCM_DECODER(ADPCM_AICA, sample_fmts_s16p, adpcm_aica, "ADPCM Yamaha AICA")
ADPCM_DECODER(ADPCM_ARGO, sample_fmts_s16p, adpcm_argo, "ADPCM Argonaut Games")
ADPCM_DECODER(ADPCM_CIRCUS, sample_fmts_s16, adpcm_circus, "ADPCM Circus")
ADPCM_DECODER(ADPCM_CT, sample_fmts_s16, adpcm_ct, "ADPCM Creative Technology")
ADPCM_DECODER(ADPCM_DTK, sample_fmts_s16p, adpcm_dtk, "ADPCM Nintendo Gamecube DTK")
ADPCM_DECODER(ADPCM_EA, sample_fmts_s16, adpcm_ea, "ADPCM Electronic Arts")

View file

@ -649,6 +649,7 @@ extern const FFCodec ff_adpcm_agm_decoder;
extern const FFCodec ff_adpcm_aica_decoder;
extern const FFCodec ff_adpcm_argo_decoder;
extern const FFCodec ff_adpcm_argo_encoder;
extern const FFCodec ff_adpcm_circus_decoder;
extern const FFCodec ff_adpcm_ct_decoder;
extern const FFCodec ff_adpcm_dtk_decoder;
extern const FFCodec ff_adpcm_ea_decoder;

View file

@ -2676,6 +2676,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
.long_name = NULL_IF_CONFIG_SMALL("ADPCM Playstation C"),
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
},
{
.id = AV_CODEC_ID_ADPCM_CIRCUS,
.type = AVMEDIA_TYPE_AUDIO,
.name = "adpcm_circus",
.long_name = NULL_IF_CONFIG_SMALL("ADPCM Circus"),
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
},
/* AMR */
{

View file

@ -433,6 +433,7 @@ enum AVCodecID {
AV_CODEC_ID_ADPCM_IMA_HVQM2,
AV_CODEC_ID_ADPCM_IMA_MAGIX,
AV_CODEC_ID_ADPCM_PSXC,
AV_CODEC_ID_ADPCM_CIRCUS,
/* AMR */
AV_CODEC_ID_AMR_NB = 0x12000,

View file

@ -488,6 +488,7 @@ int av_get_exact_bits_per_sample(enum AVCodecID codec_id)
case AV_CODEC_ID_CBD2_DPCM:
case AV_CODEC_ID_DERF_DPCM:
case AV_CODEC_ID_WADY_DPCM:
case AV_CODEC_ID_ADPCM_CIRCUS:
return 8;
case AV_CODEC_ID_PCM_S16BE:
case AV_CODEC_ID_PCM_S16BE_PLANAR: