Wed Oct 28 15:47:53 2009

Asterisk developer's documentation


codec_alaw.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_alaw.c - translate between signed linear and alaw
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/alaw.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 = "A-law Coder/Decoder";
00052 
00053 static int useplc = 0;
00054 
00055 /* Sample frame data (Mu data is okay) */
00056 
00057 #include "slin_ulaw_ex.h"
00058 #include "ulaw_slin_ex.h"
00059 
00060 /*!
00061  * \brief Private workspace for translating signed linear signals to alaw.
00062  */
00063 struct alaw_encoder_pvt
00064 {
00065   struct ast_frame f;
00066   char offset[AST_FRIENDLY_OFFSET];   /*!< Space to build offset */
00067   unsigned char outbuf[BUFFER_SIZE];  /*!< Encoded alaw, two nibbles to a word */
00068   int tail;
00069 };
00070 
00071 /*!
00072  * \brief Private workspace for translating alaw signals to signed linear.
00073  */
00074 struct alaw_decoder_pvt
00075 {
00076   struct ast_frame f;
00077   char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
00078   short outbuf[BUFFER_SIZE];  /* Decoded signed linear values */
00079   int tail;
00080   plc_state_t plc;
00081 };
00082 
00083 /*!
00084  * \brief alawToLin_New
00085  *  Create a new instance of alaw_decoder_pvt.
00086  *
00087  * Results:
00088  *  Returns a pointer to the new instance.
00089  *
00090  * Side effects:
00091  *  None.
00092  */
00093 
00094 static struct ast_translator_pvt * alawtolin_new (void)
00095 {
00096   struct alaw_decoder_pvt *tmp;
00097   tmp = malloc (sizeof (struct alaw_decoder_pvt));
00098   if (tmp)
00099     {
00100      memset(tmp, 0, sizeof(*tmp));
00101       tmp->tail = 0;
00102       plc_init(&tmp->plc);
00103       localusecnt++;
00104       ast_update_use_count ();
00105     }
00106   return (struct ast_translator_pvt *) tmp;
00107 }
00108 
00109 /*!
00110  * \brief LinToalaw_New
00111  *  Create a new instance of alaw_encoder_pvt.
00112  *
00113  * Results:
00114  *  Returns a pointer to the new instance.
00115  *
00116  * Side effects:
00117  *  None.
00118  */
00119 
00120 static struct ast_translator_pvt * lintoalaw_new (void)
00121 {
00122   struct alaw_encoder_pvt *tmp;
00123   tmp = malloc (sizeof (struct alaw_encoder_pvt));
00124   if (tmp)
00125     {
00126      memset(tmp, 0, sizeof(*tmp));
00127       localusecnt++;
00128       ast_update_use_count ();
00129       tmp->tail = 0;
00130     }
00131   return (struct ast_translator_pvt *) tmp;
00132 }
00133 
00134 /*!
00135  * \brief alawToLin_FrameIn
00136  *  Fill an input buffer with packed 4-bit alaw values if there is room
00137  *  left.
00138  *
00139  * Results:
00140  *  Foo
00141  *
00142  * Side effects:
00143  *  tmp->tail is the number of packed values in the buffer.
00144  */
00145 
00146 static int
00147 alawtolin_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
00148 {
00149   struct alaw_decoder_pvt *tmp = (struct alaw_decoder_pvt *) pvt;
00150   int x;
00151   unsigned char *b;
00152 
00153   if(f->datalen == 0) { /* perform PLC with nominal framesize of 20ms/160 samples */
00154         if((tmp->tail + 160)  * 2 > sizeof(tmp->outbuf)) {
00155             ast_log(LOG_WARNING, "Out of buffer space\n");
00156             return -1;
00157         }
00158         if(useplc) {
00159        plc_fillin(&tmp->plc, tmp->outbuf+tmp->tail, 160);
00160        tmp->tail += 160;
00161    }
00162         return 0;
00163   }
00164 
00165   if ((tmp->tail + f->datalen) * 2 > sizeof(tmp->outbuf)) {
00166    ast_log(LOG_WARNING, "Out of buffer space\n");
00167    return -1;
00168   }
00169 
00170   /* Reset ssindex and signal to frame's specified values */
00171   b = f->data;
00172   for (x=0;x<f->datalen;x++)
00173    tmp->outbuf[tmp->tail + x] = AST_ALAW(b[x]);
00174 
00175   if(useplc) plc_rx(&tmp->plc, tmp->outbuf+tmp->tail, f->datalen);
00176 
00177   tmp->tail += f->datalen;
00178   return 0;
00179 }
00180 
00181 /*!
00182  * \brief alawToLin_FrameOut
00183  *  Convert 4-bit alaw encoded signals to 16-bit signed linear.
00184  *
00185  * Results:
00186  *  Converted signals are placed in tmp->f.data, tmp->f.datalen
00187  *  and tmp->f.samples are calculated.
00188  *
00189  * Side effects:
00190  *  None.
00191  */
00192 
00193 static struct ast_frame * alawtolin_frameout (struct ast_translator_pvt *pvt)
00194 {
00195   struct alaw_decoder_pvt *tmp = (struct alaw_decoder_pvt *) pvt;
00196 
00197   if (!tmp->tail)
00198     return NULL;
00199 
00200   tmp->f.frametype = AST_FRAME_VOICE;
00201   tmp->f.subclass = AST_FORMAT_SLINEAR;
00202   tmp->f.datalen = tmp->tail *2;
00203   tmp->f.samples = tmp->tail;
00204   tmp->f.mallocd = 0;
00205   tmp->f.offset = AST_FRIENDLY_OFFSET;
00206   tmp->f.src = __PRETTY_FUNCTION__;
00207   tmp->f.data = tmp->outbuf;
00208   tmp->tail = 0;
00209   return &tmp->f;
00210 }
00211 
00212 /*!
00213  * \brief LinToalaw_FrameIn
00214  *  Fill an input buffer with 16-bit signed linear PCM values.
00215  *
00216  * Results:
00217  *  None.
00218  *
00219  * Side effects:
00220  *  tmp->tail is number of signal values in the input buffer.
00221  */
00222 
00223 static int lintoalaw_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
00224 {
00225   struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *) pvt;
00226   int x;
00227   short *s;
00228   if (tmp->tail + f->datalen/2 >= sizeof(tmp->outbuf))
00229     {
00230       ast_log (LOG_WARNING, "Out of buffer space\n");
00231       return -1;
00232     }
00233   s = f->data;
00234   for (x=0;x<f->datalen/2;x++) 
00235    tmp->outbuf[x+tmp->tail] = AST_LIN2A(s[x]);
00236   tmp->tail += f->datalen/2;
00237   return 0;
00238 }
00239 
00240 /*!
00241  * \brief LinToalaw_FrameOut
00242  *  Convert a buffer of raw 16-bit signed linear PCM to a buffer
00243  *  of 4-bit alaw packed two to a byte (Big Endian).
00244  *
00245  * Results:
00246  *  Foo
00247  *
00248  * Side effects:
00249  *  Leftover inbuf data gets packed, tail gets updated.
00250  */
00251 
00252 static struct ast_frame * lintoalaw_frameout (struct ast_translator_pvt *pvt)
00253 {
00254   struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *) pvt;
00255   
00256   if (tmp->tail) {
00257      tmp->f.frametype = AST_FRAME_VOICE;
00258      tmp->f.subclass = AST_FORMAT_ALAW;
00259      tmp->f.samples = tmp->tail;
00260      tmp->f.mallocd = 0;
00261      tmp->f.offset = AST_FRIENDLY_OFFSET;
00262      tmp->f.src = __PRETTY_FUNCTION__;
00263      tmp->f.data = tmp->outbuf;
00264      tmp->f.datalen = tmp->tail;
00265      tmp->tail = 0;
00266      return &tmp->f;
00267    } else return NULL;
00268 }
00269 
00270 
00271 /*!
00272  * \brief alawToLin_Sample
00273  */
00274 
00275 static struct ast_frame * alawtolin_sample (void)
00276 {
00277   static struct ast_frame f;
00278   f.frametype = AST_FRAME_VOICE;
00279   f.subclass = AST_FORMAT_ALAW;
00280   f.datalen = sizeof (ulaw_slin_ex);
00281   f.samples = sizeof(ulaw_slin_ex);
00282   f.mallocd = 0;
00283   f.offset = 0;
00284   f.src = __PRETTY_FUNCTION__;
00285   f.data = ulaw_slin_ex;
00286   return &f;
00287 }
00288 
00289 /*!
00290  * \brief LinToalaw_Sample
00291  */
00292 
00293 static struct ast_frame * lintoalaw_sample (void)
00294 {
00295   static struct ast_frame f;
00296   f.frametype = AST_FRAME_VOICE;
00297   f.subclass = AST_FORMAT_SLINEAR;
00298   f.datalen = sizeof (slin_ulaw_ex);
00299   /* Assume 8000 Hz */
00300   f.samples = sizeof (slin_ulaw_ex) / 2;
00301   f.mallocd = 0;
00302   f.offset = 0;
00303   f.src = __PRETTY_FUNCTION__;
00304   f.data = slin_ulaw_ex;
00305   return &f;
00306 }
00307 
00308 /*!
00309  * \brief alaw_Destroy
00310  *  Destroys a private workspace.
00311  *
00312  * Results:
00313  *  It's gone!
00314  *
00315  * Side effects:
00316  *  None.
00317  */
00318 
00319 static void alaw_destroy (struct ast_translator_pvt *pvt)
00320 {
00321   free (pvt);
00322   localusecnt--;
00323   ast_update_use_count ();
00324 }
00325 
00326 /*!
00327  * \brief The complete translator for alawToLin.
00328  */
00329 
00330 static struct ast_translator alawtolin = {
00331   "alawtolin",
00332   AST_FORMAT_ALAW,
00333   AST_FORMAT_SLINEAR,
00334   alawtolin_new,
00335   alawtolin_framein,
00336   alawtolin_frameout,
00337   alaw_destroy,
00338   /* NULL */
00339   alawtolin_sample
00340 };
00341 
00342 /*!
00343  * \brief The complete translator for LinToalaw.
00344  */
00345 
00346 static struct ast_translator lintoalaw = {
00347   "lintoalaw",
00348   AST_FORMAT_SLINEAR,
00349   AST_FORMAT_ALAW,
00350   lintoalaw_new,
00351   lintoalaw_framein,
00352   lintoalaw_frameout,
00353   alaw_destroy,
00354   /* NULL */
00355   lintoalaw_sample
00356 };
00357 
00358 static void parse_config(void)
00359 {
00360   struct ast_config *cfg;
00361   struct ast_variable *var;
00362 
00363   if ((cfg = ast_config_load("codecs.conf"))) {
00364     if ((var = ast_variable_browse(cfg, "plc"))) {
00365       while (var) {
00366        if (!strcasecmp(var->name, "genericplc")) {
00367          useplc = ast_true(var->value) ? 1 : 0;
00368          if (option_verbose > 2)
00369            ast_verbose(VERBOSE_PREFIX_3 "codec_alaw: %susing generic PLC\n", useplc ? "" : "not ");
00370        }
00371        var = var->next;
00372       }
00373     }
00374     ast_config_destroy(cfg);
00375   }
00376 }
00377 
00378 int reload(void)
00379 {
00380   parse_config();
00381   return 0;
00382 }
00383 
00384 int unload_module (void)
00385 {
00386   int res;
00387   ast_mutex_lock (&localuser_lock);
00388   res = ast_unregister_translator (&lintoalaw);
00389   if (!res)
00390     res = ast_unregister_translator (&alawtolin);
00391   if (localusecnt)
00392     res = -1;
00393   ast_mutex_unlock (&localuser_lock);
00394   return res;
00395 }
00396 
00397 int load_module (void)
00398 {
00399   int res;
00400   parse_config();
00401   res = ast_register_translator (&alawtolin);
00402   if (!res)
00403     res = ast_register_translator (&lintoalaw);
00404   else
00405     ast_unregister_translator (&alawtolin);
00406   return res;
00407 }
00408 
00409 /*
00410  * Return a description of this module.
00411  */
00412 
00413 char * description (void)
00414 {
00415   return tdesc;
00416 }
00417 
00418 int usecount (void)
00419 {
00420   int res;
00421   STANDARD_USECOUNT (res);
00422   return res;
00423 }
00424 
00425 char * key ()
00426 {
00427   return ASTERISK_GPL_KEY;
00428 }

Generated on Wed Oct 28 15:47:53 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6