Asterisk.org: Developer Documentation (28 Oct 2009)

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 }