From ffb7afe7b594c4864f41b975b00536123623311c Mon Sep 17 00:00:00 2001 From: Mark Spencer Date: Sat, 7 Apr 2001 01:45:34 +0000 Subject: Version 0.1.8 from FTP git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@267 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- codecs/codec_ulaw.c | 378 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 378 insertions(+) create mode 100755 codecs/codec_ulaw.c (limited to 'codecs') diff --git a/codecs/codec_ulaw.c b/codecs/codec_ulaw.c new file mode 100755 index 000000000..cbe174946 --- /dev/null +++ b/codecs/codec_ulaw.c @@ -0,0 +1,378 @@ +/* codec_ulaw.c - translate between signed linear and ulaw + * + * Asterisk -- A telephony toolkit for Linux. + * + * Copyright (c) 2001 Linux Support Services, Inc. All rights reserved. + * + * Mark Spencer +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 = "Mu-law Coder/Decoder"; + +/* Sample frame data */ + +#include "slin_ulaw_ex.h" +#include "ulaw_slin_ex.h" + +/* + * 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; +}; + +/* + * Private workspace for translating ulaw signals to signed linear. + */ + +struct ulaw_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; +}; + +/* + * 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 () +{ + struct ulaw_decoder_pvt *tmp; + tmp = malloc (sizeof (struct ulaw_decoder_pvt)); + if (tmp) + { + memset(tmp, 0, sizeof(*tmp)); + tmp->tail = 0; + localusecnt++; + ast_update_use_count (); + } + return (struct ast_translator_pvt *) tmp; +} + +/* + * 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 () +{ + struct ulaw_encoder_pvt *tmp; + tmp = malloc (sizeof (struct ulaw_encoder_pvt)); + if (tmp) + { + memset(tmp, 0, sizeof(*tmp)); + localusecnt++; + ast_update_use_count (); + tmp->tail = 0; + } + return (struct ast_translator_pvt *) tmp; +} + +/* + * 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 ((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;xdatalen;x++) + tmp->outbuf[tmp->tail + x] = ast_mulaw[b[x]]; + + tmp->tail += f->datalen; + return 0; +} + +/* + * 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.timelen are calculated. + * + * Side effects: + * None. + */ + +static struct ast_frame * +ulawtolin_frameout (struct ast_translator_pvt *pvt) +{ + struct ulaw_decoder_pvt *tmp = (struct ulaw_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; +} + +/* + * 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;xdatalen/2;x++) + tmp->outbuf[x+tmp->tail] = ast_lin2mu[s[x]+32768]; + tmp->tail += f->datalen/2; + return 0; +} + +/* + * 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.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; +} + + +/* + * ulawToLin_Sample + */ + +static struct ast_frame * +ulawtolin_sample () +{ + static struct ast_frame f; + f.frametype = AST_FRAME_VOICE; + f.subclass = AST_FORMAT_ULAW; + 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; +} + +/* + * LinToulaw_Sample + */ + +static struct ast_frame * +lintoulaw_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; +} + +/* + * 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 (); +} + +/* + * The complete translator for ulawToLin. + */ + +static struct ast_translator ulawtolin = { + "ulawtolin", + AST_FORMAT_ULAW, + AST_FORMAT_SLINEAR, + ulawtolin_new, + ulawtolin_framein, + ulawtolin_frameout, + ulaw_destroy, + /* NULL */ + ulawtolin_sample +}; + +/* + * The complete translator for LinToulaw. + */ + +static struct ast_translator lintoulaw = { + "lintoulaw", + AST_FORMAT_SLINEAR, + AST_FORMAT_ULAW, + lintoulaw_new, + lintoulaw_framein, + lintoulaw_frameout, + ulaw_destroy, + /* NULL */ + lintoulaw_sample +}; + +int +unload_module (void) +{ + int res; + ast_pthread_mutex_lock (&localuser_lock); + res = ast_unregister_translator (&lintoulaw); + if (!res) + res = ast_unregister_translator (&ulawtolin); + if (localusecnt) + res = -1; + ast_pthread_mutex_unlock (&localuser_lock); + return res; +} + +int +load_module (void) +{ + int res; + res = ast_register_translator (&ulawtolin); + if (!res) + res = ast_register_translator (&lintoulaw); + else + ast_unregister_translator (&ulawtolin); + 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; +} -- cgit v1.2.3