Wed Oct 28 15:47:53 2009

Asterisk developer's documentation


codec_adpcm.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Based on frompcm.c and topcm.c from the Emiliano MIPL browser/
00005  * interpreter.  See http://www.bsdtelephony.com.mx
00006  *
00007  * Copyright (c) 2001 - 2005 Digium, Inc.
00008  * All rights reserved.
00009  *
00010  * Karl Sackett <krs@linux-support.net>, 2001-03-21
00011  *
00012  * See http://www.asterisk.org for more information about
00013  * the Asterisk project. Please do not directly contact
00014  * any of the maintainers of this project for assistance;
00015  * the project provides a web site, mailing lists and IRC
00016  * channels for your use.
00017  *
00018  * This program is free software, distributed under the terms of
00019  * the GNU General Public License Version 2. See the LICENSE file
00020  * at the top of the source tree.
00021  */
00022 
00023 /*! \file
00024  *
00025  * \brief codec_adpcm.c - translate between signed linear and Dialogic ADPCM
00026  * 
00027  * \ingroup codecs
00028  */
00029 
00030 #include <fcntl.h>
00031 #include <netinet/in.h>
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <unistd.h>
00036 
00037 #include "asterisk.h"
00038 
00039 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
00040 
00041 #include "asterisk/lock.h"
00042 #include "asterisk/logger.h"
00043 #include "asterisk/module.h"
00044 #include "asterisk/config.h"
00045 #include "asterisk/options.h"
00046 #include "asterisk/translate.h"
00047 #include "asterisk/channel.h"
00048 
00049 /* define NOT_BLI to use a faster but not bit-level identical version */
00050 /* #define NOT_BLI */
00051 
00052 #define BUFFER_SIZE   8096 /* size for the translation buffers */
00053 
00054 AST_MUTEX_DEFINE_STATIC(localuser_lock);
00055 static int localusecnt = 0;
00056 
00057 static char *tdesc = "Adaptive Differential PCM Coder/Decoder";
00058 
00059 static int useplc = 0;
00060 
00061 /* Sample frame data */
00062 
00063 #include "slin_adpcm_ex.h"
00064 #include "adpcm_slin_ex.h"
00065 
00066 /*
00067  * Step size index shift table 
00068  */
00069 
00070 static int indsft[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
00071 
00072 /*
00073  * Step size table, where stpsz[i]=floor[16*(11/10)^i]
00074  */
00075 
00076 static int stpsz[49] = {
00077   16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73,
00078   80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279,
00079   307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963,
00080   1060, 1166, 1282, 1411, 1552
00081 };
00082 
00083 /*
00084  * Decoder/Encoder state
00085  *   States for both encoder and decoder are synchronized
00086  */
00087 struct adpcm_state {
00088    int ssindex;
00089    int signal;
00090    int zero_count;
00091    int next_flag;
00092 };
00093 
00094 /*
00095  * Decode(encoded)
00096  *  Decodes the encoded nibble from the adpcm file.
00097  *
00098  * Results:
00099  *  Returns the encoded difference.
00100  *
00101  * Side effects:
00102  *  Sets the index to the step size table for the next encode.
00103  */
00104 
00105 static inline short
00106 decode(int encoded, struct adpcm_state* state)
00107 {
00108    int diff;
00109    int step;
00110    int sign;
00111 
00112    step = stpsz[state->ssindex];
00113 
00114    sign = encoded & 0x08;
00115    encoded &= 0x07;
00116 #ifdef NOT_BLI
00117    diff = (((encoded << 1) + 1) * step) >> 3;
00118 #else /* BLI code */
00119    diff = step >> 3;
00120    if (encoded & 4) diff += step;
00121    if (encoded & 2) diff += step >> 1;
00122    if (encoded & 1) diff += step >> 2;
00123    if ((encoded >> 1) & step & 0x1)
00124       diff++;
00125 #endif
00126    if (sign)
00127       diff = -diff;
00128 
00129    if (state->next_flag & 0x1)
00130       state->signal -= 8;
00131    else if (state->next_flag & 0x2)
00132       state->signal += 8;
00133 
00134    state->signal += diff;
00135 
00136    if (state->signal > 2047)
00137       state->signal = 2047;
00138    else if (state->signal < -2047)
00139       state->signal = -2047;
00140 
00141    state->next_flag = 0;
00142 
00143 #ifdef AUTO_RETURN
00144    if (encoded)
00145       state->zero_count = 0;
00146    else if (++(state->zero_count) == 24)
00147    {
00148       state->zero_count = 0;
00149       if (state->signal > 0)
00150          state->next_flag = 0x1;
00151       else if (state->signal < 0)
00152          state->next_flag = 0x2;
00153    }
00154 #endif
00155 
00156    state->ssindex += indsft[encoded];
00157    if (state->ssindex < 0)
00158       state->ssindex = 0;
00159    else if (state->ssindex > 48)
00160       state->ssindex = 48;
00161 
00162    return state->signal << 4;
00163 }
00164 
00165 /*
00166  * Adpcm
00167  *  Takes a signed linear signal and encodes it as ADPCM
00168  *  For more information see http://support.dialogic.com/appnotes/adpcm.pdf
00169  *
00170  * Results:
00171  *  Foo.
00172  *
00173  * Side effects:
00174  *  signal gets updated with each pass.
00175  */
00176 
00177 static inline int
00178 adpcm(short csig, struct adpcm_state* state)
00179 {
00180    int diff;
00181    int step;
00182    int encoded;
00183 
00184    /* 
00185    * Clip csig if too large or too small
00186    */
00187    csig >>= 4;
00188 
00189    step = stpsz[state->ssindex];
00190    diff = csig - state->signal;
00191 
00192 #ifdef NOT_BLI
00193    if (diff < 0)
00194    {
00195       encoded = (-diff << 2) / step;
00196       if (encoded > 7)
00197          encoded = 7;
00198       encoded |= 0x08;
00199    }
00200    else
00201    {
00202       encoded = (diff << 2) / step;
00203       if (encoded > 7)
00204          encoded = 7;
00205    }
00206 #else /* BLI code */
00207    if (diff < 0)
00208    {
00209       encoded = 8;
00210       diff = -diff;
00211    }
00212    else
00213       encoded = 0;
00214    if (diff >= step)
00215    {
00216       encoded |= 4;
00217       diff -= step;
00218    }
00219    step >>= 1;
00220    if (diff >= step)
00221    {
00222       encoded |= 2;
00223       diff -= step;
00224    }
00225    step >>= 1;
00226    if (diff >= step)
00227       encoded |= 1;
00228 #endif /* NOT_BLI */
00229 
00230    /* feedback to state */
00231    decode(encoded, state);
00232    
00233    return encoded;
00234 }
00235 
00236 /*
00237  * Private workspace for translating signed linear signals to ADPCM.
00238  */
00239 
00240 struct adpcm_encoder_pvt
00241 {
00242   struct ast_frame f;
00243   char offset[AST_FRIENDLY_OFFSET];   /* Space to build offset */
00244   short inbuf[BUFFER_SIZE];           /* Unencoded signed linear values */
00245   unsigned char outbuf[BUFFER_SIZE];  /* Encoded ADPCM, two nibbles to a word */
00246   struct adpcm_state state;
00247   int tail;
00248 };
00249 
00250 /*
00251  * Private workspace for translating ADPCM signals to signed linear.
00252  */
00253 
00254 struct adpcm_decoder_pvt
00255 {
00256   struct ast_frame f;
00257   char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
00258   short outbuf[BUFFER_SIZE];  /* Decoded signed linear values */
00259   struct adpcm_state state;
00260   int tail;
00261   plc_state_t plc;
00262 };
00263 
00264 /*
00265  * AdpcmToLin_New
00266  *  Create a new instance of adpcm_decoder_pvt.
00267  *
00268  * Results:
00269  *  Returns a pointer to the new instance.
00270  *
00271  * Side effects:
00272  *  None.
00273  */
00274 
00275 static struct ast_translator_pvt *
00276 adpcmtolin_new (void)
00277 {
00278   struct adpcm_decoder_pvt *tmp;
00279   tmp = malloc (sizeof (struct adpcm_decoder_pvt));
00280   if (tmp)
00281     {
00282      memset(tmp, 0, sizeof(*tmp));
00283       tmp->tail = 0;
00284       plc_init(&tmp->plc);
00285       localusecnt++;
00286       ast_update_use_count ();
00287     }
00288   return (struct ast_translator_pvt *) tmp;
00289 }
00290 
00291 /*
00292  * LinToAdpcm_New
00293  *  Create a new instance of adpcm_encoder_pvt.
00294  *
00295  * Results:
00296  *  Returns a pointer to the new instance.
00297  *
00298  * Side effects:
00299  *  None.
00300  */
00301 
00302 static struct ast_translator_pvt *
00303 lintoadpcm_new (void)
00304 {
00305   struct adpcm_encoder_pvt *tmp;
00306   tmp = malloc (sizeof (struct adpcm_encoder_pvt));
00307   if (tmp)
00308     {
00309      memset(tmp, 0, sizeof(*tmp));
00310       localusecnt++;
00311       ast_update_use_count ();
00312       tmp->tail = 0;
00313     }
00314   return (struct ast_translator_pvt *) tmp;
00315 }
00316 
00317 /*
00318  * AdpcmToLin_FrameIn
00319  *  Take an input buffer with packed 4-bit ADPCM values and put decoded PCM in outbuf, 
00320  *  if there is room left.
00321  *
00322  * Results:
00323  *  Foo
00324  *
00325  * Side effects:
00326  *  tmp->tail is the number of packed values in the buffer.
00327  */
00328 
00329 static int
00330 adpcmtolin_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
00331 {
00332   struct adpcm_decoder_pvt *tmp = (struct adpcm_decoder_pvt *) pvt;
00333   int x;
00334   unsigned char *b;
00335 
00336   if(f->datalen == 0) { /* perform PLC with nominal framesize of 20ms/160 samples */
00337         if((tmp->tail + 160) > sizeof(tmp->outbuf) / 2) {
00338             ast_log(LOG_WARNING, "Out of buffer space\n");
00339             return -1;
00340         }
00341         if(useplc) {
00342      plc_fillin(&tmp->plc, tmp->outbuf+tmp->tail, 160);
00343      tmp->tail += 160;
00344    }
00345         return 0;
00346   }
00347 
00348   if (f->datalen * 4 + tmp->tail * 2 > sizeof(tmp->outbuf)) {
00349    ast_log(LOG_WARNING, "Out of buffer space\n");
00350    return -1;
00351   }
00352 
00353   b = f->data;
00354 
00355   for (x=0;x<f->datalen;x++) {
00356    tmp->outbuf[tmp->tail++] = decode((b[x] >> 4) & 0xf, &tmp->state);
00357    tmp->outbuf[tmp->tail++] = decode(b[x] & 0x0f, &tmp->state);
00358   }
00359 
00360   if(useplc) plc_rx(&tmp->plc, tmp->outbuf+tmp->tail-f->datalen*2, f->datalen*2);
00361 
00362   return 0;
00363 }
00364 
00365 /*
00366  * AdpcmToLin_FrameOut
00367  *  Convert 4-bit ADPCM encoded signals to 16-bit signed linear.
00368  *
00369  * Results:
00370  *  Converted signals are placed in tmp->f.data, tmp->f.datalen
00371  *  and tmp->f.samples are calculated.
00372  *
00373  * Side effects:
00374  *  None.
00375  */
00376 
00377 static struct ast_frame *
00378 adpcmtolin_frameout (struct ast_translator_pvt *pvt)
00379 {
00380   struct adpcm_decoder_pvt *tmp = (struct adpcm_decoder_pvt *) pvt;
00381 
00382   if (!tmp->tail)
00383     return NULL;
00384 
00385   tmp->f.frametype = AST_FRAME_VOICE;
00386   tmp->f.subclass = AST_FORMAT_SLINEAR;
00387   tmp->f.datalen = tmp->tail *2;
00388   tmp->f.samples = tmp->tail;
00389   tmp->f.mallocd = 0;
00390   tmp->f.offset = AST_FRIENDLY_OFFSET;
00391   tmp->f.src = __PRETTY_FUNCTION__;
00392   tmp->f.data = tmp->outbuf;
00393   tmp->tail = 0;
00394   return &tmp->f;
00395 }
00396 
00397 /*
00398  * LinToAdpcm_FrameIn
00399  *  Fill an input buffer with 16-bit signed linear PCM values.
00400  *
00401  * Results:
00402  *  None.
00403  *
00404  * Side effects:
00405  *  tmp->tail is number of signal values in the input buffer.
00406  */
00407 
00408 static int
00409 lintoadpcm_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
00410 {
00411   struct adpcm_encoder_pvt *tmp = (struct adpcm_encoder_pvt *) pvt;
00412 
00413   if ((tmp->tail + f->datalen / 2) < (sizeof (tmp->inbuf) / 2))
00414     {
00415       memcpy (&tmp->inbuf[tmp->tail], f->data, f->datalen);
00416       tmp->tail += f->datalen / 2;
00417     }
00418   else
00419     {
00420       ast_log (LOG_WARNING, "Out of buffer space\n");
00421       return -1;
00422     }
00423   return 0;
00424 }
00425 
00426 /*
00427  * LinToAdpcm_FrameOut
00428  *  Convert a buffer of raw 16-bit signed linear PCM to a buffer
00429  *  of 4-bit ADPCM packed two to a byte (Big Endian).
00430  *
00431  * Results:
00432  *  Foo
00433  *
00434  * Side effects:
00435  *  Leftover inbuf data gets packed, tail gets updated.
00436  */
00437 
00438 static struct ast_frame *
00439 lintoadpcm_frameout (struct ast_translator_pvt *pvt)
00440 {
00441   struct adpcm_encoder_pvt *tmp = (struct adpcm_encoder_pvt *) pvt;
00442   int i_max, i;
00443   
00444   if (tmp->tail < 2) return NULL;
00445 
00446 
00447   i_max = tmp->tail & ~1; /* atomic size is 2 samples */
00448 
00449   /* What is this, state debugging? should be #ifdef'd then
00450   tmp->outbuf[0] = tmp->ssindex & 0xff;
00451   tmp->outbuf[1] = (tmp->signal >> 8) & 0xff;
00452   tmp->outbuf[2] = (tmp->signal & 0xff);
00453   tmp->outbuf[3] = tmp->zero_count;
00454   tmp->outbuf[4] = tmp->next_flag;
00455   */
00456   for (i = 0; i < i_max; i+=2)
00457   {
00458     tmp->outbuf[i/2] =
00459       (adpcm(tmp->inbuf[i  ], &tmp->state) << 4) |
00460      (adpcm(tmp->inbuf[i+1], &tmp->state)     );
00461   };
00462 
00463 
00464   tmp->f.frametype = AST_FRAME_VOICE;
00465   tmp->f.subclass = AST_FORMAT_ADPCM;
00466   tmp->f.samples = i_max;
00467   tmp->f.mallocd = 0;
00468   tmp->f.offset = AST_FRIENDLY_OFFSET;
00469   tmp->f.src = __PRETTY_FUNCTION__;
00470   tmp->f.data = tmp->outbuf;
00471   tmp->f.datalen = i_max / 2;
00472 
00473   /*
00474    * If there is a signal left over (there should be no more than
00475    * one) move it to the beginning of the input buffer.
00476    */
00477 
00478   if (tmp->tail == i_max)
00479     tmp->tail = 0;
00480   else
00481     {
00482       tmp->inbuf[0] = tmp->inbuf[tmp->tail];
00483       tmp->tail = 1;
00484     }
00485   return &tmp->f;
00486 }
00487 
00488 
00489 /*
00490  * AdpcmToLin_Sample
00491  */
00492 
00493 static struct ast_frame *
00494 adpcmtolin_sample (void)
00495 {
00496   static struct ast_frame f;
00497   f.frametype = AST_FRAME_VOICE;
00498   f.subclass = AST_FORMAT_ADPCM;
00499   f.datalen = sizeof (adpcm_slin_ex);
00500   f.samples = sizeof(adpcm_slin_ex) * 2;
00501   f.mallocd = 0;
00502   f.offset = 0;
00503   f.src = __PRETTY_FUNCTION__;
00504   f.data = adpcm_slin_ex;
00505   return &f;
00506 }
00507 
00508 /*
00509  * LinToAdpcm_Sample
00510  */
00511 
00512 static struct ast_frame *
00513 lintoadpcm_sample (void)
00514 {
00515   static struct ast_frame f;
00516   f.frametype = AST_FRAME_VOICE;
00517   f.subclass = AST_FORMAT_SLINEAR;
00518   f.datalen = sizeof (slin_adpcm_ex);
00519   /* Assume 8000 Hz */
00520   f.samples = sizeof (slin_adpcm_ex) / 2;
00521   f.mallocd = 0;
00522   f.offset = 0;
00523   f.src = __PRETTY_FUNCTION__;
00524   f.data = slin_adpcm_ex;
00525   return &f;
00526 }
00527 
00528 /*
00529  * Adpcm_Destroy
00530  *  Destroys a private workspace.
00531  *
00532  * Results:
00533  *  It's gone!
00534  *
00535  * Side effects:
00536  *  None.
00537  */
00538 
00539 static void
00540 adpcm_destroy (struct ast_translator_pvt *pvt)
00541 {
00542   free (pvt);
00543   localusecnt--;
00544   ast_update_use_count ();
00545 }
00546 
00547 /*
00548  * The complete translator for ADPCMToLin.
00549  */
00550 
00551 static struct ast_translator adpcmtolin = {
00552   "adpcmtolin",
00553   AST_FORMAT_ADPCM,
00554   AST_FORMAT_SLINEAR,
00555   adpcmtolin_new,
00556   adpcmtolin_framein,
00557   adpcmtolin_frameout,
00558   adpcm_destroy,
00559   /* NULL */
00560   adpcmtolin_sample
00561 };
00562 
00563 /*
00564  * The complete translator for LinToADPCM.
00565  */
00566 
00567 static struct ast_translator lintoadpcm = {
00568   "lintoadpcm",
00569   AST_FORMAT_SLINEAR,
00570   AST_FORMAT_ADPCM,
00571   lintoadpcm_new,
00572   lintoadpcm_framein,
00573   lintoadpcm_frameout,
00574   adpcm_destroy,
00575   /* NULL */
00576   lintoadpcm_sample
00577 };
00578 
00579 static void 
00580 parse_config(void)
00581 {
00582   struct ast_config *cfg;
00583   struct ast_variable *var;
00584   if ((cfg = ast_config_load("codecs.conf"))) {
00585     if ((var = ast_variable_browse(cfg, "plc"))) {
00586       while (var) {
00587        if (!strcasecmp(var->name, "genericplc")) {
00588          useplc = ast_true(var->value) ? 1 : 0;
00589          if (option_verbose > 2)
00590            ast_verbose(VERBOSE_PREFIX_3 "codec_adpcm: %susing generic PLC\n", useplc ? "" : "not ");
00591        }
00592        var = var->next;
00593       }
00594     }
00595     ast_config_destroy(cfg);
00596   }
00597 }
00598 
00599 int
00600 reload(void)
00601 {
00602   parse_config();
00603   return 0;
00604 }
00605 
00606 int
00607 unload_module (void)
00608 {
00609   int res;
00610   ast_mutex_lock (&localuser_lock);
00611   res = ast_unregister_translator (&lintoadpcm);
00612   if (!res)
00613     res = ast_unregister_translator (&adpcmtolin);
00614   if (localusecnt)
00615     res = -1;
00616   ast_mutex_unlock (&localuser_lock);
00617   return res;
00618 }
00619 
00620 int
00621 load_module (void)
00622 {
00623   int res;
00624   parse_config();
00625   res = ast_register_translator (&adpcmtolin);
00626   if (!res)
00627     res = ast_register_translator (&lintoadpcm);
00628   else
00629     ast_unregister_translator (&adpcmtolin);
00630   return res;
00631 }
00632 
00633 /*
00634  * Return a description of this module.
00635  */
00636 
00637 char *
00638 description (void)
00639 {
00640   return tdesc;
00641 }
00642 
00643 int
00644 usecount (void)
00645 {
00646   int res;
00647   STANDARD_USECOUNT (res);
00648   return res;
00649 }
00650 
00651 char *
00652 key ()
00653 {
00654   return ASTERISK_GPL_KEY;
00655 }

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