diff options
author | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2001-12-09 00:41:43 +0000 |
---|---|---|
committer | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2001-12-09 00:41:43 +0000 |
commit | 73f433504205e9996ef28ea925881851caa392a3 (patch) | |
tree | e900c1cb311ee485c9707a595d48283480f82847 /codecs/codec_alaw.c | |
parent | 20550ee5133b6ddb2f233e78f8fa9bb9cb0b6de5 (diff) |
Version 0.1.10 from FTP
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@392 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'codecs/codec_alaw.c')
-rwxr-xr-x | codecs/codec_alaw.c | 378 |
1 files changed, 378 insertions, 0 deletions
diff --git a/codecs/codec_alaw.c b/codecs/codec_alaw.c new file mode 100755 index 000000000..9089fccbe --- /dev/null +++ b/codecs/codec_alaw.c @@ -0,0 +1,378 @@ +/* codec_alaw.c - translate between signed linear and alaw + * + * Asterisk -- A telephony toolkit for Linux. + * + * Copyright (c) 2001 Linux Support Services, Inc. All rights reserved. + * + * Mark Spencer <markster@linux-support.net + * + * This program is free software, distributed under the terms of + * the GNU General Public License + */ + +#include <asterisk/logger.h> +#include <asterisk/module.h> +#include <asterisk/translate.h> +#include <asterisk/channel.h> +#include <asterisk/alaw.h> +#include <fcntl.h> +#include <netinet/in.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define BUFFER_SIZE 8096 /* size for the translation buffers */ + +static pthread_mutex_t localuser_lock = PTHREAD_MUTEX_INITIALIZER; +static int localusecnt = 0; + +static char *tdesc = "A-law Coder/Decoder"; + +/* Sample frame data (Mu data is okay) */ + +#include "slin_ulaw_ex.h" +#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 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; +}; + +/* + * 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 () +{ + struct alaw_decoder_pvt *tmp; + tmp = malloc (sizeof (struct alaw_decoder_pvt)); + if (tmp) + { + memset(tmp, 0, sizeof(*tmp)); + tmp->tail = 0; + localusecnt++; + ast_update_use_count (); + } + return (struct ast_translator_pvt *) tmp; +} + +/* + * 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 () +{ + struct alaw_encoder_pvt *tmp; + tmp = malloc (sizeof (struct alaw_encoder_pvt)); + if (tmp) + { + memset(tmp, 0, sizeof(*tmp)); + localusecnt++; + ast_update_use_count (); + tmp->tail = 0; + } + return (struct ast_translator_pvt *) tmp; +} + +/* + * 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) +{ + struct alaw_decoder_pvt *tmp = (struct alaw_decoder_pvt *) pvt; + int x; + unsigned char *b; + + 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]); + + tmp->tail += f->datalen; + return 0; +} + +/* + * 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.timelen 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.timelen = tmp->tail / 8; + 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; +} + +/* + * 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) +{ + 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; +} + +/* + * 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.timelen = tmp->tail / 8; + 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; +} + + +/* + * alawToLin_Sample + */ + +static struct ast_frame * +alawtolin_sample () +{ + static struct ast_frame f; + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_ALAW; + f.datalen = sizeof (ulaw_slin_ex); + f.timelen = sizeof(ulaw_slin_ex) / 8; + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = ulaw_slin_ex; + return &f; +} + +/* + * LinToalaw_Sample + */ + +static struct ast_frame * +lintoalaw_sample () +{ + 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.timelen = sizeof (slin_ulaw_ex) / 16; + f.mallocd = 0; + f.offset = 0; + f.src = __PRETTY_FUNCTION__; + f.data = slin_ulaw_ex; + 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_translator alawtolin = { + "alawtolin", + AST_FORMAT_ALAW, + AST_FORMAT_SLINEAR, + alawtolin_new, + alawtolin_framein, + alawtolin_frameout, + alaw_destroy, + /* NULL */ + alawtolin_sample +}; + +/* + * 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 +}; + +int +unload_module (void) +{ + int res; + ast_pthread_mutex_lock (&localuser_lock); + res = ast_unregister_translator (&lintoalaw); + if (!res) + res = ast_unregister_translator (&alawtolin); + if (localusecnt) + res = -1; + ast_pthread_mutex_unlock (&localuser_lock); + return res; +} + +int +load_module (void) +{ + int res; + res = ast_register_translator (&alawtolin); + if (!res) + res = ast_register_translator (&lintoalaw); + else + ast_unregister_translator (&alawtolin); + return res; +} + +/* + * Return a description of this module. + */ + +char * +description (void) +{ + return tdesc; +} + +int +usecount (void) +{ + int res; + STANDARD_USECOUNT (res); + return res; +} + +char * +key () +{ + return ASTERISK_GPL_KEY; +} |