# HG changeset patch # User melanson # Date 1097585269 0 # Node ID 2b75dff0111899ec3a79880612ca810f5978f6b4 # Parent c8f35aaeb857d86efb2d43658277f49e71893577 Creative ADPCM decoder, format 0x200, courtesy of Konstantin Shishkov diff -r c8f35aaeb857 -r 2b75dff01118 adpcm.c --- a/adpcm.c Tue Oct 12 07:16:14 2004 +0000 +++ b/adpcm.c Tue Oct 12 12:47:49 2004 +0000 @@ -103,6 +103,11 @@ 3, 4, 7, 8, 10, 11, 0, -1, -3, -4 }; +static int ct_adpcm_table[8] = { + 0x00E6, 0x00E6, 0x00E6, 0x00E6, + 0x0133, 0x0199, 0x0200, 0x0266 +}; + /* end of tables */ typedef struct ADPCMChannelStatus { @@ -361,6 +366,9 @@ c->status[0].step = c->status[1].step = 0; switch(avctx->codec->id) { + case CODEC_ID_ADPCM_CT: + c->status[0].step = c->status[1].step = 511; + break; default: break; } @@ -411,6 +419,37 @@ return (short)predictor; } +static inline short adpcm_ct_expand_nibble(ADPCMChannelStatus *c, char nibble) +{ + int predictor; + int sign, delta, diff; + int new_step; + + sign = nibble & 8; + delta = nibble & 7; + /* perform direct multiplication instead of series of jumps proposed by + * the reference ADPCM implementation since modern CPUs can do the mults + * quickly enough */ + diff = ((2 * delta + 1) * c->step) >> 3; + predictor = c->predictor; + /* predictor update is not so trivial: predictor is multiplied on 254/256 before updating */ + if(sign) + predictor = ((predictor * 254) >> 8) - diff; + else + predictor = ((predictor * 254) >> 8) + diff; + /* calculate new step and clamp it to range 511..32767 */ + new_step = (ct_adpcm_table[nibble & 7] * c->step) >> 8; + c->step = new_step; + if(c->step < 511) + c->step = 511; + if(c->step > 32767) + c->step = 32767; + + CLAMP_TO_SHORT(predictor); + c->predictor = predictor; + return (short)predictor; +} + static void xa_decode(short *out, const unsigned char *in, ADPCMChannelStatus *left, ADPCMChannelStatus *right, int inc) { @@ -840,6 +879,22 @@ src++; } break; + case CODEC_ID_ADPCM_CT: + while (src < buf + buf_size) { + if (st) { + *samples++ = adpcm_ct_expand_nibble(&c->status[0], + (src[0] >> 4) & 0x0F); + *samples++ = adpcm_ct_expand_nibble(&c->status[1], + src[0] & 0x0F); + } else { + *samples++ = adpcm_ct_expand_nibble(&c->status[0], + (src[0] >> 4) & 0x0F); + *samples++ = adpcm_ct_expand_nibble(&c->status[0], + src[0] & 0x0F); + } + src++; + } + break; default: return -1; } @@ -895,5 +950,6 @@ ADPCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa); ADPCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx); ADPCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea); +ADPCM_CODEC(CODEC_ID_ADPCM_CT, adpcm_ct); #undef ADPCM_CODEC diff -r c8f35aaeb857 -r 2b75dff01118 allcodecs.c --- a/allcodecs.c Tue Oct 12 07:16:14 2004 +0000 +++ b/allcodecs.c Tue Oct 12 12:47:49 2004 +0000 @@ -223,6 +223,7 @@ PCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx); PCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea); PCM_CODEC(CODEC_ID_ADPCM_G726, adpcm_g726); +PCM_CODEC(CODEC_ID_ADPCM_CT, adpcm_ct); #undef PCM_CODEC diff -r c8f35aaeb857 -r 2b75dff01118 avcodec.h --- a/avcodec.h Tue Oct 12 07:16:14 2004 +0000 +++ b/avcodec.h Tue Oct 12 12:47:49 2004 +0000 @@ -128,6 +128,7 @@ CODEC_ID_ADPCM_ADX, CODEC_ID_ADPCM_EA, CODEC_ID_ADPCM_G726, + CODEC_ID_ADPCM_CT, /* AMR */ CODEC_ID_AMR_NB, @@ -1916,6 +1917,7 @@ PCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx); PCM_CODEC(CODEC_ID_ADPCM_EA, adpcm_ea); PCM_CODEC(CODEC_ID_ADPCM_G726, adpcm_g726); +PCM_CODEC(CODEC_ID_ADPCM_CT, adpcm_ct); #undef PCM_CODEC