[Freeswitch-svn] [commit] r7570 - in freeswitch/trunk: libs/voipcodecs/src libs/voipcodecs/src/voipcodecs src/mod/codecs/mod_voipcodecs

Freeswitch SVN brian at freeswitch.org
Sat Feb 9 12:43:42 EST 2008


Author: brian
Date: Sat Feb  9 12:43:42 2008
New Revision: 7570

Modified:
   freeswitch/trunk/libs/voipcodecs/src/ima_adpcm.c
   freeswitch/trunk/libs/voipcodecs/src/voipcodecs/ima_adpcm.h
   freeswitch/trunk/src/mod/codecs/mod_voipcodecs/mod_voipcodecs.c

Log:
update adpcm interops with eyebeam 8k and 16k ADPCM

Modified: freeswitch/trunk/libs/voipcodecs/src/ima_adpcm.c
==============================================================================
--- freeswitch/trunk/libs/voipcodecs/src/ima_adpcm.c	(original)
+++ freeswitch/trunk/libs/voipcodecs/src/ima_adpcm.c	Sat Feb  9 12:43:42 2008
@@ -1,8 +1,8 @@
 /*
- * VoIPcodecs - a series of DSP components for telephony
+ * SpanDSP - a series of DSP components for telephony
  *
  * ima_adpcm.c - Conversion routines between linear 16 bit PCM data and
- *                 IMA/DVI/Intel ADPCM format.
+ *               IMA/DVI/Intel ADPCM format.
  *
  * Written by Steve Underwood <steveu at coppice.org>
  *
@@ -11,8 +11,9 @@
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1, as
- * published by the Free Software Foundation.
+ * it under the terms of the GNU General Public License version 2, or
+ * the Lesser GNU General Public License version 2.1, as published by
+ * the Free Software Foundation.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -23,7 +24,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: ima_adpcm.c,v 1.18 2006/11/30 15:41:47 steveu Exp $
+ * $Id: ima_adpcm.c,v 1.21 2008/02/09 15:33:40 steveu Exp $
  */
 
 /*! \file */
@@ -42,9 +43,9 @@
 #include <math.h>
 #endif
 
-#include "voipcodecs/telephony.h"
-#include "voipcodecs/dc_restore.h"
-#include "voipcodecs/ima_adpcm.h"
+#include "spandsp/telephony.h"
+#include "spandsp/dc_restore.h"
+#include "spandsp/ima_adpcm.h"
 
 /*
  * Intel/DVI ADPCM coder/decoder.
@@ -76,8 +77,46 @@
  * Any left over bits in the last octet of an encoded burst are set to one.
  */
 
+/*
+   DVI4 uses an adaptive delta pulse code modulation (ADPCM) encoding
+   scheme that was specified by the Interactive Multimedia Association
+   (IMA) as the "IMA ADPCM wave type".  However, the encoding defined
+   here as DVI4 differs in three respects from the IMA specification:
+
+   o  The RTP DVI4 header contains the predicted value rather than the
+      first sample value contained the IMA ADPCM block header.
+
+   o  IMA ADPCM blocks contain an odd number of samples, since the first
+      sample of a block is contained just in the header (uncompressed),
+      followed by an even number of compressed samples.  DVI4 has an
+      even number of compressed samples only, using the `predict' word
+      from the header to decode the first sample.
+
+   o  For DVI4, the 4-bit samples are packed with the first sample in
+      the four most significant bits and the second sample in the four
+      least significant bits.  In the IMA ADPCM codec, the samples are
+      packed in the opposite order.
+
+   Each packet contains a single DVI block.  This profile only defines
+   the 4-bit-per-sample version, while IMA also specified a 3-bit-per-
+   sample encoding.
+
+   The "header" word for each channel has the following structure:
+
+      int16  predict;  // predicted value of first sample
+                       // from the previous block (L16 format)
+      u_int8 index;    // current index into stepsize table
+      u_int8 reserved; // set to zero by sender, ignored by receiver
+
+   Each octet following the header contains two 4-bit samples, thus the
+   number of samples per packet MUST be even because there is no means
+   to indicate a partially filled last octet.
+*/
+
+#define STEP_MAX 88
+
 /* Intel ADPCM step variation table */
-static const int step_size[89] =
+static const int step_size[STEP_MAX + 1] =
 {
         7,     8,     9,   10,     11,    12,    13,    14,    16,    17,
        19,    21,    23,   25,     28,    31,    34,    37,    41,    45,
@@ -151,7 +190,6 @@
     int16_t linear;
 
     /* e = (adpcm+0.5)*step/4 */
-
     ss = step_size[s->step_index];
     e = ss >> 3;
     if (adpcm & 0x01)
@@ -171,8 +209,8 @@
     s->step_index += step_adjustment[adpcm & 0x07];
     if (s->step_index < 0)
         s->step_index = 0;
-    else if (s->step_index > 88)
-        s->step_index = 88;
+    else if (s->step_index > STEP_MAX)
+        s->step_index = STEP_MAX;
     /*endif*/
     return linear;
 }
@@ -227,14 +265,14 @@
     s->step_index += step_adjustment[adpcm & 0x07];
     if (s->step_index < 0)
         s->step_index = 0;
-    else if (s->step_index > 88)
-        s->step_index = 88;
+    else if (s->step_index > STEP_MAX)
+        s->step_index = STEP_MAX;
     /*endif*/
     return (uint8_t) adpcm;
 }
 /*- End of function --------------------------------------------------------*/
 
-ima_adpcm_state_t *ima_adpcm_init(ima_adpcm_state_t *s, int variant)
+ima_adpcm_state_t *ima_adpcm_init(ima_adpcm_state_t *s, int variant, int chunk_size)
 {
     if (s == NULL)
     {
@@ -244,6 +282,7 @@
     /*endif*/
     memset(s, 0, sizeof(*s));
     s->variant = variant;
+    s->chunk_size = chunk_size;
     return  s;
 }
 /*- End of function --------------------------------------------------------*/
@@ -266,11 +305,50 @@
     uint16_t code;
 
     samples = 0;
-    if (s->variant == IMA_ADPCM_VDVI)
+    switch (s->variant)
     {
+    case IMA_ADPCM_IMA4:
+        i = 0;
+        if (s->chunk_size == 0)
+        {
+            amp[samples++] = (ima_data[1] << 8) | ima_data[0];
+            s->step_index = ima_data[2];
+            s->last = amp[0];
+            i = 4;
+        }
+        for (  ;  i < ima_bytes;  i++)
+        {
+            amp[samples++] = decode(s, ima_data[i] & 0xF);
+            amp[samples++] = decode(s, (ima_data[i] >> 4) & 0xF);
+        }
+        /*endfor*/
+        break;
+    case IMA_ADPCM_DVI4:
+        i = 0;
+        if (s->chunk_size == 0)
+        {
+            s->last = (int16_t) ((ima_data[0] << 8) | ima_data[1]);
+            s->step_index = ima_data[2];
+            i = 4;
+        }
+        for (  ;  i < ima_bytes;  i++)
+        {
+            amp[samples++] = decode(s, (ima_data[i] >> 4) & 0xF);
+            amp[samples++] = decode(s, ima_data[i] & 0xF);
+        }
+        /*endfor*/
+        break;
+    case IMA_ADPCM_VDVI:
+        i = 0;
+        if (s->chunk_size == 0)
+        {
+            s->last = (int16_t) ((ima_data[0] << 8) | ima_data[1]);
+            s->step_index = ima_data[2];
+            i = 4;
+        }
         code = 0;
         s->bits = 0;
-        for (i = 0;  ;  )
+        for (;;)
         {
             if (s->bits <= 8)
             {
@@ -321,18 +399,10 @@
             code <<= vdvi_decode[j].bits;
             s->bits -= vdvi_decode[j].bits;
         }
-        /*endfor*/
-    }
-    else
-    {
-        for (i = 0;  i < ima_bytes;  i++)
-        {
-            amp[samples++] = decode(s, ima_data[i] & 0xF);
-            amp[samples++] = decode(s, (ima_data[i] >> 4) & 0xF);
-        }
         /*endwhile*/
+        break;
     }
-    /*endif*/
+    /*endswitch*/
     return samples;
 }
 /*- End of function --------------------------------------------------------*/
@@ -347,8 +417,54 @@
     uint8_t code;
 
     bytes = 0;
-    if (s->variant == IMA_ADPCM_VDVI)
+    switch (s->variant)
     {
+    case IMA_ADPCM_IMA4:
+        i = 0;
+        if (s->chunk_size == 0)
+        {
+            ima_data[bytes++] = amp[1];
+            ima_data[bytes++] = amp[1] >> 8;
+            ima_data[bytes++] = s->step_index;
+            ima_data[bytes++] = 0;
+            s->last = amp[1];
+            s->bits = 0;
+            i = 1;
+        }
+        for (  ;  i < len;  i++)
+        {
+            s->ima_byte = (uint8_t) ((s->ima_byte >> 4) | (encode(s, amp[i]) << 4));
+            if ((s->bits++ & 1))
+                ima_data[bytes++] = (uint8_t) s->ima_byte;
+            /*endif*/
+        }
+        /*endfor*/
+        break;
+    case IMA_ADPCM_DVI4:
+        if (s->chunk_size == 0)
+        {
+            ima_data[bytes++] = s->last >> 8;
+            ima_data[bytes++] = s->last;
+            ima_data[bytes++] = s->step_index;
+            ima_data[bytes++] = 0;
+        }
+        for (i = 0;  i < len;  i++)
+        {
+            s->ima_byte = (uint8_t) ((s->ima_byte << 4) | encode(s, amp[i]));
+            if ((s->bits++ & 1))
+                ima_data[bytes++] = (uint8_t) s->ima_byte;
+            /*endif*/
+        }
+        /*endfor*/
+        break;
+    case IMA_ADPCM_VDVI:
+        if (s->chunk_size == 0)
+        {
+            ima_data[bytes++] = s->last >> 8;
+            ima_data[bytes++] = s->last;
+            ima_data[bytes++] = s->step_index;
+            ima_data[bytes++] = 0;
+        }
         s->bits = 0;
         for (i = 0;  i < len;  i++)
         {
@@ -364,23 +480,11 @@
         }
         /*endfor*/
         if (s->bits)
-        {
             ima_data[bytes++] = (uint8_t) (((s->ima_byte << 8) | 0xFF) >> s->bits);
-        }
         /*endif*/
+        break;
     }
-    else
-    {
-        for (i = 0;  i < len;  i++)
-        {
-            s->ima_byte = (uint8_t) ((s->ima_byte >> 4) | (encode(s, amp[i]) << 4));
-            if ((s->bits++ & 1))
-                ima_data[bytes++] = (uint8_t) s->ima_byte;
-            /*endif*/
-        }
-        /*endfor*/
-    }
-    /*endif*/
+    /*endswitch*/
     return  bytes;
 }
 /*- End of function --------------------------------------------------------*/

Modified: freeswitch/trunk/libs/voipcodecs/src/voipcodecs/ima_adpcm.h
==============================================================================
--- freeswitch/trunk/libs/voipcodecs/src/voipcodecs/ima_adpcm.h	(original)
+++ freeswitch/trunk/libs/voipcodecs/src/voipcodecs/ima_adpcm.h	Sat Feb  9 12:43:42 2008
@@ -14,8 +14,9 @@
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1, as
- * published by the Free Software Foundation.
+ * it under the terms of the GNU General Public License version 2, or
+ * the Lesser GNU General Public License version 2.1, as published by
+ * the Free Software Foundation.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -26,7 +27,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: ima_adpcm.h,v 1.16 2007/12/13 11:31:32 steveu Exp $
+ * $Id: ima_adpcm.h,v 1.18 2008/02/09 15:33:40 steveu Exp $
  */
 
 /*! \file */
@@ -46,8 +47,12 @@
 
 enum
 {
-    IMA_ADPCM_DVI4 = 0,
-    IMA_ADPCM_VDVI = 1
+    /*! IMA4 is the original IMA ADPCM variant */
+    IMA_ADPCM_IMA4 = 0,
+    /*! DVI4 is the IMA ADPCM variant defined in RFC3551 */
+    IMA_ADPCM_DVI4 = 1,
+    /*! VDVI is the variable bit rate IMA ADPCM variant defined in RFC3551 */
+    IMA_ADPCM_VDVI = 2
 };
 
 /*!
@@ -58,6 +63,8 @@
 typedef struct
 {
     int variant;
+    /*! \brief The size of a chunk, in samples. */
+    int chunk_size;
     /*! \brief The last state of the ADPCM algorithm. */
     int last;
     /*! \brief Current index into the step size table. */
@@ -75,8 +82,11 @@
 /*! Initialise an IMA ADPCM encode or decode context.
     \param s The IMA ADPCM context
     \param variant ???
+    \param chunk_size The size of a chunk, in samples. A chunk size of
+           zero sample samples means treat each encode or decode operation
+           as a chunk.
     \return A pointer to the IMA ADPCM context, or NULL for error. */
-ima_adpcm_state_t *ima_adpcm_init(ima_adpcm_state_t *s, int variant);
+ima_adpcm_state_t *ima_adpcm_init(ima_adpcm_state_t *s, int variant, int chunk_size);
 
 /*! Free an IMA ADPCM encode or decode context.
     \param s The IMA ADPCM context.

Modified: freeswitch/trunk/src/mod/codecs/mod_voipcodecs/mod_voipcodecs.c
==============================================================================
--- freeswitch/trunk/src/mod/codecs/mod_voipcodecs/mod_voipcodecs.c	(original)
+++ freeswitch/trunk/src/mod/codecs/mod_voipcodecs/mod_voipcodecs.c	Sat Feb  9 12:43:42 2008
@@ -496,10 +496,10 @@
 		return SWITCH_STATUS_FALSE;
 	} else {
 		if (encoding) {
-			ima_adpcm_init(&context->encoder_object, IMA_ADPCM_DVI4);
+			ima_adpcm_init(&context->encoder_object, IMA_ADPCM_DVI4, 0);
 		}
 		if (decoding) {
-			ima_adpcm_init(&context->decoder_object, IMA_ADPCM_DVI4);
+			ima_adpcm_init(&context->decoder_object, IMA_ADPCM_DVI4, 0);
  		}
 		
 		codec->private_info = context;
@@ -538,7 +538,7 @@
 		return SWITCH_STATUS_FALSE;
 	}
 
-	*decoded_data_len = (2 * ima_adpcm_decode(&context->decoder_object, (int16_t *) decoded_data, (uint8_t *) encoded_data, encoded_data_len));
+	*decoded_data_len = ima_adpcm_decode(&context->decoder_object, (int16_t *) decoded_data, (uint8_t *) encoded_data, encoded_data_len);
 
 	return SWITCH_STATUS_SUCCESS;
 }
@@ -567,14 +567,14 @@
     for (count = 12; count > 0; count--) {
         switch_core_codec_add_implementation(pool, codec_interface,
                                              SWITCH_CODEC_TYPE_AUDIO, 5, "DVI4", NULL, 8000, 8000, 32000,
-                                             mpf * count, spf * count, bpf * count, ebpf * count, 1, 1, 12,
+                                             mpf * count, spf * count, bpf * count, (ebpf * count) + 4, 1, 1, 12,
                                              switch_adpcm_init, switch_adpcm_encode, switch_adpcm_decode, switch_adpcm_destroy);
     }
-	mpf = 10000, spf = 160, bpf = 360, ebpf = 160;
+	mpf = 10000, spf = 160, bpf = 320, ebpf = 160;
     for (count = 12; count > 0; count--) {
         switch_core_codec_add_implementation(pool, codec_interface,
                                              SWITCH_CODEC_TYPE_AUDIO, 6, "DVI4", NULL, 16000, 16000, 64000,
-                                             mpf * count, spf * count, bpf * count, ebpf * count, 1, 1, 12,
+                                             mpf * count, spf * count, bpf * count, (ebpf * count) + 4, 1, 1, 12,
                                              switch_adpcm_init, switch_adpcm_encode, switch_adpcm_decode, switch_adpcm_destroy);
     }
 



More information about the Freeswitch-svn mailing list