update adpcm interops with eyebeam 8k and 16k ADPCM

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@7570 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Brian West 2008-02-09 17:43:42 +00:00
parent 516ae82e87
commit c65319c4b3
3 changed files with 168 additions and 54 deletions

View File

@ -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@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 @@ static int16_t decode(ima_adpcm_state_t *s, uint8_t adpcm)
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 @@ static int16_t decode(ima_adpcm_state_t *s, uint8_t adpcm)
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 @@ static uint8_t encode(ima_adpcm_state_t *s, int16_t linear)
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 @@ ima_adpcm_state_t *ima_adpcm_init(ima_adpcm_state_t *s, int variant)
/*endif*/
memset(s, 0, sizeof(*s));
s->variant = variant;
s->chunk_size = chunk_size;
return s;
}
/*- End of function --------------------------------------------------------*/
@ -266,11 +305,50 @@ int ima_adpcm_decode(ima_adpcm_state_t *s,
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 @@ int ima_adpcm_decode(ima_adpcm_state_t *s,
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 @@ int ima_adpcm_encode(ima_adpcm_state_t *s,
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 @@ int ima_adpcm_encode(ima_adpcm_state_t *s,
}
/*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 --------------------------------------------------------*/

View File

@ -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 @@ IMA ADPCM offers a good balance of simplicity and quality at a rate of
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 @@ enum
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 @@ extern "C"
/*! 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.

View File

@ -496,10 +496,10 @@ static switch_status_t switch_adpcm_init(switch_codec_t *codec, switch_codec_fla
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 @@ static switch_status_t switch_adpcm_decode(switch_codec_t *codec,
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 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_voipcodecs_load)
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);
}