Sat Mar 24 22:55:16 2007

Asterisk developer's documentation


codec_ulaw.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief codec_ulaw.c - translate between signed linear and ulaw
00022  * 
00023  * \ingroup codecs
00024  */
00025 
00026 #include <fcntl.h>
00027 #include <netinet/in.h>
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <unistd.h>
00032 
00033 #include "asterisk.h"
00034 
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
00036 
00037 #include "asterisk/lock.h"
00038 #include "asterisk/logger.h"
00039 #include "asterisk/module.h"
00040 #include "asterisk/config.h"
00041 #include "asterisk/options.h"
00042 #include "asterisk/translate.h"
00043 #include "asterisk/channel.h"
00044 #include "asterisk/ulaw.h"
00045 
00046 #define BUFFER_SIZE   8096 /* size for the translation buffers */
00047 
00048 AST_MUTEX_DEFINE_STATIC(localuser_lock);
00049 static int localusecnt = 0;
00050 
00051 static char *tdesc = "Mu-law Coder/Decoder";
00052 
00053 static int useplc = 0;
00054 
00055 /* Sample frame data */
00056 
00057 #include "slin_ulaw_ex.h"
00058 #include "ulaw_slin_ex.h"
00059 
00060 /*
00061  * Private workspace for translating signed linear signals to ulaw.
00062  */
00063 
00064 struct ulaw_encoder_pvt
00065 {
00066   struct ast_frame f;
00067   char offset[AST_FRIENDLY_OFFSET];   /* Space to build offset */
00068   unsigned char outbuf[BUFFER_SIZE];  /* Encoded ulaw, two nibbles to a word */
00069   int tail;
00070 };
00071 
00072 /*
00073  * Private workspace for translating ulaw signals to signed linear.
00074  */
00075 
00076 struct ulaw_decoder_pvt
00077 {
00078   struct ast_frame f;
00079   char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
00080   short outbuf[BUFFER_SIZE];  /* Decoded signed linear values */
00081   int tail;
00082   plc_state_t plc;
00083 };
00084 
00085 /*
00086  * ulawToLin_New
00087  *  Create a new instance of ulaw_decoder_pvt.
00088  *
00089  * Results:
00090  *  Returns a pointer to the new instance.
00091  *
00092  * Side effects:
00093  *  None.
00094  */
00095 
00096 static struct ast_translator_pvt *
00097 ulawtolin_new (void)
00098 {
00099   struct ulaw_decoder_pvt *tmp;
00100   tmp = malloc (sizeof (struct ulaw_decoder_pvt));
00101   if (tmp)
00102     {
00103      memset(tmp, 0, sizeof(*tmp));
00104       tmp->tail = 0;
00105       plc_init(&tmp->plc);
00106       localusecnt++;
00107       ast_update_use_count ();
00108     }
00109   return (struct ast_translator_pvt *) tmp;
00110 }
00111 
00112 /*
00113  * LinToulaw_New
00114  *  Create a new instance of ulaw_encoder_pvt.
00115  *
00116  * Results:
00117  *  Returns a pointer to the new instance.
00118  *
00119  * Side effects:
00120  *  None.
00121  */
00122 
00123 static struct ast_translator_pvt *
00124 lintoulaw_new (void)
00125 {
00126   struct ulaw_encoder_pvt *tmp;
00127   tmp = malloc (sizeof (struct ulaw_encoder_pvt));
00128   if (tmp)
00129     {
00130      memset(tmp, 0, sizeof(*tmp));
00131       localusecnt++;
00132       ast_update_use_count ();
00133       tmp->tail = 0;
00134     }
00135   return (struct ast_translator_pvt *) tmp;
00136 }
00137 
00138 /*
00139  * ulawToLin_FrameIn
00140  *  Fill an input buffer with packed 4-bit ulaw values if there is room
00141  *  left.
00142  *
00143  * Results:
00144  *  Foo
00145  *
00146  * Side effects:
00147  *  tmp->tail is the number of packed values in the buffer.
00148  */
00149 
00150 static int
00151 ulawtolin_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
00152 {
00153   struct ulaw_decoder_pvt *tmp = (struct ulaw_decoder_pvt *) pvt;
00154   int x;
00155   unsigned char *b;
00156 
00157   if(f->datalen == 0) { /* perform PLC with nominal framesize of 20ms/160 samples */
00158    if((tmp->tail + 160)  * 2 > sizeof(tmp->outbuf)) {
00159        ast_log(LOG_WARNING, "Out of buffer space\n");
00160        return -1;
00161    }
00162    if(useplc) {
00163        plc_fillin(&tmp->plc, tmp->outbuf+tmp->tail, 160);
00164        tmp->tail += 160;
00165    }
00166    return 0;
00167   }
00168 
00169   if ((tmp->tail + f->datalen) * 2 > sizeof(tmp->outbuf)) {
00170    ast_log(LOG_WARNING, "Out of buffer space\n");
00171    return -1;
00172   }
00173 
00174   /* Reset ssindex and signal to frame's specified values */
00175   b = f->data;
00176   for (x=0;x<f->datalen;x++)
00177    tmp->outbuf[tmp->tail + x] = AST_MULAW(b[x]);
00178 
00179   if(useplc) plc_rx(&tmp->plc, tmp->outbuf+tmp->tail, f->datalen);
00180 
00181   tmp->tail += f->datalen;
00182   return 0;
00183 }
00184 
00185 /*
00186  * ulawToLin_FrameOut
00187  *  Convert 4-bit ulaw encoded signals to 16-bit signed linear.
00188  *
00189  * Results:
00190  *  Converted signals are placed in tmp->f.data, tmp->f.datalen
00191  *  and tmp->f.samples are calculated.
00192  *
00193  * Side effects:
00194  *  None.
00195  */
00196 
00197 static struct ast_frame *
00198 ulawtolin_frameout (struct ast_translator_pvt *pvt)
00199 {
00200   struct ulaw_decoder_pvt *tmp = (struct ulaw_decoder_pvt *) pvt;
00201 
00202   if (!tmp->tail)
00203     return NULL;
00204 
00205   tmp->f.frametype = AST_FRAME_VOICE;
00206   tmp->f.subclass = AST_FORMAT_SLINEAR;
00207   tmp->f.datalen = tmp->tail *2;
00208   tmp->f.samples = tmp->tail;
00209   tmp->f.mallocd = 0;
00210   tmp->f.offset = AST_FRIENDLY_OFFSET;
00211   tmp->f.src = __PRETTY_FUNCTION__;
00212   tmp->f.data = tmp->outbuf;
00213   tmp->tail = 0;
00214   return &tmp->f;
00215 }
00216 
00217 /*
00218  * LinToulaw_FrameIn
00219  *  Fill an input buffer with 16-bit signed linear PCM values.
00220  *
00221  * Results:
00222  *  None.
00223  *
00224  * Side effects:
00225  *  tmp->tail is number of signal values in the input buffer.
00226  */
00227 
00228 static int
00229 lintoulaw_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
00230 {
00231   struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *) pvt;
00232   int x;
00233   short *s;
00234   if (tmp->tail + f->datalen/2 >= sizeof(tmp->outbuf))
00235     {
00236       ast_log (LOG_WARNING, "Out of buffer space\n");
00237       return -1;
00238     }
00239   s = f->data;
00240   for (x=0;x<f->datalen/2;x++) 
00241    tmp->outbuf[x+tmp->tail] = AST_LIN2MU(s[x]);
00242   tmp->tail += f->datalen/2;
00243   return 0;
00244 }
00245 
00246 /*
00247  * LinToulaw_FrameOut
00248  *  Convert a buffer of raw 16-bit signed linear PCM to a buffer
00249  *  of 4-bit ulaw packed two to a byte (Big Endian).
00250  *
00251  * Results:
00252  *  Foo
00253  *
00254  * Side effects:
00255  *  Leftover inbuf data gets packed, tail gets updated.
00256  */
00257 
00258 static struct ast_frame *
00259 lintoulaw_frameout (struct ast_translator_pvt *pvt)
00260 {
00261   struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *) pvt;
00262   
00263   if (tmp->tail) {
00264      tmp->f.frametype = AST_FRAME_VOICE;
00265      tmp->f.subclass = AST_FORMAT_ULAW;
00266      tmp->f.samples = tmp->tail;
00267      tmp->f.mallocd = 0;
00268      tmp->f.offset = AST_FRIENDLY_OFFSET;
00269      tmp->f.src = __PRETTY_FUNCTION__;
00270      tmp->f.data = tmp->outbuf;
00271      tmp->f.datalen = tmp->tail;
00272      tmp->tail = 0;
00273      return &tmp->f;
00274    } else return NULL;
00275 }
00276 
00277 
00278 /*
00279  * ulawToLin_Sample
00280  */
00281 
00282 static struct ast_frame *
00283 ulawtolin_sample (void)
00284 {
00285   static struct ast_frame f;
00286   f.frametype = AST_FRAME_VOICE;
00287   f.subclass = AST_FORMAT_ULAW;
00288   f.datalen = sizeof (ulaw_slin_ex);
00289   f.samples = sizeof(ulaw_slin_ex);
00290   f.mallocd = 0;
00291   f.offset = 0;
00292   f.src = __PRETTY_FUNCTION__;
00293   f.data = ulaw_slin_ex;
00294   return &f;
00295 }
00296 
00297 /*
00298  * LinToulaw_Sample
00299  */
00300 
00301 static struct ast_frame *
00302 lintoulaw_sample (void)
00303 {
00304   static struct ast_frame f;
00305   f.frametype = AST_FRAME_VOICE;
00306   f.subclass = AST_FORMAT_SLINEAR;
00307   f.datalen = sizeof (slin_ulaw_ex);
00308   /* Assume 8000 Hz */
00309   f.samples = sizeof (slin_ulaw_ex) / 2;
00310   f.mallocd = 0;
00311   f.offset = 0;
00312   f.src = __PRETTY_FUNCTION__;
00313   f.data = slin_ulaw_ex;
00314   return &f;
00315 }
00316 
00317 /*
00318  * ulaw_Destroy
00319  *  Destroys a private workspace.
00320  *
00321  * Results:
00322  *  It's gone!
00323  *
00324  * Side effects:
00325  *  None.
00326  */
00327 
00328 static void
00329 ulaw_destroy (struct ast_translator_pvt *pvt)
00330 {
00331   free (pvt);
00332   localusecnt--;
00333   ast_update_use_count ();
00334 }
00335 
00336 /*
00337  * The complete translator for ulawToLin.
00338  */
00339 
00340 static struct ast_translator ulawtolin = {
00341   "ulawtolin",
00342   AST_FORMAT_ULAW,
00343   AST_FORMAT_SLINEAR,
00344   ulawtolin_new,
00345   ulawtolin_framein,
00346   ulawtolin_frameout,
00347   ulaw_destroy,
00348   /* NULL */
00349   ulawtolin_sample
00350 };
00351 
00352 /*
00353  * The complete translator for LinToulaw.
00354  */
00355 
00356 static struct ast_translator lintoulaw = {
00357   "lintoulaw",
00358   AST_FORMAT_SLINEAR,
00359   AST_FORMAT_ULAW,
00360   lintoulaw_new,
00361   lintoulaw_framein,
00362   lintoulaw_frameout,
00363   ulaw_destroy,
00364   /* NULL */
00365   lintoulaw_sample
00366 };
00367 
00368 static void 
00369 parse_config(void)
00370 {
00371   struct ast_config *cfg;
00372   struct ast_variable *var;
00373   if ((cfg = ast_config_load("codecs.conf"))) {
00374     if ((var = ast_variable_browse(cfg, "plc"))) {
00375       while (var) {
00376    if (!strcasecmp(var->name, "genericplc")) {
00377      useplc = ast_true(var->value) ? 1 : 0;
00378      if (option_verbose > 2)
00379        ast_verbose(VERBOSE_PREFIX_3 "codec_ulaw: %susing generic PLC\n", useplc ? "" : "not ");
00380    }
00381    var = var->next;
00382       }
00383     }
00384     ast_config_destroy(cfg);
00385   }
00386 }
00387 
00388 int 
00389 reload(void)
00390 {
00391   parse_config();
00392   return 0;
00393 }
00394 
00395 
00396 int
00397 unload_module (void)
00398 {
00399   int res;
00400   ast_mutex_lock (&localuser_lock);
00401   res = ast_unregister_translator (&lintoulaw);
00402   if (!res)
00403     res = ast_unregister_translator (&ulawtolin);
00404   if (localusecnt)
00405     res = -1;
00406   ast_mutex_unlock (&localuser_lock);
00407   return res;
00408 }
00409 
00410 int
00411 load_module (void)
00412 {
00413   int res;
00414   parse_config();
00415   res = ast_register_translator (&ulawtolin);
00416   if (!res)
00417     res = ast_register_translator (&lintoulaw);
00418   else
00419     ast_unregister_translator (&ulawtolin);
00420   return res;
00421 }
00422 
00423 /*
00424  * Return a description of this module.
00425  */
00426 
00427 char *
00428 description (void)
00429 {
00430   return tdesc;
00431 }
00432 
00433 int
00434 usecount (void)
00435 {
00436   int res;
00437   STANDARD_USECOUNT (res);
00438   return res;
00439 }
00440 
00441 char *
00442 key ()
00443 {
00444   return ASTERISK_GPL_KEY;
00445 }

Generated on Sat Mar 24 22:55:16 2007 for Asterisk - the Open Source PBX by  doxygen 1.4.7