aboutsummaryrefslogtreecommitdiffstats
path: root/codecs
diff options
context:
space:
mode:
authorkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2006-04-08 21:40:57 +0000
committerkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2006-04-08 21:40:57 +0000
commitf1822bc2a6fdfea0a2fa629a0dc70336f22af185 (patch)
tree380e359c10d849c23bbe9bef0990dad66bdffdd2 /codecs
parent5adcee992f51b2ae0e6bd74e5f82a6b2a37e85d3 (diff)
merge rizzo's codec module rework (very similar to the format module rework)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@18541 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'codecs')
-rw-r--r--codecs/codec_a_mu.c235
-rw-r--r--codecs/codec_adpcm.c369
-rw-r--r--codecs/codec_alaw.c338
-rw-r--r--codecs/codec_g723_1.c270
-rw-r--r--codecs/codec_g726.c486
-rw-r--r--codecs/codec_gsm.c298
-rw-r--r--codecs/codec_ilbc.c239
-rw-r--r--codecs/codec_lpc10.c311
-rw-r--r--codecs/codec_speex.c588
-rw-r--r--codecs/codec_ulaw.c320
10 files changed, 1039 insertions, 2415 deletions
diff --git a/codecs/codec_a_mu.c b/codecs/codec_a_mu.c
index f03612b13..4d05891c2 100644
--- a/codecs/codec_a_mu.c
+++ b/codecs/codec_a_mu.c
@@ -43,12 +43,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/ulaw.h"
#include "asterisk/utils.h"
-#define BUFFER_SIZE 8096 /* size for the translation buffers */
-
-AST_MUTEX_DEFINE_STATIC(localuser_lock);
-static int localusecnt = 0;
-
-static char *tdesc = "A-law and Mulaw direct Coder/Decoder";
+#define BUFFER_SAMPLES 8000 /* size for the translation buffers */
static unsigned char mu2a[256];
static unsigned char a2mu[256];
@@ -57,146 +52,37 @@ static unsigned char a2mu[256];
#include "ulaw_slin_ex.h"
-/*
- * Private workspace for translating signed linear signals to alaw.
- */
-
-struct alaw_encoder_pvt
-{
- struct ast_frame f;
- char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
- unsigned char outbuf[BUFFER_SIZE]; /* Encoded alaw, two nibbles to a word */
- int tail;
-};
-
-/*
- * Private workspace for translating laws.
- */
-
-struct ulaw_encoder_pvt
-{
- struct ast_frame f;
- char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
- unsigned char outbuf[BUFFER_SIZE]; /* Encoded ulaw values */
- int tail;
-};
-
-static struct ast_translator_pvt *alawtoulaw_new(void)
-{
- struct ulaw_encoder_pvt *tmp;
-
- if ((tmp = ast_calloc(1, sizeof(*tmp)))) {
- tmp->tail = 0;
- localusecnt++;
- ast_update_use_count();
- }
-
- return (struct ast_translator_pvt *)tmp;
-}
-
-static struct ast_translator_pvt *ulawtoalaw_new(void)
-{
- struct alaw_encoder_pvt *tmp;
-
- if ((tmp = ast_calloc(1, sizeof(*tmp)))) {
- localusecnt++;
- ast_update_use_count();
- tmp->tail = 0;
- }
-
- return (struct ast_translator_pvt *)tmp;
-}
-
-static int alawtoulaw_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
+/*! \brief convert frame data and store into the buffer */
+static int alawtoulaw_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
- struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *)pvt;
int x;
- unsigned char *b;
+ unsigned char *src = f->data;
+ unsigned char *dst = (unsigned char *)pvt->outbuf + pvt->samples;
- if ((tmp->tail + f->datalen) > sizeof(tmp->outbuf)) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
-
- /* Reset ssindex and signal to frame's specified values */
- b = f->data;
- for (x=0;x<f->datalen;x++)
- tmp->outbuf[tmp->tail + x] = a2mu[b[x]];
-
- tmp->tail += f->datalen;
+ for ( x = 0 ; x < f->samples; x++)
+ dst[x] = a2mu[src[x]];
+ pvt->samples += f->samples;
+ pvt->datalen += f->datalen;
return 0;
}
-static struct ast_frame *alawtoulaw_frameout(struct ast_translator_pvt *pvt)
-{
- struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *)pvt;
-
- if (!tmp->tail)
- return NULL;
-
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_ULAW;
- tmp->f.datalen = tmp->tail;
- tmp->f.samples = tmp->tail;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->outbuf;
- tmp->tail = 0;
- return &tmp->f;
-}
-
-static int ulawtoalaw_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
+/*! \brief convert frame data and store into the buffer */
+static int ulawtoalaw_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
- struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *)pvt;
int x;
- unsigned char *s;
- if (tmp->tail + f->datalen >= sizeof(tmp->outbuf)) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
- s = f->data;
- for (x=0;x<f->datalen;x++)
- tmp->outbuf[x+tmp->tail] = mu2a[s[x]];
- tmp->tail += f->datalen;
- return 0;
-}
-
-/*
- * LinToalaw_FrameOut
- * Convert a buffer of raw 16-bit signed linear PCM to a buffer
- * of 4-bit alaw packed two to a byte (Big Endian).
- *
- * Results:
- * Foo
- *
- * Side effects:
- * Leftover inbuf data gets packed, tail gets updated.
- */
+ unsigned char *src = f->data;
+ unsigned char *dst = (unsigned char *)pvt->outbuf + pvt->samples;
-static struct ast_frame *ulawtoalaw_frameout(struct ast_translator_pvt *pvt)
-{
- struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *)pvt;
-
- if (tmp->tail) {
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_ALAW;
- tmp->f.samples = tmp->tail;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->outbuf;
- tmp->f.datalen = tmp->tail;
- tmp->tail = 0;
- return &tmp->f;
- } else
- return NULL;
+ for ( x = 0 ; x < f->samples; x++)
+ dst[x] = mu2a[src[x]];
+ pvt->samples += f->samples;
+ pvt->datalen += f->datalen;
+ return 0;
}
/*
- * alawToLin_Sample
+ * alawToLin_Sample. Just random data, somehow...
*/
-
static struct ast_frame *alawtoulaw_sample(void)
{
static struct ast_frame f;
@@ -207,7 +93,7 @@ static struct ast_frame *alawtoulaw_sample(void)
f.mallocd = 0;
f.offset = 0;
f.src = __PRETTY_FUNCTION__;
- f.data = ulaw_slin_ex;
+ f.data = ulaw_slin_ex; /* XXX what ? */
return &f;
}
@@ -225,66 +111,41 @@ static struct ast_frame *ulawtoalaw_sample(void)
return &f;
}
-/*
- * alaw_Destroy
- * Destroys a private workspace.
- *
- * Results:
- * It's gone!
- *
- * Side effects:
- * None.
- */
-
-static void alaw_destroy(struct ast_translator_pvt *pvt)
-{
- free(pvt);
- localusecnt--;
- ast_update_use_count();
-}
-
-/*
- * The complete translator for alawToLin.
- */
+static struct ast_module_lock me = { .usecnt = -1 };
static struct ast_translator alawtoulaw = {
- "alawtoulaw",
- AST_FORMAT_ALAW,
- AST_FORMAT_ULAW,
- alawtoulaw_new,
- alawtoulaw_framein,
- alawtoulaw_frameout,
- alaw_destroy,
- /* NULL */
- alawtoulaw_sample
+ .name = "alawtoulaw",
+ .srcfmt = AST_FORMAT_ALAW,
+ .dstfmt = AST_FORMAT_ULAW,
+ .framein = alawtoulaw_framein,
+ .sample = alawtoulaw_sample,
+ .buffer_samples = BUFFER_SAMPLES,
+ .buf_size = BUFFER_SAMPLES,
+ .lockp = &me,
};
-/*
- * The complete translator for LinToalaw.
- */
-
static struct ast_translator ulawtoalaw = {
- "ulawtoalaw",
- AST_FORMAT_ULAW,
- AST_FORMAT_ALAW,
- ulawtoalaw_new,
- ulawtoalaw_framein,
- ulawtoalaw_frameout,
- alaw_destroy,
- /* NULL */
- ulawtoalaw_sample
+ .name = "ulawtoalaw",
+ .srcfmt = AST_FORMAT_ULAW,
+ .dstfmt = AST_FORMAT_ALAW,
+ .framein = ulawtoalaw_framein,
+ .sample = ulawtoalaw_sample,
+ .buffer_samples = BUFFER_SAMPLES,
+ .buf_size = BUFFER_SAMPLES,
+ .lockp = &me,
};
+/*! \brief standard module glue */
+
int unload_module(void)
{
int res;
- ast_mutex_lock(&localuser_lock);
+ ast_mutex_lock(&me.lock);
res = ast_unregister_translator(&ulawtoalaw);
- if (!res)
- res = ast_unregister_translator(&alawtoulaw);
- if (localusecnt)
+ res |= ast_unregister_translator(&alawtoulaw);
+ if (me.usecnt)
res = -1;
- ast_mutex_unlock(&localuser_lock);
+ ast_mutex_unlock(&me.lock);
return res;
}
@@ -304,20 +165,14 @@ int load_module(void)
return res;
}
-/*
- * Return a description of this module.
- */
-
char *description(void)
{
- return tdesc;
+ return "A-law and Mulaw direct Coder/Decoder";
}
int usecount(void)
{
- int res;
- OLD_STANDARD_USECOUNT(res);
- return res;
+ return me.usecnt;
}
char *key()
diff --git a/codecs/codec_adpcm.c b/codecs/codec_adpcm.c
index 19970a501..192ae1050 100644
--- a/codecs/codec_adpcm.c
+++ b/codecs/codec_adpcm.c
@@ -40,6 +40,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/logger.h"
+#include "asterisk/linkedlists.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/options.h"
@@ -50,14 +51,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
/* define NOT_BLI to use a faster but not bit-level identical version */
/* #define NOT_BLI */
-#define BUFFER_SIZE 8096 /* size for the translation buffers */
-
-AST_MUTEX_DEFINE_STATIC(localuser_lock);
-static int localusecnt = 0;
-
-static char *tdesc = "Adaptive Differential PCM Coder/Decoder";
-
-static int useplc = 0;
+#define BUFFER_SAMPLES 8096 /* size for the translation buffers */
/* Sample frame data */
@@ -227,250 +221,81 @@ static inline int adpcm(short csig, struct adpcm_state *state)
return encoded;
}
-/*
- * Private workspace for translating signed linear signals to ADPCM.
- */
+/*----------------- Asterisk-codec glue ------------*/
-struct adpcm_encoder_pvt
-{
- struct ast_frame f;
- char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
- short inbuf[BUFFER_SIZE]; /* Unencoded signed linear values */
- unsigned char outbuf[BUFFER_SIZE]; /* Encoded ADPCM, two nibbles to a word */
+/*! \brief Workspace for translating signed linear signals to ADPCM. */
+struct adpcm_encoder_pvt {
struct adpcm_state state;
- int tail;
+ int16_t inbuf[BUFFER_SAMPLES]; /* Unencoded signed linear values */
};
-/*
- * Private workspace for translating ADPCM signals to signed linear.
- */
-
-struct adpcm_decoder_pvt
-{
- struct ast_frame f;
- char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
- short outbuf[BUFFER_SIZE]; /* Decoded signed linear values */
+/*! \brief Workspace for translating ADPCM signals to signed linear. */
+struct adpcm_decoder_pvt {
struct adpcm_state state;
- int tail;
- plc_state_t plc;
};
-/*
- * AdpcmToLin_New
- * Create a new instance of adpcm_decoder_pvt.
- *
- * Results:
- * Returns a pointer to the new instance.
- *
- * Side effects:
- * None.
- */
-
-static struct ast_translator_pvt *adpcmtolin_new(void)
+/*! \brief decode 4-bit adpcm frame data and store in output buffer */
+static int adpcmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
- struct adpcm_decoder_pvt *tmp;
-
- if ((tmp = ast_calloc(1, sizeof(*tmp)))) {
- tmp->tail = 0;
- plc_init(&tmp->plc);
- localusecnt++;
- ast_update_use_count();
- }
-
- return (struct ast_translator_pvt *)tmp;
-}
-
-/*
- * LinToAdpcm_New
- * Create a new instance of adpcm_encoder_pvt.
- *
- * Results:
- * Returns a pointer to the new instance.
- *
- * Side effects:
- * None.
- */
-
-static struct ast_translator_pvt *lintoadpcm_new(void)
-{
- struct adpcm_encoder_pvt *tmp;
-
- if ((tmp = ast_calloc(1, sizeof(*tmp)))) {
- localusecnt++;
- ast_update_use_count();
- tmp->tail = 0;
- }
-
- return (struct ast_translator_pvt *)tmp;
-}
-
-/*
- * AdpcmToLin_FrameIn
- * Take an input buffer with packed 4-bit ADPCM values and put decoded PCM in outbuf,
- * if there is room left.
- *
- * Results:
- * Foo
- *
- * Side effects:
- * tmp->tail is the number of packed values in the buffer.
- */
-
-static int adpcmtolin_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
-{
- struct adpcm_decoder_pvt *tmp = (struct adpcm_decoder_pvt *)pvt;
+ struct adpcm_decoder_pvt *tmp = pvt->pvt;
int x;
- unsigned char *b;
+ unsigned char *src = f->data;
+ int16_t *dst = (int16_t *)pvt->outbuf + pvt->samples;
- if(f->datalen == 0) { /* perform PLC with nominal framesize of 20ms/160 samples */
- if((tmp->tail + 160) > sizeof(tmp->outbuf) / 2) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
- if(useplc) {
- plc_fillin(&tmp->plc, tmp->outbuf+tmp->tail, 160);
- tmp->tail += 160;
- }
- return 0;
+ for (x=0; x < f->datalen; x++) {
+ *dst++ = decode((src[x] >> 4) & 0xf, &tmp->state);
+ *dst++ = decode(src[x] & 0x0f, &tmp->state);
}
-
- if (f->datalen * 4 + tmp->tail * 2 > sizeof(tmp->outbuf)) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
-
- b = f->data;
-
- for (x=0;x<f->datalen;x++) {
- tmp->outbuf[tmp->tail++] = decode((b[x] >> 4) & 0xf, &tmp->state);
- tmp->outbuf[tmp->tail++] = decode(b[x] & 0x0f, &tmp->state);
- }
-
- if(useplc)
- plc_rx(&tmp->plc, tmp->outbuf+tmp->tail-f->datalen*2, f->datalen*2);
-
+ pvt->samples += f->samples;
+ pvt->datalen += 2*f->samples;
return 0;
}
-/*
- * AdpcmToLin_FrameOut
- * Convert 4-bit ADPCM encoded signals to 16-bit signed linear.
- *
- * Results:
- * Converted signals are placed in tmp->f.data, tmp->f.datalen
- * and tmp->f.samples are calculated.
- *
- * Side effects:
- * None.
- */
-
-static struct ast_frame *adpcmtolin_frameout(struct ast_translator_pvt *pvt)
+/*! \brief fill input buffer with 16-bit signed linear PCM values. */
+static int lintoadpcm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
- struct adpcm_decoder_pvt *tmp = (struct adpcm_decoder_pvt *)pvt;
-
- if (!tmp->tail)
- return NULL;
-
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_SLINEAR;
- tmp->f.datalen = tmp->tail * 2;
- tmp->f.samples = tmp->tail;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->outbuf;
- tmp->tail = 0;
- return &tmp->f;
-}
+ struct adpcm_encoder_pvt *tmp = pvt->pvt;
-/*
- * LinToAdpcm_FrameIn
- * Fill an input buffer with 16-bit signed linear PCM values.
- *
- * Results:
- * None.
- *
- * Side effects:
- * tmp->tail is number of signal values in the input buffer.
- */
-
-static int lintoadpcm_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
-{
- struct adpcm_encoder_pvt *tmp = (struct adpcm_encoder_pvt *)pvt;
-
- if ((tmp->tail + f->datalen / 2) < (sizeof(tmp->inbuf) / 2)) {
- memcpy(&tmp->inbuf[tmp->tail], f->data, f->datalen);
- tmp->tail += f->datalen / 2;
- } else {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
+ memcpy(&tmp->inbuf[pvt->samples], f->data, f->datalen);
+ pvt->samples += f->samples;
return 0;
}
-/*
- * LinToAdpcm_FrameOut
- * Convert a buffer of raw 16-bit signed linear PCM to a buffer
- * of 4-bit ADPCM packed two to a byte (Big Endian).
- *
- * Results:
- * Foo
- *
- * Side effects:
- * Leftover inbuf data gets packed, tail gets updated.
- */
-
-static struct ast_frame *lintoadpcm_frameout(struct ast_translator_pvt *pvt)
+/*! \brief convert inbuf and store into frame */
+static struct ast_frame *lintoadpcm_frameout(struct ast_trans_pvt *pvt)
{
- struct adpcm_encoder_pvt *tmp = (struct adpcm_encoder_pvt *)pvt;
- int i_max, i;
+ struct adpcm_encoder_pvt *tmp = pvt->pvt;
+ struct ast_frame *f;
+ int i;
+ int samples = pvt->samples; /* save original number */
- if (tmp->tail < 2)
+ if (samples < 2)
return NULL;
- i_max = tmp->tail & ~1; /* atomic size is 2 samples */
-
- /* What is this, state debugging? should be #ifdef'd then
- tmp->outbuf[0] = tmp->ssindex & 0xff;
- tmp->outbuf[1] = (tmp->signal >> 8) & 0xff;
- tmp->outbuf[2] = (tmp->signal & 0xff);
- tmp->outbuf[3] = tmp->zero_count;
- tmp->outbuf[4] = tmp->next_flag;
- */
- for (i = 0; i < i_max; i+=2) {
- tmp->outbuf[i/2] =
+ pvt->samples &= ~1; /* atomic size is 2 samples */
+
+ for (i = 0; i < pvt->samples; i += 2) {
+ pvt->outbuf[i/2] =
(adpcm(tmp->inbuf[i ], &tmp->state) << 4) |
(adpcm(tmp->inbuf[i+1], &tmp->state) );
};
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_ADPCM;
- tmp->f.samples = i_max;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->outbuf;
- tmp->f.datalen = i_max / 2;
+ f = ast_trans_frameout(pvt, pvt->samples/2, 0);
/*
- * If there is a signal left over (there should be no more than
- * one) move it to the beginning of the input buffer.
+ * If there is a left over sample, move it to the beginning
+ * of the input buffer.
*/
- if (tmp->tail == i_max)
- tmp->tail = 0;
- else {
- tmp->inbuf[0] = tmp->inbuf[tmp->tail];
- tmp->tail = 1;
+ if (samples & 1) { /* move the leftover sample at beginning */
+ tmp->inbuf[0] = tmp->inbuf[samples - 1];
+ pvt->samples = 1;
}
- return &tmp->f;
+ return f;
}
-/*
- * AdpcmToLin_Sample
- */
-
+/*! \brief AdpcmToLin_Sample */
static struct ast_frame *adpcmtolin_sample(void)
{
static struct ast_frame f;
@@ -485,10 +310,7 @@ static struct ast_frame *adpcmtolin_sample(void)
return &f;
}
-/*
- * LinToAdpcm_Sample
- */
-
+/*! \brief LinToAdpcm_Sample */
static struct ast_frame *lintoadpcm_sample(void)
{
static struct ast_frame f;
@@ -504,75 +326,51 @@ static struct ast_frame *lintoadpcm_sample(void)
return &f;
}
-/*
- * Adpcm_Destroy
- * Destroys a private workspace.
- *
- * Results:
- * It's gone!
- *
- * Side effects:
- * None.
- */
-
-static void adpcm_destroy(struct ast_translator_pvt *pvt)
-{
- free(pvt);
- localusecnt--;
- ast_update_use_count();
-}
-
-/*
- * The complete translator for ADPCMToLin.
- */
+struct ast_module_lock me = { .usecnt = -1 };
static struct ast_translator adpcmtolin = {
- "adpcmtolin",
- AST_FORMAT_ADPCM,
- AST_FORMAT_SLINEAR,
- adpcmtolin_new,
- adpcmtolin_framein,
- adpcmtolin_frameout,
- adpcm_destroy,
- /* NULL */
- adpcmtolin_sample
+ .name = "adpcmtolin",
+ .srcfmt = AST_FORMAT_ADPCM,
+ .dstfmt = AST_FORMAT_SLINEAR,
+ .framein = adpcmtolin_framein,
+ .sample = adpcmtolin_sample,
+ .desc_size = sizeof(struct adpcm_decoder_pvt),
+ .buffer_samples = BUFFER_SAMPLES,
+ .buf_size = BUFFER_SAMPLES * 2,
+ .plc_samples = 160,
+ .lockp = &me,
};
-/*
- * The complete translator for LinToADPCM.
- */
-
static struct ast_translator lintoadpcm = {
- "lintoadpcm",
- AST_FORMAT_SLINEAR,
- AST_FORMAT_ADPCM,
- lintoadpcm_new,
- lintoadpcm_framein,
- lintoadpcm_frameout,
- adpcm_destroy,
- /* NULL */
- lintoadpcm_sample
+ .name = "lintoadpcm",
+ .srcfmt = AST_FORMAT_SLINEAR,
+ .dstfmt = AST_FORMAT_ADPCM,
+ .framein = lintoadpcm_framein,
+ .frameout = lintoadpcm_frameout,
+ .sample = lintoadpcm_sample,
+ .desc_size = sizeof (struct adpcm_encoder_pvt),
+ .buffer_samples = BUFFER_SAMPLES,
+ .buf_size = BUFFER_SAMPLES/ 2, /* 2 samples per byte */
+ .lockp = &me,
};
static void parse_config(void)
{
- struct ast_config *cfg;
+ struct ast_config *cfg = ast_config_load("codecs.conf");
struct ast_variable *var;
- if ((cfg = ast_config_load("codecs.conf"))) {
- if ((var = ast_variable_browse(cfg, "plc"))) {
- while (var) {
- if (!strcasecmp(var->name, "genericplc")) {
- useplc = ast_true(var->value) ? 1 : 0;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "codec_adpcm: %susing generic PLC\n", useplc ? "" : "not ");
- }
- var = var->next;
- }
+ if (cfg == NULL)
+ return;
+ for (var = ast_variable_browse(cfg, "plc"); var ; var = var->next) {
+ if (!strcasecmp(var->name, "genericplc")) {
+ adpcmtolin.useplc = ast_true(var->value) ? 1 : 0;
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "codec_adpcm: %susing generic PLC\n", adpcmtolin.useplc ? "" : "not ");
}
- ast_config_destroy(cfg);
}
+ ast_config_destroy(cfg);
}
+/*! \brief standard module glue */
int reload(void)
{
parse_config();
@@ -582,13 +380,12 @@ int reload(void)
int unload_module(void)
{
int res;
- ast_mutex_lock(&localuser_lock);
+ ast_mutex_lock(&me.lock);
res = ast_unregister_translator(&lintoadpcm);
- if (!res)
- res = ast_unregister_translator(&adpcmtolin);
- if (localusecnt)
+ res |= ast_unregister_translator(&adpcmtolin);
+ if (me.usecnt)
res = -1;
- ast_mutex_unlock(&localuser_lock);
+ ast_mutex_unlock(&me.lock);
return res;
}
@@ -604,20 +401,14 @@ int load_module(void)
return res;
}
-/*
- * Return a description of this module.
- */
-
char *description(void)
{
- return tdesc;
+ return "Adaptive Differential PCM Coder/Decoder";
}
int usecount(void)
{
- int res;
- OLD_STANDARD_USECOUNT(res);
- return res;
+ return me.usecnt;
}
char *key()
diff --git a/codecs/codec_alaw.c b/codecs/codec_alaw.c
index 480b92c2a..cc3f64394 100644
--- a/codecs/codec_alaw.c
+++ b/codecs/codec_alaw.c
@@ -44,232 +44,42 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/alaw.h"
#include "asterisk/utils.h"
-#define BUFFER_SIZE 8096 /* size for the translation buffers */
-
-AST_MUTEX_DEFINE_STATIC(localuser_lock);
-static int localusecnt = 0;
-
-static char *tdesc = "A-law Coder/Decoder";
-
-static int useplc = 0;
+#define BUFFER_SAMPLES 8096 /* size for the translation buffers */
/* Sample frame data (Mu data is okay) */
#include "slin_ulaw_ex.h"
#include "ulaw_slin_ex.h"
-/*!
- * \brief Private workspace for translating signed linear signals to alaw.
- */
-struct alaw_encoder_pvt
-{
- struct ast_frame f;
- char offset[AST_FRIENDLY_OFFSET]; /*!< Space to build offset */
- unsigned char outbuf[BUFFER_SIZE]; /*!< Encoded alaw, two nibbles to a word */
- int tail;
-};
-
-/*!
- * \brief Private workspace for translating alaw signals to signed linear.
- */
-struct alaw_decoder_pvt
-{
- struct ast_frame f;
- char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
- short outbuf[BUFFER_SIZE]; /* Decoded signed linear values */
- int tail;
- plc_state_t plc;
-};
-
-/*!
- * \brief alawToLin_New
- * Create a new instance of alaw_decoder_pvt.
- *
- * Results:
- * Returns a pointer to the new instance.
- *
- * Side effects:
- * None.
- */
-
-static struct ast_translator_pvt *alawtolin_new(void)
-{
- struct alaw_decoder_pvt *tmp;
-
- if ((tmp = ast_calloc(1, sizeof(*tmp)))) {
- tmp->tail = 0;
- plc_init(&tmp->plc);
- localusecnt++;
- ast_update_use_count();
- }
-
- return (struct ast_translator_pvt *)tmp;
-}
-
-/*!
- * \brief LinToalaw_New
- * Create a new instance of alaw_encoder_pvt.
- *
- * Results:
- * Returns a pointer to the new instance.
- *
- * Side effects:
- * None.
- */
-
-static struct ast_translator_pvt *lintoalaw_new(void)
-{
- struct alaw_encoder_pvt *tmp;
-
- if ((tmp = ast_calloc(1, sizeof(*tmp)))) {
- localusecnt++;
- ast_update_use_count();
- tmp->tail = 0;
- }
-
- return (struct ast_translator_pvt *)tmp;
-}
-
-/*!
- * \brief alawToLin_FrameIn
- * Fill an input buffer with packed 4-bit alaw values if there is room
- * left.
- *
- * Results:
- * Foo
- *
- * Side effects:
- * tmp->tail is the number of packed values in the buffer.
- */
-
-static int alawtolin_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
+/*! \brief decode frame into lin and fill output buffer. */
+static int alawtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
- struct alaw_decoder_pvt *tmp = (struct alaw_decoder_pvt *)pvt;
- int x;
- unsigned char *b;
-
- if(f->datalen == 0) { /* perform PLC with nominal framesize of 20ms/160 samples */
- if((tmp->tail + 160) * 2 > sizeof(tmp->outbuf)) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
- if(useplc) {
- plc_fillin(&tmp->plc, tmp->outbuf+tmp->tail, 160);
- tmp->tail += 160;
- }
- return 0;
- }
+ int i;
+ unsigned char *src = f->data;
+ int16_t *dst = (int16_t *)pvt->outbuf;
- if ((tmp->tail + f->datalen) * 2 > sizeof(tmp->outbuf)) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
-
- /* Reset ssindex and signal to frame's specified values */
- b = f->data;
- for (x=0;x<f->datalen;x++)
- tmp->outbuf[tmp->tail + x] = AST_ALAW(b[x]);
-
- if(useplc)
- plc_rx(&tmp->plc, tmp->outbuf+tmp->tail, f->datalen);
-
- tmp->tail += f->datalen;
+ for ( i = 0; i < f->samples; i++)
+ dst[pvt->samples + i] = AST_ALAW(src[i]);
+ pvt->samples += f->samples;
+ pvt->datalen += 2*f->samples; /* 2 bytes/sample */
return 0;
}
-/*!
- * \brief alawToLin_FrameOut
- * Convert 4-bit alaw encoded signals to 16-bit signed linear.
- *
- * Results:
- * Converted signals are placed in tmp->f.data, tmp->f.datalen
- * and tmp->f.samples are calculated.
- *
- * Side effects:
- * None.
- */
-
-static struct ast_frame *alawtolin_frameout(struct ast_translator_pvt *pvt)
-{
- struct alaw_decoder_pvt *tmp = (struct alaw_decoder_pvt *)pvt;
-
- if (!tmp->tail)
- return NULL;
-
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_SLINEAR;
- tmp->f.datalen = tmp->tail * 2;
- tmp->f.samples = tmp->tail;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->outbuf;
- tmp->tail = 0;
- return &tmp->f;
-}
-
-/*!
- * \brief LinToalaw_FrameIn
- * Fill an input buffer with 16-bit signed linear PCM values.
- *
- * Results:
- * None.
- *
- * Side effects:
- * tmp->tail is number of signal values in the input buffer.
- */
-
-static int lintoalaw_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
+/*! \brief convert and store input samples in output buffer */
+static int lintoalaw_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
- struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *)pvt;
int x;
- short *s;
- if (tmp->tail + f->datalen / 2 >= sizeof(tmp->outbuf)) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
- s = f->data;
- for (x=0;x<f->datalen/2;x++)
- tmp->outbuf[x+tmp->tail] = AST_LIN2A(s[x]);
- tmp->tail += f->datalen/2;
- return 0;
-}
+ char *dst = pvt->outbuf + pvt->samples;
+ int16_t *src = f->data;
-/*!
- * \brief LinToalaw_FrameOut
- * Convert a buffer of raw 16-bit signed linear PCM to a buffer
- * of 4-bit alaw packed two to a byte (Big Endian).
- *
- * Results:
- * Foo
- *
- * Side effects:
- * Leftover inbuf data gets packed, tail gets updated.
- */
-
-static struct ast_frame *lintoalaw_frameout(struct ast_translator_pvt *pvt)
-{
- struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *)pvt;
-
- if (tmp->tail) {
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_ALAW;
- tmp->f.samples = tmp->tail;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->outbuf;
- tmp->f.datalen = tmp->tail;
- tmp->tail = 0;
- return &tmp->f;
- } else
- return NULL;
+ for ( x = 0; x < f->samples; x++)
+ *dst++ = AST_LIN2A(src[x]);
+ pvt->samples += f->samples;
+ pvt->datalen += f->samples; /* 1 byte/sample */
+ return 0;
}
-/*!
- * \brief alawToLin_Sample
- */
-
+/*! \brief alawToLin_Sample */
static struct ast_frame *alawtolin_sample(void)
{
static struct ast_frame f;
@@ -284,17 +94,13 @@ static struct ast_frame *alawtolin_sample(void)
return &f;
}
-/*!
- * \brief LinToalaw_Sample
- */
-
+/*! \brief LinToalaw_Sample */
static struct ast_frame *lintoalaw_sample(void)
{
static struct ast_frame f;
f.frametype = AST_FRAME_VOICE;
f.subclass = AST_FORMAT_SLINEAR;
f.datalen = sizeof(slin_ulaw_ex);
- /* Assume 8000 Hz */
f.samples = sizeof(slin_ulaw_ex) / 2;
f.mallocd = 0;
f.offset = 0;
@@ -303,76 +109,49 @@ static struct ast_frame *lintoalaw_sample(void)
return &f;
}
-/*!
- * \brief alaw_Destroy
- * Destroys a private workspace.
- *
- * Results:
- * It's gone!
- *
- * Side effects:
- * None.
- */
-
-static void alaw_destroy(struct ast_translator_pvt *pvt)
-{
- free(pvt);
- localusecnt--;
- ast_update_use_count();
-}
-
-/*!
- * \brief The complete translator for alawToLin.
- */
+static struct ast_module_lock me = { .usecnt = -1 };
static struct ast_translator alawtolin = {
- "alawtolin",
- AST_FORMAT_ALAW,
- AST_FORMAT_SLINEAR,
- alawtolin_new,
- alawtolin_framein,
- alawtolin_frameout,
- alaw_destroy,
- /* NULL */
- alawtolin_sample
+ .name = "alawtolin",
+ .srcfmt = AST_FORMAT_ALAW,
+ .dstfmt = AST_FORMAT_SLINEAR,
+ .framein = alawtolin_framein,
+ .sample = alawtolin_sample,
+ .buffer_samples = BUFFER_SAMPLES,
+ .buf_size = BUFFER_SAMPLES * 2,
+ .plc_samples = 160,
+ .lockp = &me,
};
-/*!
- * \brief The complete translator for LinToalaw.
- */
-
static struct ast_translator lintoalaw = {
"lintoalaw",
- AST_FORMAT_SLINEAR,
- AST_FORMAT_ALAW,
- lintoalaw_new,
- lintoalaw_framein,
- lintoalaw_frameout,
- alaw_destroy,
- /* NULL */
- lintoalaw_sample
+ .srcfmt = AST_FORMAT_SLINEAR,
+ .dstfmt = AST_FORMAT_ALAW,
+ .framein = lintoalaw_framein,
+ .sample = lintoalaw_sample,
+ .buffer_samples = BUFFER_SAMPLES,
+ .buf_size = BUFFER_SAMPLES,
+ .lockp = &me,
};
static void parse_config(void)
{
- struct ast_config *cfg;
struct ast_variable *var;
-
- if ((cfg = ast_config_load("codecs.conf"))) {
- if ((var = ast_variable_browse(cfg, "plc"))) {
- while (var) {
- if (!strcasecmp(var->name, "genericplc")) {
- useplc = ast_true(var->value) ? 1 : 0;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "codec_alaw: %susing generic PLC\n", useplc ? "" : "not ");
- }
- var = var->next;
- }
+ struct ast_config *cfg = ast_config_load("codecs.conf");
+ if (!cfg)
+ return;
+ for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
+ if (!strcasecmp(var->name, "genericplc")) {
+ alawtolin.useplc = ast_true(var->value) ? 1 : 0;
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "codec_alaw: %susing generic PLC\n", alawtolin.useplc ? "" : "not ");
}
- ast_config_destroy(cfg);
}
+ ast_config_destroy(cfg);
}
+/*! \brief standard module stuff */
+
int reload(void)
{
parse_config();
@@ -382,13 +161,12 @@ int reload(void)
int unload_module(void)
{
int res;
- ast_mutex_lock(&localuser_lock);
+ ast_mutex_lock(&me.lock);
res = ast_unregister_translator(&lintoalaw);
- if (!res)
- res = ast_unregister_translator(&alawtolin);
- if (localusecnt)
+ res |= ast_unregister_translator(&alawtolin);
+ if (me.usecnt)
res = -1;
- ast_mutex_unlock(&localuser_lock);
+ ast_mutex_unlock(&me.lock);
return res;
}
@@ -404,20 +182,14 @@ int load_module(void)
return res;
}
-/*
- * Return a description of this module.
- */
-
char *description(void)
{
- return tdesc;
+ return "A-law Coder/Decoder";
}
int usecount(void)
{
- int res;
- OLD_STANDARD_USECOUNT(res);
- return res;
+ return me.usecnt;
}
char *key()
diff --git a/codecs/codec_g723_1.c b/codecs/codec_g723_1.c
index c226bb0c2..4eeb60eb4 100644
--- a/codecs/codec_g723_1.c
+++ b/codecs/codec_g723_1.c
@@ -74,14 +74,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "slin_g723_ex.h"
#include "g723_slin_ex.h"
-AST_MUTEX_DEFINE_STATIC(localuser_lock);
-static int localusecnt=0;
-
-#ifdef ANNEX_B
-static char *tdesc = "Annex B (floating point) G.723.1/PCM16 Codec Translator";
-#else
-static char *tdesc = "Annex A (fixed point) G.723.1/PCM16 Codec Translator";
-#endif
+/* g723_1 has 240 samples per buffer.
+ * We want a buffer which is a multiple...
+ */
+#define G723_SAMPLES 240
+#define BUFFER_SAMPLES 8160 /* 240 * 34 */
/* Globals */
Flag UsePf = True;
@@ -92,37 +89,20 @@ enum Crate WrkRate = Rate63;
struct g723_encoder_pvt {
struct cod_state cod;
- struct ast_frame f;
- /* Space to build offset */
- char offset[AST_FRIENDLY_OFFSET];
- /* Buffer for our outgoing frame */
- char outbuf[8000];
- /* Enough to store a full second */
- short buf[8000];
- int tail;
+ int16_t buf[BUFFER_SAMPLES]; /* input buffer */
};
struct g723_decoder_pvt {
struct dec_state dec;
- struct ast_frame f;
- /* Space to build offset */
- char offset[AST_FRIENDLY_OFFSET];
- /* Enough to store a full second */
- short buf[8000];
- int tail;
};
-static struct ast_translator_pvt *g723tolin_new(void)
+static struct ast_trans_pvt *g723tolin_new(struct ast *pvt)
{
- struct g723_decoder_pvt *tmp;
- if ((tmp = ast_malloc(sizeof(*tmp)))) {
- Init_Decod(&tmp->dec);
- Init_Dec_Cng(&tmp->dec);
- tmp->tail = 0;
- localusecnt++;
- ast_update_use_count();
- }
- return (struct ast_translator_pvt *)tmp;
+ struct g723_decoder_pvt *tmp = pvt;
+
+ Init_Decod(&tmp->dec);
+ Init_Dec_Cng(&tmp->dec);
+ return tmp;
}
static struct ast_frame *lintog723_sample(void)
@@ -131,7 +111,6 @@ static struct ast_frame *lintog723_sample(void)
f.frametype = AST_FRAME_VOICE;
f.subclass = AST_FORMAT_SLINEAR;
f.datalen = sizeof(slin_g723_ex);
- /* Assume 8000 Hz */
f.samples = sizeof(slin_g723_ex)/2;
f.mallocd = 0;
f.offset = 0;
@@ -155,53 +134,16 @@ static struct ast_frame *g723tolin_sample(void)
return &f;
}
-static struct ast_translator_pvt *lintog723_new(void)
+static void *lintog723_new(void *pvt)
{
- struct g723_encoder_pvt *tmp;
- if ((tmp = ast_malloc(sizeof(*tmp)))) {
- Init_Coder(&tmp->cod);
- /* Init Comfort Noise Functions */
- if( UseVx ) {
- Init_Vad(&tmp->cod);
- Init_Cod_Cng(&tmp->cod);
- }
- localusecnt++;
- ast_update_use_count();
- tmp->tail = 0;
+ struct g723_encoder_pvt *tmp = pvt;
+ Init_Coder(&tmp->cod);
+ /* Init Comfort Noise Functions */
+ if( UseVx ) {
+ Init_Vad(&tmp->cod);
+ Init_Cod_Cng(&tmp->cod);
}
- return (struct ast_translator_pvt *)tmp;
-}
-
-static struct ast_frame *g723tolin_frameout(struct ast_translator_pvt *pvt)
-{
- struct g723_decoder_pvt *tmp = (struct g723_decoder_pvt *)pvt;
- if (!tmp->tail)
- return NULL;
- /* Signed linear is no particular frame size, so just send whatever
- we have in the buffer in one lump sum */
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_SLINEAR;
- tmp->f.datalen = tmp->tail * 2;
- /* Assume 8000 Hz */
- tmp->f.samples = tmp->tail;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->buf;
- /* Reset tail pointer */
- tmp->tail = 0;
-
-#if 0
- /* Save the frames */
- {
- static int fd2 = -1;
- if (fd2 == -1) {
- fd2 = open("g723.example", O_WRONLY | O_CREAT | O_TRUNC, 0644);
- }
- write(fd2, tmp->f.data, tmp->f.datalen);
- }
-#endif
- return &tmp->f;
+ return tmp;
}
static int g723_len(unsigned char buf)
@@ -225,19 +167,22 @@ static int g723_len(unsigned char buf)
return -1;
}
-static int g723tolin_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
+static int g723tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
- struct g723_decoder_pvt *tmp = (struct g723_decoder_pvt *)pvt;
+ struct g723_decoder_pvt *tmp = pvt->pvt;
int len = 0;
int res;
+ int16_t *dst = pvt->outbuf;
#ifdef ANNEX_B
FLOAT tmpdata[Frame];
int x;
#endif
+ unsigned char *src = f->data;
+
while(len < f->datalen) {
/* Assuming there's space left, decode into the current buffer at
the tail location */
- res = g723_len(((unsigned char *)f->data + len)[0]);
+ res = g723_len(src[len]);
if (res < 0) {
ast_log(LOG_WARNING, "Invalid data\n");
return -1;
@@ -246,145 +191,127 @@ static int g723tolin_framein(struct ast_translator_pvt *pvt, struct ast_frame *f
ast_log(LOG_WARNING, "Measured length exceeds frame length\n");
return -1;
}
- if (tmp->tail + Frame < sizeof(tmp->buf)/2) {
-#ifdef ANNEX_B
- Decod(&tmp->dec, tmpdata, f->data + len, 0);
- for (x=0;x<Frame;x++)
- (tmp->buf + tmp->tail)[x] = (short)(tmpdata[x]);
-#else
- Decod(&tmp->dec, tmp->buf + tmp->tail, f->data + len, 0);
-#endif
- tmp->tail+=Frame;
- } else {
+ if (pvt->samples + Frame > BUFFER_SAMPLES) {
ast_log(LOG_WARNING, "Out of buffer space\n");
return -1;
}
+#ifdef ANNEX_B
+ Decod(&tmp->dec, tmpdata, f->data + len, 0);
+ for (x=0;x<Frame;x++)
+ dst[pvt->samples + x] = (int16_t)(tmpdata[x]);
+#else
+ Decod(&tmp->dec, dst + pvt->samples, f->data + len, 0);
+#endif
+ pvt->samples += Frame;
+ pvt->datalen += 2*Frame; /* 2 bytes/sample */
len += res;
}
return 0;
}
-static int lintog723_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
+static int lintog723_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
/* Just add the frames to our stream */
/* XXX We should look at how old the rest of our stream is, and if it
is too old, then we should overwrite it entirely, otherwise we can
get artifacts of earlier talk that do not belong */
- struct g723_encoder_pvt *tmp = (struct g723_encoder_pvt *)pvt;
- if (tmp->tail + f->datalen/2 < sizeof(tmp->buf) / 2) {
- memcpy(&tmp->buf[tmp->tail], f->data, f->datalen);
- tmp->tail += f->datalen/2;
- } else {
+ struct g723_encoder_pvt *tmp = pvt->pvt;
+
+ if (tmp->samples + f->samples > BUFFER_SAMPLES) {
ast_log(LOG_WARNING, "Out of buffer space\n");
return -1;
}
+ memcpy(&tmp->buf[pvt->samples], f->data, f->datalen);
+ pvt->samples += f->samples;
return 0;
}
-static struct ast_frame *lintog723_frameout(struct ast_translator_pvt *pvt)
+static struct ast_frame *lintog723_frameout(void *pvt)
{
struct g723_encoder_pvt *tmp = (struct g723_encoder_pvt *)pvt;
+ int samples = 0; /* how many samples in buffer */
#ifdef ANNEX_B
int x;
FLOAT tmpdata[Frame];
#endif
- int cnt=0;
+ int cnt = 0; /* how many bytes so far */
+
/* We can't work on anything less than a frame in size */
- if (tmp->tail < Frame)
+ if (pvt->samples < Frame)
return NULL;
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_G723_1;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.samples = 0;
- tmp->f.mallocd = 0;
- while(tmp->tail >= Frame) {
+ while (pvt->samples >= Frame) {
/* Encode a frame of data */
- if (cnt + 24 >= sizeof(tmp->outbuf)) {
+ /* at most 24 bytes/frame... */
+ if (cnt + 24 > pvt->buf_size) {
ast_log(LOG_WARNING, "Out of buffer space\n");
return NULL;
}
#ifdef ANNEX_B
- for (x=0;x<Frame;x++)
+ for ( x = 0; x < Frame ; x++)
tmpdata[x] = tmp->buf[x];
- Coder(&tmp->cod, tmpdata, tmp->outbuf + cnt);
+ Coder(&tmp->cod, tmpdata, pvt->outbuf + cnt);
#else
- Coder(&tmp->cod, tmp->buf, tmp->outbuf + cnt);
+ Coder(&tmp->cod, tmp->buf, pvt->outbuf + cnt);
#endif
/* Assume 8000 Hz */
- tmp->f.samples += 240;
+ samples += G723_SAMPLES;
cnt += g723_len(tmp->outbuf[cnt]);
- tmp->tail -= Frame;
+ pvt->samples -= Frame;
/* Move the data at the end of the buffer to the front */
- if (tmp->tail)
- memmove(tmp->buf, tmp->buf + Frame, tmp->tail * 2);
+ /* XXX inefficient... */
+ if (pvt->samples)
+ memmove(tmp->buf, tmp->buf + Frame, pvt->samples * 2);
}
- tmp->f.datalen = cnt;
- tmp->f.data = tmp->outbuf;
-#if 0
- /* Save to a g723 sample output file... */
- {
- static int fd = -1;
- int delay = htonl(30);
- short size;
- if (fd < 0)
- fd = open("trans.g723", O_WRONLY | O_CREAT | O_TRUNC, 0644);
- if (fd < 0)
- ast_log(LOG_WARNING, "Unable to create demo\n");
- write(fd, &delay, 4);
- size = htons(tmp->f.datalen);
- write(fd, &size, 2);
- write(fd, tmp->f.data, tmp->f.datalen);
- }
-#endif
- return &tmp->f;
+ return ast_trans_frameout(pvt, cnt, samples);
}
-static void g723_destroy(struct ast_translator_pvt *pvt)
-{
- free(pvt);
- localusecnt--;
- ast_update_use_count();
-}
+static struct ast_module_lock me = { .usecnt = -1 };
-static struct ast_translator g723tolin =
+static struct ast_translator g723tolin = {
+ .name =
#ifdef ANNEX_B
- { "g723tolinb",
+ "g723btolin",
#else
- { "g723tolin",
+ "g723tolin",
#endif
- AST_FORMAT_G723_1, AST_FORMAT_SLINEAR,
- g723tolin_new,
- g723tolin_framein,
- g723tolin_frameout,
- g723_destroy,
- g723tolin_sample
- };
-
-static struct ast_translator lintog723 =
+ .srcfmt = AST_FORMAT_G723_1,
+ .dstfmt = AST_FORMAT_SLINEAR,
+ .newpvt = g723tolin_new,
+ .framein = g723tolin_framein,
+ .sample = g723tolin_sample,
+ .desc_size = sizeof(struct ...),
+ .lockp = &me,
+};
+
+static struct ast_translator lintog723 = {
+ .name =
#ifdef ANNEX_B
- { "lintog723b",
+ "lintog723b",
#else
- { "lintog723",
+ "lintog723",
#endif
- AST_FORMAT_SLINEAR, AST_FORMAT_G723_1,
- lintog723_new,
- lintog723_framein,
- lintog723_frameout,
- g723_destroy,
- lintog723_sample
- };
+ .srcfmt = AST_FORMAT_SLINEAR,
+ .dstfmt = AST_FORMAT_G723_1,
+ .new = lintog723_new,
+ .framein = lintog723_framein,
+ .frameout = lintog723_frameout,
+ .destroy = g723_destroy,
+ .sample = lintog723_sample,
+ .lockp = &me,
+ .desc_size = sizeof(struct ...),
+};
+
+/*! \brief standard module glue */
int unload_module(void)
{
int res;
- ast_mutex_lock(&localuser_lock);
+ ast_mutex_lock(&me.lock);
res = ast_unregister_translator(&lintog723);
- if (!res)
- res = ast_unregister_translator(&g723tolin);
- if (localusecnt)
+ res |= ast_unregister_translator(&g723tolin);
+ if (me.usecnt)
res = -1;
- ast_mutex_unlock(&localuser_lock);
+ ast_mutex_unlock(&me.lock);
return res;
}
@@ -401,14 +328,17 @@ int load_module(void)
char *description(void)
{
- return tdesc;
+#ifdef ANNEX_B
+ return "Annex B (floating point) G.723.1/PCM16 Codec Translator";
+#else
+ return "Annex A (fixed point) G.723.1/PCM16 Codec Translator";
+#endif
+
}
int usecount(void)
{
- int res;
- OLD_STANDARD_USECOUNT(res);
- return res;
+ return me.usecnt;
}
char *key(void)
diff --git a/codecs/codec_g726.c b/codecs/codec_g726.c
index 6a33d8519..a71651cd5 100644
--- a/codecs/codec_g726.c
+++ b/codecs/codec_g726.c
@@ -19,7 +19,6 @@
* at the top of the source tree.
*/
-
/*! \file
*
* \brief codec_g726.c - translate between signed linear and ITU G.726-32kbps
@@ -40,6 +39,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/logger.h"
+#include "asterisk/linkedlists.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/options.h"
@@ -63,16 +63,9 @@ typedef long long sint64;
# endif
#endif
-#define BUFFER_SIZE 8096 /* size for the translation buffers */
+#define BUFFER_SAMPLES 8096 /* size for the translation buffers */
#define BUF_SHIFT 5
-AST_MUTEX_DEFINE_STATIC(localuser_lock);
-static int localusecnt = 0;
-
-static char *tdesc = "ITU G.726-32kbps G726 Transcoder";
-
-static int useplc = 0;
-
/* Sample frame data */
#include "slin_g726_ex.h"
@@ -152,8 +145,7 @@ static void g726_init_state(struct g726_state *state_ptr)
state_ptr->dms = 0;
state_ptr->dml = 0;
state_ptr->ap = 0;
- for (cnta = 0; cnta < 2; cnta++)
- {
+ for (cnta = 0; cnta < 2; cnta++) {
state_ptr->a[cnta] = 0;
state_ptr->pk[cnta] = 0;
#ifdef NOT_BLI
@@ -162,8 +154,7 @@ static void g726_init_state(struct g726_state *state_ptr)
state_ptr->sr[cnta] = 32;
#endif
}
- for (cnta = 0; cnta < 6; cnta++)
- {
+ for (cnta = 0; cnta < 6; cnta++) {
state_ptr->b[cnta] = 0;
#ifdef NOT_BLI
state_ptr->dq[cnta] = 1;
@@ -694,396 +685,185 @@ static int g726_encode(int sl, struct g726_state *state_ptr)
}
/*
- * Private workspace for translating signed linear signals to G726.
+ * ------------ Asterisk-codec hooks. -------------------
*/
-struct g726_encoder_pvt
-{
- struct ast_frame f;
- char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
- unsigned char outbuf[BUFFER_SIZE]; /* Encoded G726, two nibbles to a word */
- unsigned char next_flag;
- struct g726_state g726;
- int tail;
-};
-
/*
- * Private workspace for translating G726 signals to signed linear.
+ * Private workspace for translating signed linear signals to G726.
+ * Don't bother to define two distinct structs.
*/
-struct g726_decoder_pvt
-{
- struct ast_frame f;
- char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
- short outbuf[BUFFER_SIZE]; /* Decoded signed linear values */
- struct g726_state g726;
- int tail;
- plc_state_t plc;
+struct g726_coder_pvt {
+ /* buffer any odd byte in input - 0x80 + (value & 0xf) if present */
+ unsigned char next_flag;
+ struct g726_state g726;
};
-/*
- * G726ToLin_New
- * Create a new instance of g726_decoder_pvt.
- *
- * Results:
- * Returns a pointer to the new instance.
- *
- * Side effects:
- * None.
- */
-
-static struct ast_translator_pvt *
-g726tolin_new (void)
+/*! \brief init a new instance of g726_coder_pvt. */
+static void *lintog726_new(struct ast_trans_pvt *pvt)
{
- struct g726_decoder_pvt *tmp;
- if ((tmp = ast_calloc(1, sizeof(*tmp))))
- {
- tmp->tail = 0;
- plc_init(&tmp->plc);
- localusecnt++;
- g726_init_state(&tmp->g726);
- ast_update_use_count ();
- }
- return (struct ast_translator_pvt *) tmp;
-}
-
-/*
- * LinToG726_New
- * Create a new instance of g726_encoder_pvt.
- *
- * Results:
- * Returns a pointer to the new instance.
- *
- * Side effects:
- * None.
- */
+ struct g726_coder_pvt *tmp = pvt->pvt;
-static struct ast_translator_pvt *
-lintog726_new (void)
-{
- struct g726_encoder_pvt *tmp;
- if ((tmp = ast_calloc(1, sizeof(*tmp))))
- {
- localusecnt++;
- tmp->tail = 0;
- g726_init_state(&tmp->g726);
- ast_update_use_count ();
- }
- return (struct ast_translator_pvt *) tmp;
+ g726_init_state(&tmp->g726);
+ return tmp;
}
-/*
- * G726ToLin_FrameIn
- * Fill an input buffer with packed 4-bit G726 values if there is room
- * left.
- *
- * Results:
- * Foo
- *
- * Side effects:
- * tmp->tail is the number of packed values in the buffer.
- */
-
-static int
-g726tolin_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
+/*! \brief decode packed 4-bit G726 values and store in buffer. */
+static int g726tolin_framein (struct ast_trans_pvt *pvt, struct ast_frame *f)
{
- struct g726_decoder_pvt *tmp = (struct g726_decoder_pvt *) pvt;
- unsigned char *b;
- int x;
-
- if(f->datalen == 0) { /* perform PLC with nominal framesize of 20ms/160 samples */
- if((tmp->tail + 160) > BUFFER_SIZE) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
- if(useplc) {
- plc_fillin(&tmp->plc, tmp->outbuf+tmp->tail, 160);
- tmp->tail += 160;
- }
- return 0;
- }
-
- b = f->data;
- for (x=0;x<f->datalen;x++) {
- if (tmp->tail >= BUFFER_SIZE) {
- ast_log(LOG_WARNING, "Out of buffer space!\n");
- return -1;
- }
- tmp->outbuf[tmp->tail++] = g726_decode((b[x] >> 4) & 0xf, &tmp->g726);
- if (tmp->tail >= BUFFER_SIZE) {
- ast_log(LOG_WARNING, "Out of buffer space!\n");
- return -1;
- }
- tmp->outbuf[tmp->tail++] = g726_decode(b[x] & 0x0f, &tmp->g726);
- }
-
- if(useplc) plc_rx(&tmp->plc, tmp->outbuf+tmp->tail-f->datalen*2, f->datalen*2);
+ struct g726_coder_pvt *tmp = pvt->pvt;
+ unsigned char *src = f->data;
+ int16_t *dst = (int16_t *)pvt->outbuf + pvt->samples;
+ int i;
- return 0;
+ for ( i = 0 ; i < f->datalen ; i++ ) {
+ *dst++ = g726_decode((src[i] >> 4) & 0xf, &tmp->g726);
+ *dst++ = g726_decode(src[i] & 0x0f, &tmp->g726);
+ }
+ pvt->samples += f->samples;
+ pvt->datalen += 2 * f->samples; /* 2 bytes/sample */
+ return 0;
}
-/*
- * G726ToLin_FrameOut
- * Convert 4-bit G726 encoded signals to 16-bit signed linear.
- *
- * Results:
- * Converted signals are placed in tmp->f.data, tmp->f.datalen
- * and tmp->f.samples are calculated.
- *
- * Side effects:
- * None.
- */
-
-static struct ast_frame *
-g726tolin_frameout (struct ast_translator_pvt *pvt)
+/*! \brief compress and store data (4-bit G726 samples) in outbuf */
+static int lintog726_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
- struct g726_decoder_pvt *tmp = (struct g726_decoder_pvt *) pvt;
-
- if (!tmp->tail)
- return NULL;
-
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_SLINEAR;
- tmp->f.datalen = tmp->tail * 2;
- tmp->f.samples = tmp->tail;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->outbuf;
- tmp->tail = 0;
- return &tmp->f;
-}
-
-/*
- * LinToG726_FrameIn
- * Fill an input buffer with 16-bit signed linear PCM values.
- *
- * Results:
- * None.
- *
- * Side effects:
- * tmp->tail is number of signal values in the input buffer.
- */
-
-static int
-lintog726_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
-{
- struct g726_encoder_pvt *tmp = (struct g726_encoder_pvt *) pvt;
- short *s = f->data;
- int samples = f->datalen / 2;
- int x;
- for (x=0;x<samples;x++) {
- if (tmp->next_flag & 0x80) {
- if (tmp->tail >= BUFFER_SIZE) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
+ struct g726_coder_pvt *tmp = pvt->pvt;
+ int16_t *src = f->data;
+ int i;
+ for ( i = 0; i < f->samples; i++ ) {
+ unsigned char d = g726_encode(src[i], &tmp->g726); /* this sample */
+ if (tmp->next_flag & 0x80) { /* merge with leftover sample */
+ pvt->outbuf[pvt->datalen++] = ((tmp->next_flag & 0xf)<< 4) | d;
+ pvt->samples += 2; /* 2 samples per byte */
+ tmp->next_flag = 0;
+ } else {
+ tmp->next_flag = 0x80 | d;
}
- tmp->outbuf[tmp->tail++] = ((tmp->next_flag & 0xf)<< 4) | g726_encode(s[x], &tmp->g726);
- tmp->next_flag = 0;
- } else {
- tmp->next_flag = 0x80 | g726_encode(s[x], &tmp->g726);
}
- }
- return 0;
+ return 0;
}
-/*
- * LinToG726_FrameOut
- * Convert a buffer of raw 16-bit signed linear PCM to a buffer
- * of 4-bit G726 packed two to a byte (Big Endian).
- *
- * Results:
- * Foo
- *
- * Side effects:
- * Leftover inbuf data gets packed, tail gets updated.
- */
-
-static struct ast_frame *
-lintog726_frameout (struct ast_translator_pvt *pvt)
+/*! \brief G726ToLin_Sample */
+static struct ast_frame *g726tolin_sample(void)
{
- struct g726_encoder_pvt *tmp = (struct g726_encoder_pvt *) pvt;
-
- if (!tmp->tail)
- return NULL;
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_G726;
- tmp->f.samples = tmp->tail * 2;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->outbuf;
- tmp->f.datalen = tmp->tail;
-
- tmp->tail = 0;
- return &tmp->f;
+ static struct ast_frame f;
+ f.frametype = AST_FRAME_VOICE;
+ f.subclass = AST_FORMAT_G726;
+ f.datalen = sizeof (g726_slin_ex);
+ f.samples = sizeof(g726_slin_ex) * 2; /* 2 samples per byte */
+ f.mallocd = 0;
+ f.offset = 0;
+ f.src = __PRETTY_FUNCTION__;
+ f.data = g726_slin_ex;
+ return &f;
}
-
-/*
- * G726ToLin_Sample
- */
-
-static struct ast_frame *
-g726tolin_sample (void)
+/*! \brief LinToG726_Sample */
+static struct ast_frame *lintog726_sample (void)
{
- static struct ast_frame f;
- f.frametype = AST_FRAME_VOICE;
- f.subclass = AST_FORMAT_G726;
- f.datalen = sizeof (g726_slin_ex);
- f.samples = sizeof(g726_slin_ex) * 2;
- f.mallocd = 0;
- f.offset = 0;
- f.src = __PRETTY_FUNCTION__;
- f.data = g726_slin_ex;
- return &f;
+ static struct ast_frame f;
+ f.frametype = AST_FRAME_VOICE;
+ f.subclass = AST_FORMAT_SLINEAR;
+ f.datalen = sizeof (slin_g726_ex);
+ /* Assume 8000 Hz */
+ f.samples = sizeof (slin_g726_ex) / 2; /* 1 sample per 2 bytes */
+ f.mallocd = 0;
+ f.offset = 0;
+ f.src = __PRETTY_FUNCTION__;
+ f.data = slin_g726_ex;
+ return &f;
}
-/*
- * LinToG726_Sample
- */
-
-static struct ast_frame *
-lintog726_sample (void)
-{
- static struct ast_frame f;
- f.frametype = AST_FRAME_VOICE;
- f.subclass = AST_FORMAT_SLINEAR;
- f.datalen = sizeof (slin_g726_ex);
- /* Assume 8000 Hz */
- f.samples = sizeof (slin_g726_ex) / 2;
- f.mallocd = 0;
- f.offset = 0;
- f.src = __PRETTY_FUNCTION__;
- f.data = slin_g726_ex;
- return &f;
-}
-
-/*
- * G726_Destroy
- * Destroys a private workspace.
- *
- * Results:
- * It's gone!
- *
- * Side effects:
- * None.
- */
-
-static void
-g726_destroy (struct ast_translator_pvt *pvt)
-{
- free (pvt);
- localusecnt--;
- ast_update_use_count ();
-}
-
-/*
- * The complete translator for G726ToLin.
- */
+static struct ast_module_lock me = { .usecnt = -1 };
static struct ast_translator g726tolin = {
- "g726tolin",
- AST_FORMAT_G726,
- AST_FORMAT_SLINEAR,
- g726tolin_new,
- g726tolin_framein,
- g726tolin_frameout,
- g726_destroy,
- /* NULL */
- g726tolin_sample
+ .name = "g726tolin",
+ .srcfmt = AST_FORMAT_G726,
+ .dstfmt = AST_FORMAT_SLINEAR,
+ .newpvt = lintog726_new, /* same for both directions */
+ .framein = g726tolin_framein,
+ .sample = g726tolin_sample,
+ .desc_size = sizeof(struct g726_coder_pvt),
+ .buffer_samples = BUFFER_SAMPLES,
+ .buf_size = BUFFER_SAMPLES * 2,
+ .plc_samples = 160,
+ .lockp = &me,
};
-/*
- * The complete translator for LinToG726.
- */
-
static struct ast_translator lintog726 = {
- "lintog726",
- AST_FORMAT_SLINEAR,
- AST_FORMAT_G726,
- lintog726_new,
- lintog726_framein,
- lintog726_frameout,
- g726_destroy,
- /* NULL */
- lintog726_sample
+ .name = "lintog726",
+ .srcfmt = AST_FORMAT_SLINEAR,
+ .dstfmt = AST_FORMAT_G726,
+ .newpvt = lintog726_new, /* same for both directions */
+ .framein = lintog726_framein,
+ .sample = lintog726_sample,
+ .desc_size = sizeof(struct g726_coder_pvt),
+ .buffer_samples = BUFFER_SAMPLES,
+ .buf_size = BUFFER_SAMPLES/2,
+ .lockp = &me,
};
-static void
-parse_config(void)
+static void parse_config(void)
{
- struct ast_config *cfg;
- struct ast_variable *var;
- if ((cfg = ast_config_load("codecs.conf"))) {
- if ((var = ast_variable_browse(cfg, "plc"))) {
- while (var) {
- if (!strcasecmp(var->name, "genericplc")) {
- useplc = ast_true(var->value) ? 1 : 0;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "codec_g726: %susing generic PLC\n", useplc ? "" : "not ");
- }
- var = var->next;
- }
- }
- ast_config_destroy(cfg);
- }
+ struct ast_variable *var;
+ struct ast_config *cfg = ast_config_load("codecs.conf");
+ if (!cfg)
+ return;
+ for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
+ if (!strcasecmp(var->name, "genericplc")) {
+ g726tolin.useplc = ast_true(var->value) ? 1 : 0;
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "codec_g726: %susing generic PLC\n",
+ g726tolin.useplc ? "" : "not ");
+ }
+ }
+ ast_config_destroy(cfg);
}
-int
-reload(void)
+/*! \brief standard module glue */
+
+int reload(void)
{
- parse_config();
- return 0;
+ parse_config();
+ return 0;
}
-int
-unload_module (void)
+int unload_module (void)
{
- int res;
- ast_mutex_lock (&localuser_lock);
- res = ast_unregister_translator (&lintog726);
- if (!res)
- res = ast_unregister_translator (&g726tolin);
- if (localusecnt)
- res = -1;
- ast_mutex_unlock (&localuser_lock);
- return res;
+ int res;
+ ast_mutex_lock (&me.lock);
+ res = ast_unregister_translator (&lintog726);
+ res |= ast_unregister_translator (&g726tolin);
+ if (me.usecnt)
+ res = -1;
+ ast_mutex_unlock (&me.lock);
+ return res;
}
-int
-load_module (void)
+int load_module (void)
{
- int res;
- parse_config();
- res = ast_register_translator (&g726tolin);
- if (!res)
- res = ast_register_translator (&lintog726);
- else
- ast_unregister_translator (&g726tolin);
- return res;
+ int res;
+ parse_config();
+ res = ast_register_translator (&g726tolin);
+ if (!res)
+ res = ast_register_translator (&lintog726);
+ else
+ ast_unregister_translator (&g726tolin);
+ return res;
}
-/*
- * Return a description of this module.
- */
-
-char *
-description (void)
+char *description (void)
{
- return tdesc;
+ return "ITU G.726-32kbps G726 Transcoder";
}
-int
-usecount (void)
+int usecount (void)
{
- int res;
- OLD_STANDARD_USECOUNT (res);
- return res;
+ return me.usecnt;
}
-char *
-key ()
+char *key()
{
- return ASTERISK_GPL_KEY;
+ return ASTERISK_GPL_KEY;
}
diff --git a/codecs/codec_gsm.c b/codecs/codec_gsm.c
index 59ce77fab..d6a82f029 100644
--- a/codecs/codec_gsm.c
+++ b/codecs/codec_gsm.c
@@ -58,40 +58,22 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "slin_gsm_ex.h"
#include "gsm_slin_ex.h"
-AST_MUTEX_DEFINE_STATIC(localuser_lock);
-static int localusecnt=0;
+#define BUFFER_SAMPLES 8000
+#define GSM_SAMPLES 160
+#define GSM_FRAME_LEN 33
+#define MSGSM_FRAME_LEN 65
-static char *tdesc = "GSM/PCM16 (signed linear) Codec Translator";
-
-static int useplc = 0;
-
-struct ast_translator_pvt {
+struct gsm_translator_pvt { /* both gsm2lin and lin2gsm */
gsm gsm;
- struct ast_frame f;
- /* Space to build offset */
- char offset[AST_FRIENDLY_OFFSET];
- /* Buffer for our outgoing frame */
- short outbuf[8000];
- /* Enough to store a full second */
- short buf[8000];
- int tail;
- plc_state_t plc;
+ int16_t buf[BUFFER_SAMPLES]; /* lin2gsm, temporary storage */
};
-#define gsm_coder_pvt ast_translator_pvt
-
-static struct ast_translator_pvt *gsm_new(void)
+static void *gsm_new(struct ast_trans_pvt *pvt)
{
- struct gsm_coder_pvt *tmp;
- if ((tmp = ast_malloc(sizeof(*tmp)))) {
- if (!(tmp->gsm = gsm_create())) {
- free(tmp);
- tmp = NULL;
- }
- tmp->tail = 0;
- plc_init(&tmp->plc);
- localusecnt++;
- }
+ struct gsm_translator_pvt *tmp = pvt->pvt;
+
+ if (!(tmp->gsm = gsm_create()))
+ return NULL;
return tmp;
}
@@ -117,7 +99,7 @@ static struct ast_frame *gsmtolin_sample(void)
f.subclass = AST_FORMAT_GSM;
f.datalen = sizeof(gsm_slin_ex);
/* All frames are 20 ms long */
- f.samples = 160;
+ f.samples = GSM_SAMPLES;
f.mallocd = 0;
f.offset = 0;
f.src = __PRETTY_FUNCTION__;
@@ -125,189 +107,151 @@ static struct ast_frame *gsmtolin_sample(void)
return &f;
}
-static struct ast_frame *gsmtolin_frameout(struct ast_translator_pvt *tmp)
+/*! \brief decode and store in outbuf. */
+static int gsmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
- if (!tmp->tail)
- return NULL;
- /* Signed linear is no particular frame size, so just send whatever
- we have in the buffer in one lump sum */
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_SLINEAR;
- tmp->f.datalen = tmp->tail * 2;
- /* Assume 8000 Hz */
- tmp->f.samples = tmp->tail;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->buf;
- /* Reset tail pointer */
- tmp->tail = 0;
-
- return &tmp->f;
-}
-
-static int gsmtolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
-{
- /* Assuming there's space left, decode into the current buffer at
- the tail location. Read in as many frames as there are */
+ struct gsm_translator_pvt *tmp = pvt->pvt;
int x;
- unsigned char data[66];
- int msgsm=0;
-
- if(f->datalen == 0) { /* perform PLC with nominal framesize of 20ms/160 samples */
- if((tmp->tail + 160) > sizeof(tmp->buf) / 2) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
- if(useplc) {
- plc_fillin(&tmp->plc, tmp->buf+tmp->tail, 160);
- tmp->tail += 160;
- }
- return 0;
- }
-
- if ((f->datalen % 33) && (f->datalen % 65)) {
- ast_log(LOG_WARNING, "Huh? A GSM frame that isn't a multiple of 33 or 65 bytes long from %s (%d)?\n", f->src, f->datalen);
- return -1;
- }
-
- if (f->datalen % 65 == 0)
- msgsm = 1;
-
- for (x=0;x<f->datalen;x+=(msgsm ? 65 : 33)) {
- if (msgsm) {
+ int16_t *dst = (int16_t *)pvt->outbuf;
+ /* guess format from frame len. 65 for MSGSM, 33 for regular GSM */
+ int flen = (f->datalen % MSGSM_FRAME_LEN == 0) ?
+ MSGSM_FRAME_LEN : GSM_FRAME_LEN;
+
+ for (x=0; x < f->datalen; x += flen) {
+ unsigned char data[2 * GSM_FRAME_LEN];
+ char *src;
+ int len;
+ if (flen == MSGSM_FRAME_LEN) {
+ len = 2*GSM_SAMPLES;
+ src = data;
/* Translate MSGSM format to Real GSM format before feeding in */
+ /* XXX what's the point here! we should just work
+ * on the full format.
+ */
conv65(f->data + x, data);
- if (tmp->tail + 320 < sizeof(tmp->buf)/2) {
- if (gsm_decode(tmp->gsm, data, tmp->buf + tmp->tail)) {
- ast_log(LOG_WARNING, "Invalid GSM data (1)\n");
- return -1;
- }
- tmp->tail+=160;
- if (gsm_decode(tmp->gsm, data + 33, tmp->buf + tmp->tail)) {
- ast_log(LOG_WARNING, "Invalid GSM data (2)\n");
- return -1;
- }
- tmp->tail+=160;
- } else {
- ast_log(LOG_WARNING, "Out of (MS) buffer space\n");
- return -1;
- }
} else {
- if (tmp->tail + 160 < sizeof(tmp->buf)/2) {
- if (gsm_decode(tmp->gsm, f->data + x, tmp->buf + tmp->tail)) {
- ast_log(LOG_WARNING, "Invalid GSM data\n");
- return -1;
- }
- tmp->tail+=160;
- } else {
- ast_log(LOG_WARNING, "Out of buffer space\n");
+ len = GSM_SAMPLES;
+ src = f->data + x;
+ }
+ /* XXX maybe we don't need to check */
+ if (pvt->samples + len > BUFFER_SAMPLES) {
+ ast_log(LOG_WARNING, "Out of buffer space\n");
+ return -1;
+ }
+ if (gsm_decode(tmp->gsm, src, dst + pvt->samples)) {
+ ast_log(LOG_WARNING, "Invalid GSM data (1)\n");
+ return -1;
+ }
+ pvt->samples += GSM_SAMPLES;
+ pvt->datalen += 2 * GSM_SAMPLES;
+ if (flen == MSGSM_FRAME_LEN) {
+ if (gsm_decode(tmp->gsm, data + GSM_FRAME_LEN, dst + pvt->samples)) {
+ ast_log(LOG_WARNING, "Invalid GSM data (2)\n");
return -1;
}
+ pvt->samples += GSM_SAMPLES;
+ pvt->datalen += 2 * GSM_SAMPLES;
}
}
-
- /* just add the last 20ms frame; there must have been at least one */
- if(useplc) plc_rx(&tmp->plc, tmp->buf+tmp->tail-160, 160);
-
return 0;
}
-static int lintogsm_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
+/*! \brief store samples into working buffer for later decode */
+static int lintogsm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
- /* Just add the frames to our stream */
+ struct gsm_translator_pvt *tmp = pvt->pvt;
+
/* XXX We should look at how old the rest of our stream is, and if it
is too old, then we should overwrite it entirely, otherwise we can
get artifacts of earlier talk that do not belong */
- if (tmp->tail + f->datalen/2 < sizeof(tmp->buf) / 2) {
- memcpy((tmp->buf + tmp->tail), f->data, f->datalen);
- tmp->tail += f->datalen/2;
- } else {
+ if (pvt->samples + f->samples > BUFFER_SAMPLES) {
ast_log(LOG_WARNING, "Out of buffer space\n");
return -1;
}
+ memcpy(tmp->buf + pvt->samples, f->data, f->datalen);
+ pvt->samples += f->samples;
return 0;
}
-static struct ast_frame *lintogsm_frameout(struct ast_translator_pvt *tmp)
+/*! \brief encode and produce a frame */
+static struct ast_frame *lintogsm_frameout(struct ast_trans_pvt *pvt)
{
- int x=0;
+ struct gsm_translator_pvt *tmp = pvt->pvt;
+ int datalen = 0;
+ int samples = 0;
+
/* We can't work on anything less than a frame in size */
- if (tmp->tail < 160)
+ if (pvt->samples < GSM_SAMPLES)
return NULL;
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_GSM;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->outbuf;
- while(tmp->tail >= 160) {
- if ((x+1) * 33 >= sizeof(tmp->outbuf)) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- break;
- }
+ while (pvt->samples >= GSM_SAMPLES) {
/* Encode a frame of data */
- gsm_encode(tmp->gsm, tmp->buf, ((gsm_byte *) tmp->outbuf) + (x * 33));
- /* Assume 8000 Hz -- 20 ms */
- tmp->tail -= 160;
+ gsm_encode(tmp->gsm, tmp->buf, (gsm_byte *)pvt->outbuf + datalen);
+ datalen += GSM_FRAME_LEN;
+ samples += GSM_SAMPLES;
+ pvt->samples -= GSM_SAMPLES;
/* Move the data at the end of the buffer to the front */
- if (tmp->tail)
- memmove(tmp->buf, tmp->buf + 160, tmp->tail * 2);
- x++;
+ if (pvt->samples)
+ memmove(tmp->buf, tmp->buf + GSM_SAMPLES, pvt->samples * 2);
}
- tmp->f.datalen = x * 33;
- tmp->f.samples = x * 160;
- return &tmp->f;
+ return ast_trans_frameout(pvt, datalen, samples);
}
-static void gsm_destroy_stuff(struct ast_translator_pvt *pvt)
+static void gsm_destroy_stuff(struct ast_trans_pvt *pvt)
{
- if (pvt->gsm)
- gsm_destroy(pvt->gsm);
- free(pvt);
- localusecnt--;
+ struct gsm_translator_pvt *tmp = pvt->pvt;
+ if (tmp->gsm)
+ gsm_destroy(tmp->gsm);
}
-static struct ast_translator gsmtolin =
- { "gsmtolin",
- AST_FORMAT_GSM, AST_FORMAT_SLINEAR,
- gsm_new,
- gsmtolin_framein,
- gsmtolin_frameout,
- gsm_destroy_stuff,
- gsmtolin_sample
- };
+static struct ast_module_lock me = { .usecnt = -1 };
+
+static struct ast_translator gsmtolin = {
+ .name = "gsmtolin",
+ .srcfmt = AST_FORMAT_GSM,
+ .dstfmt = AST_FORMAT_SLINEAR,
+ .newpvt = gsm_new,
+ .framein = gsmtolin_framein,
+ .destroy = gsm_destroy_stuff,
+ .sample = gsmtolin_sample,
+ .lockp = &me,
+ .buffer_samples = BUFFER_SAMPLES,
+ .buf_size = BUFFER_SAMPLES * 2,
+ .desc_size = sizeof (struct gsm_translator_pvt ),
+ .plc_samples = GSM_SAMPLES,
+};
-static struct ast_translator lintogsm =
- { "lintogsm",
- AST_FORMAT_SLINEAR, AST_FORMAT_GSM,
- gsm_new,
- lintogsm_framein,
- lintogsm_frameout,
- gsm_destroy_stuff,
- lintogsm_sample
- };
+static struct ast_translator lintogsm = {
+ .name = "lintogsm",
+ .srcfmt = AST_FORMAT_SLINEAR,
+ .dstfmt = AST_FORMAT_GSM,
+ .newpvt = gsm_new,
+ .framein = lintogsm_framein,
+ .frameout = lintogsm_frameout,
+ .destroy = gsm_destroy_stuff,
+ .sample = lintogsm_sample,
+ .lockp = &me,
+ .desc_size = sizeof (struct gsm_translator_pvt ),
+ .buf_size = (BUFFER_SAMPLES * GSM_FRAME_LEN + GSM_SAMPLES - 1)/GSM_SAMPLES,
+};
static void parse_config(void)
{
- struct ast_config *cfg;
struct ast_variable *var;
- if ((cfg = ast_config_load("codecs.conf"))) {
- if ((var = ast_variable_browse(cfg, "plc"))) {
- while (var) {
- if (!strcasecmp(var->name, "genericplc")) {
- useplc = ast_true(var->value) ? 1 : 0;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "codec_gsm: %susing generic PLC\n", useplc ? "" : "not ");
- }
- var = var->next;
- }
- }
- ast_config_destroy(cfg);
+ struct ast_config *cfg = ast_config_load("codecs.conf");
+ if (!cfg)
+ return;
+ for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
+ if (!strcasecmp(var->name, "genericplc")) {
+ gsmtolin.useplc = ast_true(var->value) ? 1 : 0;
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "codec_gsm: %susing generic PLC\n", gsmtolin.useplc ? "" : "not ");
+ }
}
+ ast_config_destroy(cfg);
}
+/*! \brief standard module glue */
int reload(void)
{
parse_config();
@@ -317,13 +261,13 @@ int reload(void)
int unload_module(void)
{
int res;
- ast_mutex_lock(&localuser_lock);
+ ast_mutex_lock(&me.lock);
res = ast_unregister_translator(&lintogsm);
if (!res)
res = ast_unregister_translator(&gsmtolin);
- if (localusecnt)
+ if (me.usecnt)
res = -1;
- ast_mutex_unlock(&localuser_lock);
+ ast_mutex_unlock(&me.lock);
return res;
}
@@ -341,14 +285,12 @@ int load_module(void)
char *description(void)
{
- return tdesc;
+ return "GSM/PCM16 (signed linear) Codec Translator";
}
int usecount(void)
{
- int res;
- OLD_STANDARD_USECOUNT(res);
- return res;
+ return me.usecnt;
}
char *key()
diff --git a/codecs/codec_ilbc.c b/codecs/codec_ilbc.c
index fb042cfa5..35404f665 100644
--- a/codecs/codec_ilbc.c
+++ b/codecs/codec_ilbc.c
@@ -54,49 +54,32 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define ILBC_MS 30
/* #define ILBC_MS 20 */
-AST_MUTEX_DEFINE_STATIC(localuser_lock);
-static int localusecnt=0;
+#define ILBC_FRAME_LEN 50 /* apparently... */
+#define ILBC_SAMPLES 240 /* 30ms at 8000 hz */
+#define BUFFER_SAMPLES 8000
static char *tdesc = "iLBC/PCM16 (signed linear) Codec Translator";
-struct ast_translator_pvt {
+struct ilbc_coder_pvt {
iLBC_Enc_Inst_t enc;
iLBC_Dec_Inst_t dec;
- struct ast_frame f;
- /* Space to build offset */
- char offset[AST_FRIENDLY_OFFSET];
- /* Buffer for our outgoing frame */
- short outbuf[8000];
/* Enough to store a full second */
- short buf[8000];
- int tail;
+ int16_t buf[BUFFER_SAMPLES];
};
-#define ilbc_coder_pvt ast_translator_pvt
-
-static struct ast_translator_pvt *lintoilbc_new(void)
+static void *lintoilbc_new(struct ast_trans_pvt *pvt)
{
- struct ilbc_coder_pvt *tmp;
- if ((tmp = ast_malloc(sizeof(*tmp)))) {
- /* Shut valgrind up */
- memset(&tmp->enc, 0, sizeof(tmp->enc));
- initEncode(&tmp->enc, ILBC_MS);
- tmp->tail = 0;
- localusecnt++;
- }
+ struct ilbc_coder_pvt *tmp = pvt->pvt;
+
+ initEncode(&tmp->enc, ILBC_MS);
return tmp;
}
-static struct ast_translator_pvt *ilbctolin_new(void)
+static void *ilbctolin_new(struct ast_trans_pvt *pvt)
{
- struct ilbc_coder_pvt *tmp;
- if ((tmp = ast_malloc(sizeof(*tmp)))) {
- /* Shut valgrind up */
- memset(&tmp->dec, 0, sizeof(tmp->dec));
- initDecode(&tmp->dec, ILBC_MS, USE_ILBC_ENHANCER);
- tmp->tail = 0;
- localusecnt++;
- }
+ struct ilbc_coder_pvt *tmp = pvt->pvt;
+
+ initDecode(&tmp->dec, ILBC_MS, USE_ILBC_ENHANCER);
return tmp;
}
@@ -106,7 +89,6 @@ static struct ast_frame *lintoilbc_sample(void)
f.frametype = AST_FRAME_VOICE;
f.subclass = AST_FORMAT_SLINEAR;
f.datalen = sizeof(slin_ilbc_ex);
- /* Assume 8000 Hz */
f.samples = sizeof(slin_ilbc_ex)/2;
f.mallocd = 0;
f.offset = 0;
@@ -122,7 +104,7 @@ static struct ast_frame *ilbctolin_sample(void)
f.subclass = AST_FORMAT_ILBC;
f.datalen = sizeof(ilbc_slin_ex);
/* All frames are 30 ms long */
- f.samples = 240;
+ f.samples = ILBC_SAMPLES;
f.mallocd = 0;
f.offset = 0;
f.src = __PRETTY_FUNCTION__;
@@ -130,161 +112,120 @@ static struct ast_frame *ilbctolin_sample(void)
return &f;
}
-static struct ast_frame *ilbctolin_frameout(struct ast_translator_pvt *tmp)
-{
- if (!tmp->tail)
- return NULL;
- /* Signed linear is no particular frame size, so just send whatever
- we have in the buffer in one lump sum */
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_SLINEAR;
- tmp->f.datalen = tmp->tail * 2;
- /* Assume 8000 Hz */
- tmp->f.samples = tmp->tail;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->buf;
- /* Reset tail pointer */
- tmp->tail = 0;
-
- return &tmp->f;
-}
-
-static int ilbctolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
+/*! \brief decode a frame and store in outbuf */
+static int ilbctolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
+ struct ilbc_coder_pvt *tmp = pvt->pvt;
+ int plc_mode = 1; /* 1 = normal data, 0 = plc */
/* Assuming there's space left, decode into the current buffer at
the tail location. Read in as many frames as there are */
int x,i;
- float tmpf[240];
-
- if (f->datalen == 0) { /* native PLC */
- if (tmp->tail + 240 < sizeof(tmp->buf)/2) {
- iLBC_decode(tmpf, NULL, &tmp->dec, 0);
- for (i=0;i<240;i++)
- tmp->buf[tmp->tail + i] = tmpf[i];
- tmp->tail+=240;
- } else {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
+ int16_t *dst = (int16_t *)pvt->outbuf;
+ float tmpf[ILBC_SAMPLES];
+
+ if (f->datalen == 0) { /* native PLC, set fake f->datalen and clear plc_mode */
+ f->datalen = ILBC_FRAME_LEN;
+ f->samples = ILBC_SAMPLES;
+ plc_mode = 0; /* do native plc */
+ pvt->samples += ILBC_SAMPLES;
}
- if (f->datalen % 50) {
+ if (f->datalen % ILBC_FRAME_LEN) {
ast_log(LOG_WARNING, "Huh? An ilbc frame that isn't a multiple of 50 bytes long from %s (%d)?\n", f->src, f->datalen);
return -1;
}
- for (x=0;x<f->datalen;x+=50) {
- if (tmp->tail + 240 < sizeof(tmp->buf)/2) {
- iLBC_decode(tmpf, f->data + x, &tmp->dec, 1);
- for (i=0;i<240;i++)
- tmp->buf[tmp->tail + i] = tmpf[i];
- tmp->tail+=240;
- } else {
+ for (x=0; x < f->datalen ; x += ILBC_FRAME_LEN) {
+ if (pvt->samples + ILBC_SAMPLES > BUFFER_SAMPLES) {
ast_log(LOG_WARNING, "Out of buffer space\n");
return -1;
}
+ iLBC_decode(tmpf, plc_mode ? f->data + x : NULL, &tmp->dec, plc_mode);
+ for ( i=0; i < ILBC_SAMPLES; i++)
+ dst[pvt->samples + i] = tmpf[i];
+ pvt->samples += ILBC_SAMPLES;
+ pvt->datalen += 2*ILBC_SAMPLES;
}
return 0;
}
-static int lintoilbc_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
+/*! \brief store a frame into a temporary buffer, for later decoding */
+static int lintoilbc_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
+ struct ilbc_coder_pvt *tmp = pvt->pvt;
+
/* Just add the frames to our stream */
/* XXX We should look at how old the rest of our stream is, and if it
is too old, then we should overwrite it entirely, otherwise we can
get artifacts of earlier talk that do not belong */
- if (tmp->tail + f->datalen/2 < sizeof(tmp->buf) / 2) {
- memcpy((tmp->buf + tmp->tail), f->data, f->datalen);
- tmp->tail += f->datalen/2;
- } else {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
+ memcpy(tmp->buf + pvt->samples, f->data, f->datalen);
+ pvt->samples += f->samples;
return 0;
}
-static struct ast_frame *lintoilbc_frameout(struct ast_translator_pvt *tmp)
+/*! \brief encode the temporary buffer and generate a frame */
+static struct ast_frame *lintoilbc_frameout(struct ast_trans_pvt *pvt)
{
- int x=0,i;
- float tmpf[240];
+ struct ilbc_coder_pvt *tmp = pvt->pvt;
+ int datalen = 0;
+ int samples = 0;
+
/* We can't work on anything less than a frame in size */
- if (tmp->tail < 240)
+ if (pvt->samples < ILBC_SAMPLES)
return NULL;
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_ILBC;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->outbuf;
- while(tmp->tail >= 240) {
- if ((x+1) * 50 >= sizeof(tmp->outbuf)) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- break;
- }
- for (i=0;i<240;i++)
- tmpf[i] = tmp->buf[i];
+ while (pvt->samples >= ILBC_SAMPLES) {
+ float tmpf[ILBC_SAMPLES];
+ int i;
/* Encode a frame of data */
- iLBC_encode(((unsigned char *)(tmp->outbuf)) + (x * 50), tmpf, &tmp->enc);
- /* Assume 8000 Hz -- 20 ms */
- tmp->tail -= 240;
+ for ( i = 0 ; i < ILBC_SAMPLES ; i++ )
+ tmpf[i] = tmp->buf[i];
+ iLBC_encode(pvt->outbuf + datalen, tmpf, &tmp->enc);
+ datalen += ILBC_FRAME_LEN;
+ samples += ILBC_SAMPLES;
+ pvt->samples -= ILBC_SAMPLES;
/* Move the data at the end of the buffer to the front */
- if (tmp->tail)
- memmove(tmp->buf, tmp->buf + 240, tmp->tail * 2);
- x++;
- }
- tmp->f.datalen = x * 50;
- tmp->f.samples = x * 240;
-#if 0
- {
- static int fd = -1;
- if (fd == -1) {
- fd = open("ilbc.out", O_CREAT|O_TRUNC|O_WRONLY, 0666);
- write(fd, tmp->f.data, tmp->f.datalen);
- close(fd);
- }
+ if (pvt->samples)
+ memmove(tmp->buf, tmp->buf + ILBC_SAMPLES, pvt->samples * 2);
}
-#endif
- return &tmp->f;
+ return ast_trans_frameout(pvt, datalen, samples);
}
-static void ilbc_destroy_stuff(struct ast_translator_pvt *pvt)
-{
- free(pvt);
- localusecnt--;
-}
+static struct ast_module_lock me = { .usecnt = -1 };
-static struct ast_translator ilbctolin =
- { "ilbctolin",
- AST_FORMAT_ILBC, AST_FORMAT_SLINEAR,
- ilbctolin_new,
- ilbctolin_framein,
- ilbctolin_frameout,
- ilbc_destroy_stuff,
- ilbctolin_sample
- };
-
-static struct ast_translator lintoilbc =
- { "lintoilbc",
- AST_FORMAT_SLINEAR, AST_FORMAT_ILBC,
- lintoilbc_new,
- lintoilbc_framein,
- lintoilbc_frameout,
- ilbc_destroy_stuff,
- lintoilbc_sample
- };
+static struct ast_translator ilbctolin = {
+ .name = "ilbctolin",
+ .srcfmt = AST_FORMAT_ILBC,
+ .dstfmt = AST_FORMAT_SLINEAR,
+ .newpvt = ilbctolin_new,
+ .framein = ilbctolin_framein,
+ .sample = ilbctolin_sample,
+ .desc_size = sizeof(struct ilbc_coder_pvt),
+ .buf_size = BUFFER_SAMPLES * 2,
+ .lockp = &me,
+};
+
+static struct ast_translator lintoilbc = {
+ .name = "lintoilbc",
+ .srcfmt = AST_FORMAT_SLINEAR,
+ .dstfmt = AST_FORMAT_ILBC,
+ .newpvt = lintoilbc_new,
+ .framein = lintoilbc_framein,
+ .frameout = lintoilbc_frameout,
+ .sample = lintoilbc_sample,
+ .desc_size = sizeof(struct ilbc_coder_pvt),
+ .buf_size = (BUFFER_SAMPLES * ILBC_FRAME_LEN + ILBC_SAMPLES - 1) / ILBC_SAMPLES,
+ .lockp = &me,
+};
int unload_module(void)
{
int res;
- ast_mutex_lock(&localuser_lock);
+ ast_mutex_lock(&me.lock);
res = ast_unregister_translator(&lintoilbc);
- if (!res)
- res = ast_unregister_translator(&ilbctolin);
- if (localusecnt)
+ res |= ast_unregister_translator(&ilbctolin);
+ if (me.usecnt)
res = -1;
- ast_mutex_unlock(&localuser_lock);
+ ast_mutex_unlock(&me.lock);
return res;
}
@@ -306,9 +247,7 @@ char *description(void)
int usecount(void)
{
- int res;
- OLD_STANDARD_USECOUNT(res);
- return res;
+ return me.usecnt;
}
char *key()
diff --git a/codecs/codec_lpc10.c b/codecs/codec_lpc10.c
index f9157cdc8..c2800690a 100644
--- a/codecs/codec_lpc10.c
+++ b/codecs/codec_lpc10.c
@@ -60,62 +60,36 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define LPC10_BYTES_IN_COMPRESSED_FRAME (LPC10_BITS_IN_COMPRESSED_FRAME + 7)/8
-AST_MUTEX_DEFINE_STATIC(localuser_lock);
-static int localusecnt=0;
+#define BUFFER_SAMPLES 8000
-static char *tdesc = "LPC10 2.4kbps (signed linear) Voice Coder";
-
-static int useplc = 0;
-
-struct ast_translator_pvt {
+struct lpc10_coder_pvt {
union {
struct lpc10_encoder_state *enc;
struct lpc10_decoder_state *dec;
} lpc10;
- struct ast_frame f;
- /* Space to build offset */
- char offset[AST_FRIENDLY_OFFSET];
- /* Buffer for our outgoing frame */
- short outbuf[8000];
/* Enough to store a full second */
- short buf[8000];
- int tail;
+ short buf[BUFFER_SAMPLES];
int longer;
- plc_state_t plc; /* god only knows why I bothered to implement PLC for LPC10 :) */
};
-#define lpc10_coder_pvt ast_translator_pvt
-
-static struct ast_translator_pvt *lpc10_enc_new(void)
+static void *lpc10_enc_new(struct ast_trans_pvt *pvt)
{
- struct lpc10_coder_pvt *tmp;
- if ((tmp = ast_malloc(sizeof(*tmp)))) {
- if (!(tmp->lpc10.enc = create_lpc10_encoder_state())) {
- free(tmp);
- tmp = NULL;
- }
- tmp->tail = 0;
- tmp->longer = 0;
- localusecnt++;
- }
+ struct lpc10_coder_pvt *tmp = pvt->pvt;
+
+ if (!(tmp->lpc10.enc = create_lpc10_encoder_state()))
+ return NULL;
return tmp;
}
-static struct ast_translator_pvt *lpc10_dec_new(void)
+static void *lpc10_dec_new(struct ast_trans_pvt *pvt)
{
- struct lpc10_coder_pvt *tmp;
- if ((tmp = ast_malloc(sizeof(*tmp)))) {
- if (!(tmp->lpc10.dec = create_lpc10_decoder_state())) {
- free(tmp);
- tmp = NULL;
- }
- tmp->tail = 0;
- tmp->longer = 0;
- plc_init(&tmp->plc);
- localusecnt++;
- }
+ struct lpc10_coder_pvt *tmp = pvt->pvt;
+
+ if (!(tmp->lpc10.dec = create_lpc10_decoder_state()))
+ return NULL;
return tmp;
}
+
static struct ast_frame *lintolpc10_sample(void)
{
static struct ast_frame f;
@@ -147,39 +121,6 @@ static struct ast_frame *lpc10tolin_sample(void)
return &f;
}
-static struct ast_frame *lpc10tolin_frameout(struct ast_translator_pvt *tmp)
-{
- if (!tmp->tail)
- return NULL;
- /* Signed linear is no particular frame size, so just send whatever
- we have in the buffer in one lump sum */
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_SLINEAR;
- tmp->f.datalen = tmp->tail * 2;
- /* Assume 8000 Hz */
- tmp->f.samples = tmp->tail;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->buf;
- /* Reset tail pointer */
- tmp->tail = 0;
-
-#if 0
- /* Save a sample frame */
- { static int samplefr = 0;
- if (samplefr == 80) {
- int fd;
- fd = open("lpc10.example", O_WRONLY | O_CREAT, 0644);
- write(fd, tmp->f.data, tmp->f.datalen);
- close(fd);
- }
- samplefr++;
- }
-#endif
- return &tmp->f;
-}
-
static void extract_bits(INT32 *bits, unsigned char *c)
{
int x;
@@ -193,6 +134,7 @@ static void extract_bits(INT32 *bits, unsigned char *c)
}
}
+/* XXX note lpc10_encode() produces one bit per word in bits[] */
static void build_bits(unsigned char *c, INT32 *bits)
{
unsigned char mask=0x80;
@@ -210,48 +152,32 @@ static void build_bits(unsigned char *c, INT32 *bits)
}
}
-static int lpc10tolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
+static int lpc10tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
- /* Assuming there's space left, decode into the current buffer at
- the tail location */
- int x;
- int len=0;
- float tmpbuf[LPC10_SAMPLES_PER_FRAME];
- short *sd;
- INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
-
- if(f->datalen == 0) { /* perform PLC with nominal framesize of LPC10_SAMPLES_PER_FRAME */
- if((tmp->tail + LPC10_SAMPLES_PER_FRAME) > sizeof(tmp->buf)/2) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
- if(useplc) {
- plc_fillin(&tmp->plc, tmp->buf+tmp->tail, LPC10_SAMPLES_PER_FRAME);
- tmp->tail += LPC10_SAMPLES_PER_FRAME;
- }
- return 0;
- }
-
- while(len + LPC10_BYTES_IN_COMPRESSED_FRAME <= f->datalen) {
- if (tmp->tail + LPC10_SAMPLES_PER_FRAME < sizeof(tmp->buf)/2) {
- sd = tmp->buf + tmp->tail;
- extract_bits(bits, f->data + len);
- if (lpc10_decode(bits, tmpbuf, tmp->lpc10.dec)) {
- ast_log(LOG_WARNING, "Invalid lpc10 data\n");
- return -1;
- }
- for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
- /* Convert to a real between -1.0 and 1.0 */
- sd[x] = 32768.0 * tmpbuf[x];
- }
-
- if(useplc) plc_rx(&tmp->plc, tmp->buf + tmp->tail, LPC10_SAMPLES_PER_FRAME);
-
- tmp->tail+=LPC10_SAMPLES_PER_FRAME;
- } else {
+ struct lpc10_coder_pvt *tmp = pvt->pvt;
+ int16_t *dst = (int16_t *)pvt->outbuf;
+ int len = 0;
+
+ while (len + LPC10_BYTES_IN_COMPRESSED_FRAME <= f->datalen) {
+ int x;
+ float tmpbuf[LPC10_SAMPLES_PER_FRAME];
+ INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME]; /* XXX see note */
+ if (pvt->samples + LPC10_SAMPLES_PER_FRAME > BUFFER_SAMPLES) {
ast_log(LOG_WARNING, "Out of buffer space\n");
return -1;
}
+ extract_bits(bits, f->data + len);
+ if (lpc10_decode(bits, tmpbuf, tmp->lpc10.dec)) {
+ ast_log(LOG_WARNING, "Invalid lpc10 data\n");
+ return -1;
+ }
+ for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
+ /* Convert to a short between -1.0 and 1.0 */
+ dst[pvt->samples + x] = (int16_t)(32768.0 * tmpbuf[x]);
+ }
+
+ pvt->samples += LPC10_SAMPLES_PER_FRAME;
+ pvt->datalen += 2*LPC10_SAMPLES_PER_FRAME;
len += LPC10_BYTES_IN_COMPRESSED_FRAME;
}
if (len != f->datalen)
@@ -259,125 +185,108 @@ static int lpc10tolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *
return 0;
}
-static int lintolpc10_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
+static int lintolpc10_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
+ struct lpc10_coder_pvt *tmp = pvt->pvt;
+
/* Just add the frames to our stream */
- /* XXX We should look at how old the rest of our stream is, and if it
- is too old, then we should overwrite it entirely, otherwise we can
- get artifacts of earlier talk that do not belong */
- if (tmp->tail + f->datalen < sizeof(tmp->buf) / 2) {
- memcpy((tmp->buf + tmp->tail), f->data, f->datalen);
- tmp->tail += f->datalen/2;
- } else {
+ if (pvt->samples + f->samples > BUFFER_SAMPLES) {
ast_log(LOG_WARNING, "Out of buffer space\n");
return -1;
}
+ memcpy(tmp->buf + pvt->samples, f->data, f->datalen);
+ pvt->samples += f->samples;
return 0;
}
-static struct ast_frame *lintolpc10_frameout(struct ast_translator_pvt *tmp)
+static struct ast_frame *lintolpc10_frameout(struct ast_trans_pvt *pvt)
{
+ struct lpc10_coder_pvt *tmp = pvt->pvt;
int x;
- int consumed = 0;
+ int datalen = 0; /* output frame */
+ int samples = 0; /* output samples */
float tmpbuf[LPC10_SAMPLES_PER_FRAME];
- INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
+ INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME]; /* XXX what ??? */
/* We can't work on anything less than a frame in size */
- if (tmp->tail < LPC10_SAMPLES_PER_FRAME)
+ if (pvt->samples < LPC10_SAMPLES_PER_FRAME)
return NULL;
- /* Start with an empty frame */
- tmp->f.samples = 0;
- tmp->f.datalen = 0;
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_LPC10;
- while(tmp->tail >= LPC10_SAMPLES_PER_FRAME) {
- if (tmp->f.datalen + LPC10_BYTES_IN_COMPRESSED_FRAME > sizeof(tmp->outbuf)) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return NULL;
- }
+ while (pvt->samples >= LPC10_SAMPLES_PER_FRAME) {
/* Encode a frame of data */
- for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
- tmpbuf[x] = (float)tmp->buf[x+consumed] / 32768.0;
- }
+ for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++)
+ tmpbuf[x] = (float)tmp->buf[x + samples] / 32768.0;
lpc10_encode(tmpbuf, bits, tmp->lpc10.enc);
- build_bits(((unsigned char *)tmp->outbuf) + tmp->f.datalen, bits);
- tmp->f.datalen += LPC10_BYTES_IN_COMPRESSED_FRAME;
- tmp->f.samples += LPC10_SAMPLES_PER_FRAME;
+ build_bits(pvt->outbuf + datalen, bits);
+ datalen += LPC10_BYTES_IN_COMPRESSED_FRAME;
+ samples += LPC10_SAMPLES_PER_FRAME;
+ pvt->samples -= LPC10_SAMPLES_PER_FRAME;
/* Use one of the two left over bits to record if this is a 22 or 23 ms frame...
important for IAX use */
tmp->longer = 1 - tmp->longer;
#if 0 /* what the heck was this for? */
((char *)(tmp->f.data))[consumed - 1] |= tmp->longer;
#endif
- tmp->tail -= LPC10_SAMPLES_PER_FRAME;
- consumed += LPC10_SAMPLES_PER_FRAME;
}
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->outbuf;
/* Move the data at the end of the buffer to the front */
- if (tmp->tail)
- memmove(tmp->buf, tmp->buf + consumed, tmp->tail * 2);
-#if 0
- /* Save a sample frame */
- { static int samplefr = 0;
- if (samplefr == 0) {
- int fd;
- fd = open("lpc10.example", O_WRONLY | O_CREAT, 0644);
- write(fd, tmp->f.data, tmp->f.datalen);
- close(fd);
- }
- samplefr++;
- }
-#endif
- return &tmp->f;
+ if (pvt->samples)
+ memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
+ return ast_trans_frameout(pvt, datalen, samples);
}
-static void lpc10_destroy(struct ast_translator_pvt *pvt)
+
+static void lpc10_destroy(struct ast_trans_pvt *arg)
{
+ struct lpc10_coder_pvt *pvt = arg->pvt;
/* Enc and DEC are both just allocated, so they can be freed */
free(pvt->lpc10.enc);
- free(pvt);
- localusecnt--;
}
-static struct ast_translator lpc10tolin =
- { "lpc10tolin",
- AST_FORMAT_LPC10, AST_FORMAT_SLINEAR,
- lpc10_dec_new,
- lpc10tolin_framein,
- lpc10tolin_frameout,
- lpc10_destroy,
- lpc10tolin_sample
- };
-
-static struct ast_translator lintolpc10 =
- { "lintolpc10",
- AST_FORMAT_SLINEAR, AST_FORMAT_LPC10,
- lpc10_enc_new,
- lintolpc10_framein,
- lintolpc10_frameout,
- lpc10_destroy,
- lintolpc10_sample
- };
+static struct ast_module_lock me = { .usecnt = -1 };
+
+static struct ast_translator lpc10tolin = {
+ .name = "lpc10tolin",
+ .srcfmt = AST_FORMAT_LPC10,
+ .dstfmt = AST_FORMAT_SLINEAR,
+ .newpvt = lpc10_dec_new,
+ .framein = lpc10tolin_framein,
+ .destroy = lpc10_destroy,
+ .sample = lpc10tolin_sample,
+ .lockp = &me,
+ .desc_size = sizeof(struct lpc10_coder_pvt),
+ .buffer_samples = BUFFER_SAMPLES,
+ .plc_samples = LPC10_SAMPLES_PER_FRAME,
+ .buf_size = BUFFER_SAMPLES * 2,
+};
+
+static struct ast_translator lintolpc10 = {
+ .name = "lintolpc10",
+ .srcfmt = AST_FORMAT_SLINEAR,
+ .dstfmt = AST_FORMAT_LPC10,
+ .newpvt = lpc10_enc_new,
+ .framein = lintolpc10_framein,
+ .frameout = lintolpc10_frameout,
+ .destroy = lpc10_destroy,
+ .sample = lintolpc10_sample,
+ .lockp = &me,
+ .desc_size = sizeof(struct lpc10_coder_pvt),
+ .buffer_samples = BUFFER_SAMPLES,
+ .buf_size = LPC10_BYTES_IN_COMPRESSED_FRAME * (1 + BUFFER_SAMPLES / LPC10_SAMPLES_PER_FRAME),
+};
static void parse_config(void)
{
- struct ast_config *cfg;
struct ast_variable *var;
- if ((cfg = ast_config_load("codecs.conf"))) {
- if ((var = ast_variable_browse(cfg, "plc"))) {
- while (var) {
- if (!strcasecmp(var->name, "genericplc")) {
- useplc = ast_true(var->value) ? 1 : 0;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "codec_lpc10: %susing generic PLC\n", useplc ? "" : "not ");
- }
- var = var->next;
- }
- }
- ast_config_destroy(cfg);
+ struct ast_config *cfg = ast_config_load("codecs.conf");
+ if (!cfg)
+ return;
+ for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
+ if (!strcasecmp(var->name, "genericplc")) {
+ lpc10tolin.useplc = ast_true(var->value) ? 1 : 0;
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "codec_lpc10: %susing generic PLC\n",
+ lpc10tolin.useplc ? "" : "not ");
+ }
}
+ ast_config_destroy(cfg);
}
int reload(void)
@@ -390,13 +299,13 @@ int reload(void)
int unload_module(void)
{
int res;
- ast_mutex_lock(&localuser_lock);
+ ast_mutex_lock(&me.lock);
res = ast_unregister_translator(&lintolpc10);
if (!res)
res = ast_unregister_translator(&lpc10tolin);
- if (localusecnt)
+ if (me.usecnt)
res = -1;
- ast_mutex_unlock(&localuser_lock);
+ ast_mutex_unlock(&me.lock);
return res;
}
@@ -414,14 +323,12 @@ int load_module(void)
char *description(void)
{
- return tdesc;
+ return "LPC10 2.4kbps (signed linear) Voice Coder";
}
int usecount(void)
{
- int res;
- OLD_STANDARD_USECOUNT(res);
- return res;
+ return me.usecnt;
}
char *key()
diff --git a/codecs/codec_speex.c b/codecs/codec_speex.c
index fc9b22bfb..daaf5eda6 100644
--- a/codecs/codec_speex.c
+++ b/codecs/codec_speex.c
@@ -41,6 +41,7 @@
#include <speex/speex_preprocess.h>
#endif
+/* codec variables */
static int quality = 3;
static int complexity = 2;
static int enhancement = 0;
@@ -48,12 +49,12 @@ static int vad = 0;
static int vbr = 0;
static float vbr_quality = 4;
static int abr = 0;
-static int dtx = 0;
+static int dtx = 0; /* set to 1 to enable silence detection */
static int preproc = 0;
static int pp_vad = 0;
static int pp_agc = 0;
-static float pp_agc_level = 8000;
+static float pp_agc_level = 8000; /* XXX what is this 8000 ? */
static int pp_denoise = 0;
static int pp_dereverb = 0;
static float pp_dereverb_decay = 0.4;
@@ -81,97 +82,75 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "slin_speex_ex.h"
#include "speex_slin_ex.h"
-AST_MUTEX_DEFINE_STATIC(localuser_lock);
-static int localusecnt=0;
+#define BUFFER_SAMPLES 8000
+#define SPEEX_SAMPLES 160
-static char *tdesc = "Speex/PCM16 (signed linear) Codec Translator";
-
-struct ast_translator_pvt {
+struct speex_coder_pvt {
void *speex;
- struct ast_frame f;
SpeexBits bits;
int framesize;
- /* Space to build offset */
- char offset[AST_FRIENDLY_OFFSET];
+ int silent_state;
#ifdef _SPEEX_TYPES_H
SpeexPreprocessState *pp;
- /* Buffer for our outgoing frame */
- spx_int16_t outbuf[8000];
- /* Enough to store a full second */
- spx_int16_t buf[8000];
+ spx_int16_t buf[BUFFER_SAMPLES];
#else
- short outbuf[8000];
- short buf[8000];
+ int16_t buf[BUFFER_SAMPLES]; /* input, waiting to be compressed */
#endif
-
- int tail;
- int silent_state;
};
-#define speex_coder_pvt ast_translator_pvt
-static struct ast_translator_pvt *lintospeex_new(void)
+static void *lintospeex_new(struct ast_trans_pvt *pvt)
{
- struct speex_coder_pvt *tmp;
- if ((tmp = ast_malloc(sizeof(*tmp)))) {
- if (!(tmp->speex = speex_encoder_init(&speex_nb_mode))) {
- free(tmp);
- tmp = NULL;
- } else {
- speex_bits_init(&tmp->bits);
- speex_bits_reset(&tmp->bits);
- speex_encoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize);
- speex_encoder_ctl(tmp->speex, SPEEX_SET_COMPLEXITY, &complexity);
+ struct speex_coder_pvt *tmp = pvt->pvt;
+
+ if (!(tmp->speex = speex_encoder_init(&speex_nb_mode)))
+ return NULL;
+
+ speex_bits_init(&tmp->bits);
+ speex_bits_reset(&tmp->bits);
+ speex_encoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize);
+ ast_log(LOG_WARNING, "speex framesize is %d\n", tmp->framesize);
+ speex_encoder_ctl(tmp->speex, SPEEX_SET_COMPLEXITY, &complexity);
#ifdef _SPEEX_TYPES_H
- if (preproc) {
- tmp->pp = speex_preprocess_state_init(tmp->framesize, 8000);
- speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_VAD, &pp_vad);
- speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_AGC, &pp_agc);
- speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &pp_agc_level);
- speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DENOISE, &pp_denoise);
- speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB, &pp_dereverb);
- speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &pp_dereverb_decay);
- speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &pp_dereverb_level);
- }
+ if (preproc) {
+ tmp->pp = speex_preprocess_state_init(tmp->framesize, 8000); /* XXX what is this 8000 ? */
+ speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_VAD, &pp_vad);
+ speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_AGC, &pp_agc);
+ speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &pp_agc_level);
+ speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DENOISE, &pp_denoise);
+ speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB, &pp_dereverb);
+ speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &pp_dereverb_decay);
+ speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &pp_dereverb_level);
+ }
#endif
- if (!abr && !vbr) {
- speex_encoder_ctl(tmp->speex, SPEEX_SET_QUALITY, &quality);
- if (vad)
- speex_encoder_ctl(tmp->speex, SPEEX_SET_VAD, &vad);
- }
- if (vbr) {
- speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR, &vbr);
- speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR_QUALITY, &vbr_quality);
- }
- if (abr) {
- speex_encoder_ctl(tmp->speex, SPEEX_SET_ABR, &abr);
- }
- if (dtx)
- speex_encoder_ctl(tmp->speex, SPEEX_SET_DTX, &dtx);
- tmp->tail = 0;
- tmp->silent_state = 0;
- }
- localusecnt++;
+ if (!abr && !vbr) {
+ speex_encoder_ctl(tmp->speex, SPEEX_SET_QUALITY, &quality);
+ if (vad)
+ speex_encoder_ctl(tmp->speex, SPEEX_SET_VAD, &vad);
}
+ if (vbr) {
+ speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR, &vbr);
+ speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR_QUALITY, &vbr_quality);
+ }
+ if (abr)
+ speex_encoder_ctl(tmp->speex, SPEEX_SET_ABR, &abr);
+ if (dtx)
+ speex_encoder_ctl(tmp->speex, SPEEX_SET_DTX, &dtx);
+ tmp->silent_state = 0;
+
return tmp;
}
-static struct ast_translator_pvt *speextolin_new(void)
+static void *speextolin_new(struct ast_trans_pvt *pvt)
{
- struct speex_coder_pvt *tmp;
- if ((tmp = ast_malloc(sizeof(*tmp)))) {
- if (!(tmp->speex = speex_decoder_init(&speex_nb_mode))) {
- free(tmp);
- tmp = NULL;
- } else {
- speex_bits_init(&tmp->bits);
- speex_decoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize);
- if (enhancement)
- speex_decoder_ctl(tmp->speex, SPEEX_SET_ENH, &enhancement);
- tmp->tail = 0;
- }
- localusecnt++;
- }
+ struct speex_coder_pvt *tmp = pvt->pvt;
+
+ if (!(tmp->speex = speex_decoder_init(&speex_nb_mode)))
+ return NULL;
+ speex_bits_init(&tmp->bits);
+ speex_decoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize);
+ if (enhancement)
+ speex_decoder_ctl(tmp->speex, SPEEX_SET_ENH, &enhancement);
return tmp;
}
@@ -197,7 +176,7 @@ static struct ast_frame *speextolin_sample(void)
f.subclass = AST_FORMAT_SPEEX;
f.datalen = sizeof(speex_slin_ex);
/* All frames are 20 ms long */
- f.samples = 160;
+ f.samples = SPEEX_SAMPLES;
f.mallocd = 0;
f.offset = 0;
f.src = __PRETTY_FUNCTION__;
@@ -205,122 +184,91 @@ static struct ast_frame *speextolin_sample(void)
return &f;
}
-static struct ast_frame *speextolin_frameout(struct ast_translator_pvt *tmp)
+/*! \brief convert and store into outbuf */
+static int speextolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
- if (!tmp->tail)
- return NULL;
- /* Signed linear is no particular frame size, so just send whatever
- we have in the buffer in one lump sum */
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_SLINEAR;
- tmp->f.datalen = tmp->tail * 2;
- /* Assume 8000 Hz */
- tmp->f.samples = tmp->tail;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->buf;
- /* Reset tail pointer */
- tmp->tail = 0;
- return &tmp->f;
-}
+ struct speex_coder_pvt *tmp = pvt->pvt;
-static int speextolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
-{
/* Assuming there's space left, decode into the current buffer at
the tail location. Read in as many frames as there are */
int x;
int res;
+ int16_t *dst = (int16_t *)pvt->outbuf;
+ /* XXX fout is a temporary buffer, may have different types */
#ifdef _SPEEX_TYPES_H
- spx_int16_t out[1024];
+ spx_int16_t fout[1024];
#else
float fout[1024];
#endif
if (f->datalen == 0) { /* Native PLC interpolation */
- if (tmp->tail + tmp->framesize > sizeof(tmp->buf) / 2) {
+ if (pvt->samples + tmp->framesize > BUFFER_SAMPLES) {
ast_log(LOG_WARNING, "Out of buffer space\n");
return -1;
}
#ifdef _SPEEX_TYPES_H
- speex_decode_int(tmp->speex, NULL, tmp->buf + tmp->tail);
+ speex_decode_int(tmp->speex, NULL, dst + pvt->samples);
#else
speex_decode(tmp->speex, NULL, fout);
for (x=0;x<tmp->framesize;x++) {
- tmp->buf[tmp->tail + x] = fout[x];
+ dst[pvt->samples + x] = (int16_t)fout[x];
}
#endif
- tmp->tail += tmp->framesize;
+ pvt->samples += tmp->framesize;
return 0;
}
/* Read in bits */
speex_bits_read_from(&tmp->bits, f->data, f->datalen);
- for(;;) {
+ for (;;) {
#ifdef _SPEEX_TYPES_H
- res = speex_decode_int(tmp->speex, &tmp->bits, out);
+ res = speex_decode_int(tmp->speex, &tmp->bits, fout);
#else
res = speex_decode(tmp->speex, &tmp->bits, fout);
#endif
if (res < 0)
break;
- if (tmp->tail + tmp->framesize < sizeof(tmp->buf) / 2) {
- for (x=0;x<tmp->framesize;x++) {
-#ifdef _SPEEX_TYPES_H
- tmp->buf[tmp->tail + x] = out[x];
-#else
- tmp->buf[tmp->tail + x] = fout[x];
-#endif
- }
- tmp->tail += tmp->framesize;
- } else {
+ if (pvt->samples + tmp->framesize > BUFFER_SAMPLES) {
ast_log(LOG_WARNING, "Out of buffer space\n");
return -1;
}
-
+ for (x = 0 ; x < tmp->framesize; x++)
+ dst[pvt->samples + x] = (int16_t)fout[x];
+ pvt->samples += tmp->framesize;
+ pvt->datalen += 2 * tmp->framesize; /* 2 bytes/sample */
}
return 0;
}
-static int lintospeex_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
+/*! \brief store input frame in work buffer */
+static int lintospeex_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
- /* Just add the frames to our stream */
+ struct speex_coder_pvt *tmp = pvt->pvt;
+
/* XXX We should look at how old the rest of our stream is, and if it
is too old, then we should overwrite it entirely, otherwise we can
get artifacts of earlier talk that do not belong */
- if (tmp->tail + f->datalen/2 < sizeof(tmp->buf) / 2) {
- memcpy((tmp->buf + tmp->tail), f->data, f->datalen);
- tmp->tail += f->datalen/2;
- } else {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
+ memcpy(tmp->buf + pvt->samples, f->data, f->datalen);
+ pvt->samples += f->samples;
return 0;
}
-static struct ast_frame *lintospeex_frameout(struct ast_translator_pvt *tmp)
+/*! \brief convert work buffer and produce output frame */
+static struct ast_frame *lintospeex_frameout(struct ast_trans_pvt *pvt)
{
-#ifndef _SPEEX_TYPES_H
- float fbuf[1024];
- int x;
-#endif
- int len;
- int y=0;
+ struct speex_coder_pvt *tmp = pvt->pvt;
int is_speech=1;
+ int datalen = 0; /* output bytes */
+ int samples = 0; /* output samples */
+
/* We can't work on anything less than a frame in size */
- if (tmp->tail < tmp->framesize)
+ if (pvt->samples < tmp->framesize)
return NULL;
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_SPEEX;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->outbuf;
speex_bits_reset(&tmp->bits);
- while(tmp->tail >= tmp->framesize) {
+ while (pvt->samples >= tmp->framesize) {
#ifdef _SPEEX_TYPES_H
/* Preprocess audio */
- if(preproc)
+ if (preproc)
is_speech = speex_preprocess(tmp->pp, tmp->buf, NULL);
/* Encode a frame of data */
if (is_speech) {
@@ -331,254 +279,230 @@ static struct ast_frame *lintospeex_frameout(struct ast_translator_pvt *tmp)
speex_bits_pack(&tmp->bits, 0, 5);
}
#else
- /* Convert to floating point */
- for (x=0;x<tmp->framesize;x++)
- fbuf[x] = tmp->buf[x];
- /* Encode a frame of data */
- is_speech = speex_encode(tmp->speex, fbuf, &tmp->bits) || !dtx;
+ {
+ float fbuf[1024];
+ int x;
+ /* Convert to floating point */
+ for (x = 0; x < tmp->framesize; x++)
+ fbuf[x] = tmp->buf[x];
+ /* Encode a frame of data */
+ is_speech = speex_encode(tmp->speex, fbuf, &tmp->bits) || !dtx;
+ }
#endif
- /* Assume 8000 Hz -- 20 ms */
- tmp->tail -= tmp->framesize;
+ samples += tmp->framesize;
+ pvt->samples -= tmp->framesize;
/* Move the data at the end of the buffer to the front */
- if (tmp->tail)
- memmove(tmp->buf, tmp->buf + tmp->framesize, tmp->tail * 2);
- y++;
+ if (pvt->samples)
+ memmove(tmp->buf, tmp->buf + tmp->framesize, pvt->samples * 2);
}
/* Use AST_FRAME_CNG to signify the start of any silence period */
- if (!is_speech) {
+ if (is_speech) {
+ tmp->silent_state = 0;
+ } else {
if (tmp->silent_state) {
return NULL;
} else {
tmp->silent_state = 1;
speex_bits_reset(&tmp->bits);
- tmp->f.frametype = AST_FRAME_CNG;
+ memset(&pvt->f, 0, sizeof(pvt->f));
+ pvt->f.frametype = AST_FRAME_CNG;
+ pvt->f.samples = samples;
+ /* XXX what now ? format etc... */
}
- } else {
- tmp->silent_state = 0;
}
/* Terminate bit stream */
speex_bits_pack(&tmp->bits, 15, 5);
- len = speex_bits_write(&tmp->bits, (char *)tmp->outbuf, sizeof(tmp->outbuf));
- tmp->f.datalen = len;
- tmp->f.samples = y * 160;
-#if 0
- {
- static int fd = -1;
- if (fd < 0) {
- fd = open("speex.raw", O_WRONLY|O_TRUNC|O_CREAT);
- if (fd > -1) {
- write(fd, tmp->f.data, tmp->f.datalen);
- close(fd);
- }
- }
- }
-#endif
- return &tmp->f;
+ datalen = speex_bits_write(&tmp->bits, pvt->outbuf, pvt->t->buf_size);
+ return ast_trans_frameout(pvt, datalen, samples);
}
-static void speextolin_destroy(struct ast_translator_pvt *pvt)
+static void speextolin_destroy(struct ast_trans_pvt *arg)
{
+ struct speex_coder_pvt *pvt = arg->pvt;
+
speex_decoder_destroy(pvt->speex);
speex_bits_destroy(&pvt->bits);
- free(pvt);
- localusecnt--;
}
-static void lintospeex_destroy(struct ast_translator_pvt *pvt)
+static void lintospeex_destroy(struct ast_trans_pvt *arg)
{
+ struct speex_coder_pvt *pvt = arg->pvt;
#ifdef _SPEEX_TYPES_H
if (preproc)
speex_preprocess_state_destroy(pvt->pp);
#endif
speex_encoder_destroy(pvt->speex);
speex_bits_destroy(&pvt->bits);
- free(pvt);
- localusecnt--;
}
-static struct ast_translator speextolin =
- { "speextolin",
- AST_FORMAT_SPEEX, AST_FORMAT_SLINEAR,
- speextolin_new,
- speextolin_framein,
- speextolin_frameout,
- speextolin_destroy,
- speextolin_sample
- };
-
-static struct ast_translator lintospeex =
- { "lintospeex",
- AST_FORMAT_SLINEAR, AST_FORMAT_SPEEX,
- lintospeex_new,
- lintospeex_framein,
- lintospeex_frameout,
- lintospeex_destroy,
- lintospeex_sample
- };
+static struct ast_module_lock me = { .usecnt = -1 };
+
+static struct ast_translator speextolin = {
+ .name = "speextolin",
+ .srcfmt = AST_FORMAT_SPEEX,
+ .dstfmt = AST_FORMAT_SLINEAR,
+ .newpvt = speextolin_new,
+ .framein = speextolin_framein,
+ .destroy = speextolin_destroy,
+ .sample = speextolin_sample,
+ .desc_size = sizeof(struct speex_coder_pvt),
+ .buffer_samples = BUFFER_SAMPLES,
+ .buf_size = BUFFER_SAMPLES * 2,
+ .lockp = &me,
+};
+
+static struct ast_translator lintospeex = {
+ .name = "lintospeex",
+ .srcfmt = AST_FORMAT_SLINEAR,
+ .dstfmt = AST_FORMAT_SPEEX,
+ .newpvt = lintospeex_new,
+ .framein = lintospeex_framein,
+ .frameout = lintospeex_frameout,
+ .destroy = lintospeex_destroy,
+ .sample = lintospeex_sample,
+ .desc_size = sizeof(struct speex_coder_pvt),
+ .buffer_samples = BUFFER_SAMPLES,
+ .buf_size = BUFFER_SAMPLES * 2, /* XXX maybe a lot less ? */
+ .lockp = &me,
+};
static void parse_config(void)
{
- struct ast_config *cfg;
+ struct ast_config *cfg = ast_config_load("codecs.conf");
struct ast_variable *var;
int res;
float res_f;
- if ((cfg = ast_config_load("codecs.conf"))) {
- if ((var = ast_variable_browse(cfg, "speex"))) {
- while (var) {
- if (!strcasecmp(var->name, "quality")) {
- res = abs(atoi(var->value));
- if (res > -1 && res < 11) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting Quality to %d\n",res);
- ast_mutex_lock(&localuser_lock);
- quality = res;
- ast_mutex_unlock(&localuser_lock);
- } else
- ast_log(LOG_ERROR,"Error Quality must be 0-10\n");
- } else if (!strcasecmp(var->name, "complexity")) {
- res = abs(atoi(var->value));
- if (res > -1 && res < 11) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting Complexity to %d\n",res);
- ast_mutex_lock(&localuser_lock);
- complexity = res;
- ast_mutex_unlock(&localuser_lock);
- } else
- ast_log(LOG_ERROR,"Error! Complexity must be 0-10\n");
- } else if (!strcasecmp(var->name, "vbr_quality")) {
- if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0 && res_f <= 10) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting VBR Quality to %f\n",res_f);
- ast_mutex_lock(&localuser_lock);
- vbr_quality = res_f;
- ast_mutex_unlock(&localuser_lock);
- } else
- ast_log(LOG_ERROR,"Error! VBR Quality must be 0-10\n");
- } else if (!strcasecmp(var->name, "abr_quality")) {
- ast_log(LOG_ERROR,"Error! ABR Quality setting obsolete, set ABR to desired bitrate\n");
- } else if (!strcasecmp(var->name, "enhancement")) {
- ast_mutex_lock(&localuser_lock);
- enhancement = ast_true(var->value) ? 1 : 0;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Perceptual Enhancement Mode. [%s]\n",enhancement ? "on" : "off");
- ast_mutex_unlock(&localuser_lock);
- } else if (!strcasecmp(var->name, "vbr")) {
- ast_mutex_lock(&localuser_lock);
- vbr = ast_true(var->value) ? 1 : 0;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: VBR Mode. [%s]\n",vbr ? "on" : "off");
- ast_mutex_unlock(&localuser_lock);
- } else if (!strcasecmp(var->name, "abr")) {
- res = abs(atoi(var->value));
- if (res >= 0) {
- if (option_verbose > 2) {
- if (res > 0)
- ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting ABR target bitrate to %d\n",res);
- else
- ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Disabling ABR\n");
- }
- ast_mutex_lock(&localuser_lock);
- abr = res;
- ast_mutex_unlock(&localuser_lock);
- } else
- ast_log(LOG_ERROR,"Error! ABR target bitrate must be >= 0\n");
- } else if (!strcasecmp(var->name, "vad")) {
- ast_mutex_lock(&localuser_lock);
- vad = ast_true(var->value) ? 1 : 0;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: VAD Mode. [%s]\n",vad ? "on" : "off");
- ast_mutex_unlock(&localuser_lock);
- } else if (!strcasecmp(var->name, "dtx")) {
- ast_mutex_lock(&localuser_lock);
- dtx = ast_true(var->value) ? 1 : 0;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: DTX Mode. [%s]\n",dtx ? "on" : "off");
- ast_mutex_unlock(&localuser_lock);
- } else if (!strcasecmp(var->name, "preprocess")) {
- ast_mutex_lock(&localuser_lock);
- preproc = ast_true(var->value) ? 1 : 0;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessing. [%s]\n",preproc ? "on" : "off");
- ast_mutex_unlock(&localuser_lock);
- } else if (!strcasecmp(var->name, "pp_vad")) {
- ast_mutex_lock(&localuser_lock);
- pp_vad = ast_true(var->value) ? 1 : 0;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor VAD. [%s]\n",pp_vad ? "on" : "off");
- ast_mutex_unlock(&localuser_lock);
- } else if (!strcasecmp(var->name, "pp_agc")) {
- ast_mutex_lock(&localuser_lock);
- pp_agc = ast_true(var->value) ? 1 : 0;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor AGC. [%s]\n",pp_agc ? "on" : "off");
- ast_mutex_unlock(&localuser_lock);
- } else if (!strcasecmp(var->name, "pp_agc_level")) {
- if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting preprocessor AGC Level to %f\n",res_f);
- ast_mutex_lock(&localuser_lock);
- pp_agc_level = res_f;
- ast_mutex_unlock(&localuser_lock);
- } else
- ast_log(LOG_ERROR,"Error! Preprocessor AGC Level must be >= 0\n");
- } else if (!strcasecmp(var->name, "pp_denoise")) {
- ast_mutex_lock(&localuser_lock);
- pp_denoise = ast_true(var->value) ? 1 : 0;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor Denoise. [%s]\n",pp_denoise ? "on" : "off");
- ast_mutex_unlock(&localuser_lock);
- } else if (!strcasecmp(var->name, "pp_dereverb")) {
- ast_mutex_lock(&localuser_lock);
- pp_dereverb = ast_true(var->value) ? 1 : 0;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor Dereverb. [%s]\n",pp_dereverb ? "on" : "off");
- ast_mutex_unlock(&localuser_lock);
- } else if (!strcasecmp(var->name, "pp_dereverb_decay")) {
- if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting preprocessor Dereverb Decay to %f\n",res_f);
- ast_mutex_lock(&localuser_lock);
- pp_dereverb_decay = res_f;
- ast_mutex_unlock(&localuser_lock);
- } else
- ast_log(LOG_ERROR,"Error! Preprocessor Dereverb Decay must be >= 0\n");
- } else if (!strcasecmp(var->name, "pp_dereverb_level")) {
- if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting preprocessor Dereverb Level to %f\n",res_f);
- ast_mutex_lock(&localuser_lock);
- pp_dereverb_level = res_f;
- ast_mutex_unlock(&localuser_lock);
- } else
- ast_log(LOG_ERROR,"Error! Preprocessor Dereverb Level must be >= 0\n");
+ if (cfg == NULL)
+ return;
+
+ for (var = ast_variable_browse(cfg, "speex"); var; var = var->next) {
+ if (!strcasecmp(var->name, "quality")) {
+ res = abs(atoi(var->value));
+ if (res > -1 && res < 11) {
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting Quality to %d\n",res);
+ quality = res;
+ } else
+ ast_log(LOG_ERROR,"Error Quality must be 0-10\n");
+ } else if (!strcasecmp(var->name, "complexity")) {
+ res = abs(atoi(var->value));
+ if (res > -1 && res < 11) {
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting Complexity to %d\n",res);
+ complexity = res;
+ } else
+ ast_log(LOG_ERROR,"Error! Complexity must be 0-10\n");
+ } else if (!strcasecmp(var->name, "vbr_quality")) {
+ if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0 && res_f <= 10) {
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting VBR Quality to %f\n",res_f);
+ vbr_quality = res_f;
+ } else
+ ast_log(LOG_ERROR,"Error! VBR Quality must be 0-10\n");
+ } else if (!strcasecmp(var->name, "abr_quality")) {
+ ast_log(LOG_ERROR,"Error! ABR Quality setting obsolete, set ABR to desired bitrate\n");
+ } else if (!strcasecmp(var->name, "enhancement")) {
+ enhancement = ast_true(var->value) ? 1 : 0;
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Perceptual Enhancement Mode. [%s]\n",enhancement ? "on" : "off");
+ } else if (!strcasecmp(var->name, "vbr")) {
+ vbr = ast_true(var->value) ? 1 : 0;
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: VBR Mode. [%s]\n",vbr ? "on" : "off");
+ } else if (!strcasecmp(var->name, "abr")) {
+ res = abs(atoi(var->value));
+ if (res >= 0) {
+ if (option_verbose > 2) {
+ if (res > 0)
+ ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting ABR target bitrate to %d\n",res);
+ else
+ ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Disabling ABR\n");
}
- var = var->next;
- }
+ abr = res;
+ } else
+ ast_log(LOG_ERROR,"Error! ABR target bitrate must be >= 0\n");
+ } else if (!strcasecmp(var->name, "vad")) {
+ vad = ast_true(var->value) ? 1 : 0;
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: VAD Mode. [%s]\n",vad ? "on" : "off");
+ } else if (!strcasecmp(var->name, "dtx")) {
+ dtx = ast_true(var->value) ? 1 : 0;
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: DTX Mode. [%s]\n",dtx ? "on" : "off");
+ } else if (!strcasecmp(var->name, "preprocess")) {
+ preproc = ast_true(var->value) ? 1 : 0;
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessing. [%s]\n",preproc ? "on" : "off");
+ } else if (!strcasecmp(var->name, "pp_vad")) {
+ pp_vad = ast_true(var->value) ? 1 : 0;
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor VAD. [%s]\n",pp_vad ? "on" : "off");
+ } else if (!strcasecmp(var->name, "pp_agc")) {
+ pp_agc = ast_true(var->value) ? 1 : 0;
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor AGC. [%s]\n",pp_agc ? "on" : "off");
+ } else if (!strcasecmp(var->name, "pp_agc_level")) {
+ if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0) {
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting preprocessor AGC Level to %f\n",res_f);
+ pp_agc_level = res_f;
+ } else
+ ast_log(LOG_ERROR,"Error! Preprocessor AGC Level must be >= 0\n");
+ } else if (!strcasecmp(var->name, "pp_denoise")) {
+ pp_denoise = ast_true(var->value) ? 1 : 0;
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor Denoise. [%s]\n",pp_denoise ? "on" : "off");
+ } else if (!strcasecmp(var->name, "pp_dereverb")) {
+ pp_dereverb = ast_true(var->value) ? 1 : 0;
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor Dereverb. [%s]\n",pp_dereverb ? "on" : "off");
+ } else if (!strcasecmp(var->name, "pp_dereverb_decay")) {
+ if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0) {
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting preprocessor Dereverb Decay to %f\n",res_f);
+ pp_dereverb_decay = res_f;
+ } else
+ ast_log(LOG_ERROR,"Error! Preprocessor Dereverb Decay must be >= 0\n");
+ } else if (!strcasecmp(var->name, "pp_dereverb_level")) {
+ if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0) {
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting preprocessor Dereverb Level to %f\n",res_f);
+ pp_dereverb_level = res_f;
+ } else
+ ast_log(LOG_ERROR,"Error! Preprocessor Dereverb Level must be >= 0\n");
}
- ast_config_destroy(cfg);
}
+ ast_config_destroy(cfg);
}
int reload(void)
{
+ /*
+ * XXX reloading while there are active sessions is
+ * somewhat silly because the old state presumably
+ * wouldn't work anymore...
+ * maybe we shuld do a standard hangup localusers ?
+ */
+ ast_mutex_lock(&me.lock);
parse_config();
+ ast_mutex_lock(&me.lock);
return 0;
}
int unload_module(void)
{
int res;
- ast_mutex_lock(&localuser_lock);
+ ast_mutex_lock(&me.lock);
res = ast_unregister_translator(&lintospeex);
if (!res)
res = ast_unregister_translator(&speextolin);
- if (localusecnt)
+ if (me.usecnt)
res = -1;
- ast_mutex_unlock(&localuser_lock);
+ ast_mutex_unlock(&me.lock);
return res;
}
@@ -596,14 +520,12 @@ int load_module(void)
char *description(void)
{
- return tdesc;
+ return "Speex/PCM16 (signed linear) Codec Translator";
}
int usecount(void)
{
- int res;
- OLD_STANDARD_USECOUNT(res);
- return res;
+ return me.usecnt;
}
char *key()
diff --git a/codecs/codec_ulaw.c b/codecs/codec_ulaw.c
index 4f38a024e..ff42128e7 100644
--- a/codecs/codec_ulaw.c
+++ b/codecs/codec_ulaw.c
@@ -44,235 +44,43 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/ulaw.h"
#include "asterisk/utils.h"
-#define BUFFER_SIZE 8096 /* size for the translation buffers */
-
-AST_MUTEX_DEFINE_STATIC(localuser_lock);
-static int localusecnt = 0;
-
-static char *tdesc = "Mu-law Coder/Decoder";
-
-static int useplc = 0;
+#define BUFFER_SAMPLES 8096 /* size for the translation buffers */
/* Sample frame data */
#include "slin_ulaw_ex.h"
#include "ulaw_slin_ex.h"
-/*!
- * \brief Private workspace for translating signed linear signals to ulaw.
- */
-
-struct ulaw_encoder_pvt
-{
- struct ast_frame f;
- char offset[AST_FRIENDLY_OFFSET]; /*!< Space to build offset */
- unsigned char outbuf[BUFFER_SIZE]; /*!< Encoded ulaw, two nibbles to a word */
- int tail;
-};
-
-/*!
- * \brief Private workspace for translating ulaw signals to signed linear.
- */
-
-struct ulaw_decoder_pvt
+/*! \brief convert and store samples in outbuf */
+static int ulawtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
- struct ast_frame f;
- char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
- short outbuf[BUFFER_SIZE]; /* Decoded signed linear values */
- int tail;
- plc_state_t plc;
-};
-
-/*!
- * \brief ulawToLin_New
- * Create a new instance of ulaw_decoder_pvt.
- *
- * Results:
- * Returns a pointer to the new instance.
- *
- * Side effects:
- * None.
- */
-
-static struct ast_translator_pvt *ulawtolin_new(void)
-{
- struct ulaw_decoder_pvt *tmp;
-
- if ((tmp = ast_calloc(1, sizeof(*tmp)))) {
- tmp->tail = 0;
- plc_init(&tmp->plc);
- localusecnt++;
- ast_update_use_count();
- }
-
- return (struct ast_translator_pvt *)tmp;
-}
-
-/*!
- * \brief LinToulaw_New
- * Create a new instance of ulaw_encoder_pvt.
- *
- * Results:
- * Returns a pointer to the new instance.
- *
- * Side effects:
- * None.
- */
-
-static struct ast_translator_pvt *lintoulaw_new(void)
-{
- struct ulaw_encoder_pvt *tmp;
-
- if ((tmp = ast_calloc(1, sizeof(*tmp)))) {
- localusecnt++;
- ast_update_use_count();
- tmp->tail = 0;
- }
-
- return (struct ast_translator_pvt *)tmp;
-}
-
-/*!
- * \brief ulawToLin_FrameIn
- * Fill an input buffer with packed 4-bit ulaw values if there is room
- * left.
- *
- * Results:
- * Foo
- *
- * Side effects:
- * tmp->tail is the number of packed values in the buffer.
- */
-
-static int ulawtolin_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
-{
- struct ulaw_decoder_pvt *tmp = (struct ulaw_decoder_pvt *)pvt;
- int x;
- unsigned char *b;
-
- if(f->datalen == 0) { /* perform PLC with nominal framesize of 20ms/160 samples */
- if((tmp->tail + 160) * 2 > sizeof(tmp->outbuf)) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
- if(useplc) {
- plc_fillin(&tmp->plc, tmp->outbuf+tmp->tail, 160);
- tmp->tail += 160;
- }
- return 0;
- }
-
- if ((tmp->tail + f->datalen) * 2 > sizeof(tmp->outbuf)) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
-
- /* Reset ssindex and signal to frame's specified values */
- b = f->data;
- for (x=0;x<f->datalen;x++)
- tmp->outbuf[tmp->tail + x] = AST_MULAW(b[x]);
+ int i;
+ unsigned char *src = f->data;
+ int16_t *dst = (int16_t *)pvt->outbuf;
- if(useplc)
- plc_rx(&tmp->plc, tmp->outbuf+tmp->tail, f->datalen);
+ /* convert and copy in outbuf */
+ for (i=0; i<f->samples; i++)
+ dst[pvt->samples + i] = AST_MULAW(src[i]);
- tmp->tail += f->datalen;
+ pvt->samples += f->samples;
+ pvt->datalen += 2 * f->samples;
return 0;
}
-/*!
- * \brief ulawToLin_FrameOut
- * Convert 4-bit ulaw encoded signals to 16-bit signed linear.
- *
- * Results:
- * Converted signals are placed in tmp->f.data, tmp->f.datalen
- * and tmp->f.samples are calculated.
- *
- * Side effects:
- * None.
- */
-
-static struct ast_frame *ulawtolin_frameout(struct ast_translator_pvt *pvt)
+/*! \brief convert and store samples in outbuf */
+static int lintoulaw_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
- struct ulaw_decoder_pvt *tmp = (struct ulaw_decoder_pvt *)pvt;
-
- if (!tmp->tail)
- return NULL;
+ int i;
+ int16_t *src = f->data;
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_SLINEAR;
- tmp->f.datalen = tmp->tail * 2;
- tmp->f.samples = tmp->tail;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->outbuf;
- tmp->tail = 0;
- return &tmp->f;
-}
-
-/*!
- * \brief LinToulaw_FrameIn
- * Fill an input buffer with 16-bit signed linear PCM values.
- *
- * Results:
- * None.
- *
- * Side effects:
- * tmp->tail is number of signal values in the input buffer.
- */
-
-static int lintoulaw_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
-{
- struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *)pvt;
- int x;
- short *s;
- if (tmp->tail + f->datalen / 2 >= sizeof(tmp->outbuf)) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
- s = f->data;
- for (x=0;x<f->datalen/2;x++)
- tmp->outbuf[x+tmp->tail] = AST_LIN2MU(s[x]);
- tmp->tail += f->datalen/2;
+ for (i=0 ; i < f->samples; i++)
+ pvt->outbuf[pvt->samples + i] = AST_LIN2MU(src[i]);
+ pvt->samples += f->samples;
+ pvt->datalen += f->samples; /* 1 byte/sample */
return 0;
}
-/*!
- * \brief LinToulaw_FrameOut
- * Convert a buffer of raw 16-bit signed linear PCM to a buffer
- * of 4-bit ulaw packed two to a byte (Big Endian).
- *
- * Results:
- * Foo
- *
- * Side effects:
- * Leftover inbuf data gets packed, tail gets updated.
- */
-
-static struct ast_frame *lintoulaw_frameout(struct ast_translator_pvt *pvt)
-{
- struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *)pvt;
-
- if (tmp->tail) {
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_ULAW;
- tmp->f.samples = tmp->tail;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->outbuf;
- tmp->f.datalen = tmp->tail;
- tmp->tail = 0;
- return &tmp->f;
- } else
- return NULL;
-}
-
-
-/*!
- * \brief ulawToLin_Sample
- */
-
+/*! * \brief ulawToLin_Sample */
static struct ast_frame *ulawtolin_sample(void)
{
static struct ast_frame f;
@@ -307,37 +115,21 @@ static struct ast_frame *lintoulaw_sample(void)
}
/*!
- * \brief ulaw_Destroy
- * Destroys a private workspace.
- *
- * Results:
- * It's gone!
- *
- * Side effects:
- * None.
- */
-
-static void ulaw_destroy(struct ast_translator_pvt *pvt)
-{
- free(pvt);
- localusecnt--;
- ast_update_use_count();
-}
-
-/*!
* \brief The complete translator for ulawToLin.
*/
+static struct ast_module_lock me = { .usecnt = -1 };
+
static struct ast_translator ulawtolin = {
- "ulawtolin",
- AST_FORMAT_ULAW,
- AST_FORMAT_SLINEAR,
- ulawtolin_new,
- ulawtolin_framein,
- ulawtolin_frameout,
- ulaw_destroy,
- /* NULL */
- ulawtolin_sample
+ .name = "ulawtolin",
+ .srcfmt = AST_FORMAT_ULAW,
+ .dstfmt = AST_FORMAT_SLINEAR,
+ .framein = ulawtolin_framein,
+ .sample = ulawtolin_sample,
+ .lockp = &me,
+ .buffer_samples = BUFFER_SAMPLES,
+ .buf_size = BUFFER_SAMPLES * 2,
+ .plc_samples = 160,
};
/*!
@@ -345,34 +137,30 @@ static struct ast_translator ulawtolin = {
*/
static struct ast_translator lintoulaw = {
- "lintoulaw",
- AST_FORMAT_SLINEAR,
- AST_FORMAT_ULAW,
- lintoulaw_new,
- lintoulaw_framein,
- lintoulaw_frameout,
- ulaw_destroy,
- /* NULL */
- lintoulaw_sample
+ .name = "lintoulaw",
+ .srcfmt = AST_FORMAT_SLINEAR,
+ .dstfmt = AST_FORMAT_ULAW,
+ .framein = lintoulaw_framein,
+ .sample = lintoulaw_sample,
+ .lockp = &me,
+ .buf_size = BUFFER_SAMPLES,
+ .buffer_samples = BUFFER_SAMPLES,
};
static void parse_config(void)
{
- struct ast_config *cfg;
struct ast_variable *var;
- if ((cfg = ast_config_load("codecs.conf"))) {
- if ((var = ast_variable_browse(cfg, "plc"))) {
- while (var) {
- if (!strcasecmp(var->name, "genericplc")) {
- useplc = ast_true(var->value) ? 1 : 0;
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "codec_ulaw: %susing generic PLC\n", useplc ? "" : "not ");
- }
- var = var->next;
- }
+ struct ast_config *cfg = ast_config_load("codecs.conf");
+ if (cfg == NULL)
+ return;
+ for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
+ if (!strcasecmp(var->name, "genericplc")) {
+ ulawtolin.useplc = ast_true(var->value) ? 1 : 0;
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "codec_ulaw: %susing generic PLC\n", ulawtolin.useplc ? "" : "not ");
}
- ast_config_destroy(cfg);
}
+ ast_config_destroy(cfg);
}
int reload(void)
@@ -384,13 +172,13 @@ int reload(void)
int unload_module(void)
{
int res;
- ast_mutex_lock(&localuser_lock);
+ ast_mutex_lock(&me.lock);
res = ast_unregister_translator(&lintoulaw);
if (!res)
res = ast_unregister_translator(&ulawtolin);
- if (localusecnt)
+ if (me.usecnt)
res = -1;
- ast_mutex_unlock(&localuser_lock);
+ ast_mutex_unlock(&me.lock);
return res;
}
@@ -412,14 +200,12 @@ int load_module(void)
char *description(void)
{
- return tdesc;
+ return "Mu-law Coder/Decoder";
}
int usecount(void)
{
- int res;
- OLD_STANDARD_USECOUNT(res);
- return res;
+ return me.usecnt;
}
char *key()