changeset 2296:2b75dff01118 libavcodec

Creative ADPCM decoder, format 0x200, courtesy of Konstantin Shishkov
author melanson
date Tue, 12 Oct 2004 12:47:49 +0000
parents c8f35aaeb857
children 41b5a7bd9a96
files adpcm.c allcodecs.c avcodec.h
diffstat 3 files changed, 59 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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
 
--- 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