changeset 4001:ae6f97724b84

fixed format 0x62 ADPCM audio
author melanson
date Sun, 06 Jan 2002 01:56:27 +0000
parents 587906e031fa
children 6ce744b637ad
files adpcm.c adpcm.h dec_audio.c etc/codecs.conf
diffstat 4 files changed, 154 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/adpcm.c	Sat Jan 05 19:35:01 2002 +0000
+++ b/adpcm.c	Sun Jan 06 01:56:27 2002 +0000
@@ -296,55 +296,159 @@
 
 // note: This decoder assumes the format 0x62 data always comes in
 // stereo flavor
-int fox62_adpcm_decode_block(unsigned short *output, unsigned char *input,
-  int channels)
+int fox62_adpcm_decode_block(unsigned short *output, unsigned char *input)
 {
-  int predictor_l;
-  int predictor_r;
-  int index_l;
-  int index_r;
-  int i;
-  int adjustment;
+  int pred1;
+  int pred2;
+  int index1;
+  int index2;
+  int in_ptr = 0x10;
+  int out_ptr = 0;
+
+  int flag1 = 0;
+  int flag2 = 1;
+  int sum;
+  unsigned char last_byte = 0;
+  unsigned char nibble;
+
+  // ADPCM work variables
+  int sign;
+  int delta;
+  int step;
+  int diff;
+
+  pred1 = LE_16(&input[10]);
+  pred2 = LE_16(&input[12]);
+  SE_16BIT(pred1);
+  SE_16BIT(pred2);
+  sum = pred2;
+  index1 = input[14];
+  index2 = input[15];
+
+  while (in_ptr < 2048)
+  {
+    if (flag2)
+    {
+      last_byte = input[in_ptr++];
+      nibble = last_byte & 0x0F;
 
-static int counter = 0;
+      step = adpcm_step[index1];
+
+      sign = nibble & 8;
+      delta = nibble & 7;
+
+      diff = step >> 3;
+      if (delta & 4) diff += step;
+      if (delta & 2) diff += step >> 1;
+      if (delta & 1) diff += step >> 2;
+
+      if (sign)
+        pred1 -= diff;
+      else
+        pred1 += diff;
+
+      CLAMP_S16(pred1);
+
+      index1 += adpcm_index[nibble];
+      CLAMP_0_TO_88(index1);
+
+      if (flag1)
+        flag2 = 0;
+      else
+      {
+        nibble = (last_byte >> 4) & 0x0F;
+
+        step = adpcm_step[index2];
+
+        sign = nibble & 8;
+        delta = nibble & 7;
+
+        diff = step >> 3;
+        if (delta & 4) diff += step;
+        if (delta & 2) diff += step >> 1;
+        if (delta & 1) diff += step >> 2;
 
-  predictor_l = LE_16(&input[10]);
-  predictor_r = LE_16(&input[12]);
-  SE_16BIT(predictor_l);
-  SE_16BIT(predictor_r);
-  index_l = input[14];
-  index_r = input[15];
+        if (sign)
+          pred2 -= diff;
+        else
+          pred2 += diff;
+
+        CLAMP_S16(pred2);
+
+        index2 += adpcm_index[nibble];
+        CLAMP_0_TO_88(index2);
+
+        sum = (sum + pred2) / 2;
+      }
+      output[out_ptr++] = pred1 + sum;
+      output[out_ptr++] = pred1 - sum;
+
+      flag1 ^= 1;
+      if (in_ptr >= 2048)
+        break;
+    }
+    else
+    {
+      nibble = (last_byte >> 4) & 0x0F;
+
+      step = adpcm_step[index1];
+
+      sign = nibble & 8;
+      delta = nibble & 7;
+
+      diff = step >> 3;
+      if (delta & 4) diff += step;
+      if (delta & 2) diff += step >> 1;
+      if (delta & 1) diff += step >> 2;
+
+      if (sign)
+        pred1 -= diff;
+      else
+        pred1 += diff;
+
+      CLAMP_S16(pred1);
 
-  for (i = 16; i < FOX62_ADPCM_BLOCK_SIZE; i++)
-  {
-    output[(i - 16) * 2 + 0] = input[i] & 0x0F;
-    output[(i - 16) * 2 + 1] = (input[i] >> 4) & 0x0F;
+      index1 += adpcm_index[nibble];
+      CLAMP_0_TO_88(index1);
+
+      if (flag1)
+        flag2 = 1;
+      else
+      {
+        last_byte = input[in_ptr++];
+        nibble = last_byte & 0x0F;
+
+        step = adpcm_step[index2];
+
+        sign = nibble & 8;
+        delta = nibble & 7;
+
+        diff = step >> 3;
+        if (delta & 4) diff += step;
+        if (delta & 2) diff += step >> 1;
+        if (delta & 1) diff += step >> 2;
+
+        if (sign)
+          pred2 -= diff;
+        else
+          pred2 += diff;
+
+        CLAMP_S16(pred2);
+
+        index2 += adpcm_index[nibble];
+        CLAMP_0_TO_88(index2);
+
+        sum = (sum + pred2) / 2;
+      }
+
+      output[out_ptr++] = pred1 + sum;
+      output[out_ptr++] = pred1 - sum;
+
+      flag1 ^= 1;
+      if (in_ptr >= 2048)
+        break;
+    }
   }
 
-  decode_nibbles(output, FOX62_ADPCM_SAMPLES_PER_BLOCK * channels, channels,
-  predictor_l, index_l,
-  predictor_r, index_r);
-
-
-  for (i = 0; i < FOX62_ADPCM_SAMPLES_PER_BLOCK / 2; i += 2)
-  {
-    adjustment = (predictor_r + output[i + 1]) / 2;
-if (counter < 20)
-{
-printf ("(L, R) = %04X, %04X, prev_r = %04X, adjustment = %04X\n", 
-  output[i], output[i+1], predictor_r, adjustment);
-  counter++;
+  return out_ptr;
 }
-    predictor_r = output[i + 1];
-    output[i + 1] = output[i] - adjustment;
-    output[i] += adjustment;
-  }
-
-if (counter++ == 20)
-{
-printf (" after:\n");
-for (i = 0; i < 20; i++)
-  printf ("%04X\n", output[i]);
-}
-  return FOX62_ADPCM_SAMPLES_PER_BLOCK * channels;
-}
--- a/adpcm.h	Sat Jan 05 19:35:01 2002 +0000
+++ b/adpcm.h	Sun Jan 06 01:56:27 2002 +0000
@@ -18,14 +18,13 @@
 // pretend there's such a thing as mono for this format
 #define FOX62_ADPCM_PREAMBLE_SIZE 8
 #define FOX62_ADPCM_BLOCK_SIZE 0x400
-#define FOX62_ADPCM_SAMPLES_PER_BLOCK \
-  ((FOX62_ADPCM_BLOCK_SIZE - FOX62_ADPCM_PREAMBLE_SIZE) * 2)
+// this isn't exact
+#define FOX62_ADPCM_SAMPLES_PER_BLOCK 6000
 
 int ima_adpcm_decode_block(unsigned short *output, unsigned char *input,
   int channels);
 int ms_adpcm_decode_block(unsigned short *output, unsigned char *input,
   int channels, int block_size);
 int fox61_adpcm_decode_block(unsigned short *output, unsigned char *input);
-int fox62_adpcm_decode_block(unsigned short *output, unsigned char *input,
-  int channels);
+int fox62_adpcm_decode_block(unsigned short *output, unsigned char *input);
 #endif
--- a/dec_audio.c	Sat Jan 05 19:35:01 2002 +0000
+++ b/dec_audio.c	Sun Jan 06 01:56:27 2002 +0000
@@ -1153,7 +1153,7 @@
           FOX62_ADPCM_BLOCK_SIZE * sh_audio->wf->nChannels) 
           break; // EOF
         len = 2 * fox62_adpcm_decode_block(
-          (unsigned short*)buf,ibuf, sh_audio->wf->nChannels);
+          (unsigned short*)buf,ibuf);
         break;
       }
 #ifdef USE_LIBAC3
--- a/etc/codecs.conf	Sat Jan 05 19:35:01 2002 +0000
+++ b/etc/codecs.conf	Sun Jan 06 01:56:27 2002 +0000
@@ -346,7 +346,7 @@
 
 audiocodec fox62adpcm
   info "Format 0x62 ADPCM"
-  status buggy
+  status working
   format 0x62
   driver fox62adpcm