Wed Oct 28 11:45:36 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 "asterisk.h"
00031 
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 94541 $")
00033 
00034 #include "asterisk/lock.h"
00035 #include "asterisk/linkedlists.h"
00036 #include "asterisk/module.h"
00037 #include "asterisk/config.h"
00038 #include "asterisk/translate.h"
00039 #include "asterisk/utils.h"
00040 
00041 /* define NOT_BLI to use a faster but not bit-level identical version */
00042 /* #define NOT_BLI */
00043 
00044 #define BUFFER_SAMPLES   8096 /* size for the translation buffers */
00045 
00046 /* Sample frame data */
00047 
00048 #include "slin_adpcm_ex.h"
00049 #include "adpcm_slin_ex.h"
00050 
00051 /*
00052  * Step size index shift table 
00053  */
00054 
00055 static int indsft[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
00056 
00057 /*
00058  * Step size table, where stpsz[i]=floor[16*(11/10)^i]
00059  */
00060 
00061 static int stpsz[49] = {
00062   16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73,
00063   80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279,
00064   307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963,
00065   1060, 1166, 1282, 1411, 1552
00066 };
00067 
00068 /*
00069  * Decoder/Encoder state
00070  *   States for both encoder and decoder are synchronized
00071  */
00072 struct adpcm_state {
00073    int ssindex;
00074    int signal;
00075    int zero_count;
00076    int next_flag;
00077 };
00078 
00079 /*
00080  * Decode(encoded)
00081  *  Decodes the encoded nibble from the adpcm file.
00082  *
00083  * Results:
00084  *  Returns the encoded difference.
00085  *
00086  * Side effects:
00087  *  Sets the index to the step size table for the next encode.
00088  */
00089 
00090 static inline short decode(int encoded, struct adpcm_state *state)
00091 {
00092    int diff;
00093    int step;
00094    int sign;
00095 
00096    step = stpsz[state->ssindex];
00097 
00098    sign = encoded & 0x08;
00099    encoded &= 0x07;
00100 #ifdef NOT_BLI
00101    diff = (((encoded << 1) + 1) * step) >> 3;
00102 #else /* BLI code */
00103    diff = step >> 3;
00104    if (encoded & 4)
00105       diff += step;
00106    if (encoded & 2)
00107       diff += step >> 1;
00108    if (encoded & 1)
00109       diff += step >> 2;
00110    if ((encoded >> 1) & step & 0x1)
00111       diff++;
00112 #endif
00113    if (sign)
00114       diff = -diff;
00115 
00116    if (state->next_flag & 0x1)
00117       state->signal -= 8;
00118    else if (state->next_flag & 0x2)
00119       state->signal += 8;
00120 
00121    state->signal += diff;
00122 
00123    if (state->signal > 2047)
00124       state->signal = 2047;
00125    else if (state->signal < -2047)
00126       state->signal = -2047;
00127 
00128    state->next_flag = 0;
00129 
00130 #ifdef AUTO_RETURN
00131    if (encoded)
00132       state->zero_count = 0;
00133    else if (++(state->zero_count) == 24) {
00134       state->zero_count = 0;
00135       if (state->signal > 0)
00136          state->next_flag = 0x1;
00137       else if (state->signal < 0)
00138          state->next_flag = 0x2;
00139    }
00140 #endif
00141 
00142    state->ssindex += indsft[encoded];
00143    if (state->ssindex < 0)
00144       state->ssindex = 0;
00145    else if (state->ssindex > 48)
00146       state->ssindex = 48;
00147 
00148    return state->signal << 4;
00149 }
00150 
00151 /*
00152  * Adpcm
00153  *  Takes a signed linear signal and encodes it as ADPCM
00154  *  For more information see http://support.dialogic.com/appnotes/adpcm.pdf
00155  *
00156  * Results:
00157  *  Foo.
00158  *
00159  * Side effects:
00160  *  signal gets updated with each pass.
00161  */
00162 
00163 static inline int adpcm(short csig, struct adpcm_state *state)
00164 {
00165    int diff;
00166    int step;
00167    int encoded;
00168 
00169    /* 
00170     * Clip csig if too large or too small
00171     */
00172    csig >>= 4;
00173 
00174    step = stpsz[state->ssindex];
00175    diff = csig - state->signal;
00176 
00177 #ifdef NOT_BLI
00178    if (diff < 0) {
00179       encoded = (-diff << 2) / step;
00180       if (encoded > 7)
00181          encoded = 7;
00182       encoded |= 0x08;
00183    } else {
00184       encoded = (diff << 2) / step;
00185       if (encoded > 7)
00186          encoded = 7;
00187    }
00188 #else /* BLI code */
00189    if (diff < 0) {
00190       encoded = 8;
00191       diff = -diff;
00192    } else
00193       encoded = 0;
00194    if (diff >= step) {
00195       encoded |= 4;
00196       diff -= step;
00197    }
00198    step >>= 1;
00199    if (diff >= step) {
00200       encoded |= 2;
00201       diff -= step;
00202    }
00203    step >>= 1;
00204    if (diff >= step)
00205       encoded |= 1;
00206 #endif /* NOT_BLI */
00207 
00208    /* feedback to state */
00209    decode(encoded, state);
00210    
00211    return encoded;
00212 }
00213 
00214 /*----------------- Asterisk-codec glue ------------*/
00215 
00216 /*! \brief Workspace for translating signed linear signals to ADPCM. */
00217 struct adpcm_encoder_pvt {
00218    struct adpcm_state state;
00219    int16_t inbuf[BUFFER_SAMPLES];   /* Unencoded signed linear values */
00220 };
00221 
00222 /*! \brief Workspace for translating ADPCM signals to signed linear. */
00223 struct adpcm_decoder_pvt {
00224    struct adpcm_state state;
00225 };
00226 
00227 /*! \brief decode 4-bit adpcm frame data and store in output buffer */
00228 static int adpcmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00229 {
00230    struct adpcm_decoder_pvt *tmp = pvt->pvt;
00231    int x = f->datalen;
00232    unsigned char *src = f->data;
00233    int16_t *dst = (int16_t *)pvt->outbuf + pvt->samples;
00234 
00235    while (x--) {
00236       *dst++ = decode((*src >> 4) & 0xf, &tmp->state);
00237       *dst++ = decode(*src++ & 0x0f, &tmp->state);
00238    }
00239    pvt->samples += f->samples;
00240    pvt->datalen += 2*f->samples;
00241    return 0;
00242 }
00243 
00244 /*! \brief fill input buffer with 16-bit signed linear PCM values. */
00245 static int lintoadpcm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00246 {
00247    struct adpcm_encoder_pvt *tmp = pvt->pvt;
00248 
00249    memcpy(&tmp->inbuf[pvt->samples], f->data, f->datalen);
00250    pvt->samples += f->samples;
00251    return 0;
00252 }
00253 
00254 /*! \brief convert inbuf and store into frame */
00255 static struct ast_frame *lintoadpcm_frameout(struct ast_trans_pvt *pvt)
00256 {
00257    struct adpcm_encoder_pvt *tmp = pvt->pvt;
00258    struct ast_frame *f;
00259    int i;
00260    int samples = pvt->samples;   /* save original number */
00261   
00262    if (samples < 2)
00263       return NULL;
00264 
00265    pvt->samples &= ~1; /* atomic size is 2 samples */
00266 
00267    for (i = 0; i < pvt->samples; i += 2) {
00268       pvt->outbuf[i/2] =
00269          (adpcm(tmp->inbuf[i  ], &tmp->state) << 4) |
00270          (adpcm(tmp->inbuf[i+1], &tmp->state)     );
00271    };
00272 
00273    f = ast_trans_frameout(pvt, pvt->samples/2, 0);
00274 
00275    /*
00276     * If there is a left over sample, move it to the beginning
00277     * of the input buffer.
00278     */
00279 
00280    if (samples & 1) {   /* move the leftover sample at beginning */
00281       tmp->inbuf[0] = tmp->inbuf[samples - 1];
00282       pvt->samples = 1;
00283    }
00284    return f;
00285 }
00286 
00287 
00288 /*! \brief AdpcmToLin_Sample */
00289 static struct ast_frame *adpcmtolin_sample(void)
00290 {
00291    static struct ast_frame f;
00292    f.frametype = AST_FRAME_VOICE;
00293    f.subclass = AST_FORMAT_ADPCM;
00294    f.datalen = sizeof(adpcm_slin_ex);
00295    f.samples = sizeof(adpcm_slin_ex) * 2;
00296    f.mallocd = 0;
00297    f.offset = 0;
00298    f.src = __PRETTY_FUNCTION__;
00299    f.data = adpcm_slin_ex;
00300    return &f;
00301 }
00302 
00303 /*! \brief LinToAdpcm_Sample */
00304 static struct ast_frame *lintoadpcm_sample(void)
00305 {
00306    static struct ast_frame f;
00307    f.frametype = AST_FRAME_VOICE;
00308    f.subclass = AST_FORMAT_SLINEAR;
00309    f.datalen = sizeof(slin_adpcm_ex);
00310    /* Assume 8000 Hz */
00311    f.samples = sizeof(slin_adpcm_ex) / 2;
00312    f.mallocd = 0;
00313    f.offset = 0;
00314    f.src = __PRETTY_FUNCTION__;
00315    f.data = slin_adpcm_ex;
00316    return &f;
00317 }
00318 
00319 static struct ast_translator adpcmtolin = {
00320    .name = "adpcmtolin",
00321    .srcfmt = AST_FORMAT_ADPCM,
00322    .dstfmt = AST_FORMAT_SLINEAR,
00323    .framein = adpcmtolin_framein,
00324    .sample = adpcmtolin_sample,
00325    .desc_size = sizeof(struct adpcm_decoder_pvt),
00326    .buffer_samples = BUFFER_SAMPLES,
00327    .buf_size = BUFFER_SAMPLES * 2,
00328    .plc_samples = 160,
00329 };
00330 
00331 static struct ast_translator lintoadpcm = {
00332    .name = "lintoadpcm",
00333    .srcfmt = AST_FORMAT_SLINEAR,
00334    .dstfmt = AST_FORMAT_ADPCM,
00335    .framein = lintoadpcm_framein,
00336    .frameout = lintoadpcm_frameout,
00337    .sample = lintoadpcm_sample,
00338    .desc_size = sizeof (struct adpcm_encoder_pvt),
00339    .buffer_samples = BUFFER_SAMPLES,
00340    .buf_size = BUFFER_SAMPLES/ 2,   /* 2 samples per byte */
00341 };
00342 
00343 static int parse_config(int reload)
00344 {
00345    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00346    struct ast_config *cfg = ast_config_load("codecs.conf", config_flags);
00347    struct ast_variable *var;
00348    if (cfg == NULL)
00349       return 0;
00350    if (cfg == CONFIG_STATUS_FILEUNCHANGED)
00351       return 0;
00352    for (var = ast_variable_browse(cfg, "plc"); var ; var = var->next) {
00353       if (!strcasecmp(var->name, "genericplc")) {
00354          adpcmtolin.useplc = ast_true(var->value) ? 1 : 0;
00355          ast_verb(3, "codec_adpcm: %susing generic PLC\n", adpcmtolin.useplc ? "" : "not ");
00356       }
00357    }
00358    ast_config_destroy(cfg);
00359    return 0;
00360 }
00361 
00362 /*! \brief standard module glue */
00363 static int reload(void)
00364 {
00365    if (parse_config(1))
00366       return AST_MODULE_LOAD_DECLINE;
00367    return AST_MODULE_LOAD_SUCCESS;
00368 }
00369 
00370 static int unload_module(void)
00371 {
00372    int res;
00373 
00374    res = ast_unregister_translator(&lintoadpcm);
00375    res |= ast_unregister_translator(&adpcmtolin);
00376 
00377    return res;
00378 }
00379 
00380 static int load_module(void)
00381 {
00382    int res;
00383 
00384    if (parse_config(0))
00385       return AST_MODULE_LOAD_DECLINE;
00386    res = ast_register_translator(&adpcmtolin);
00387    if (!res)
00388       res = ast_register_translator(&lintoadpcm);
00389    else
00390       ast_unregister_translator(&adpcmtolin);
00391    if (res)
00392       return AST_MODULE_LOAD_FAILURE;
00393    return AST_MODULE_LOAD_SUCCESS;
00394 }
00395 
00396 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Adaptive Differential PCM Coder/Decoder",
00397       .load = load_module,
00398       .unload = unload_module,
00399       .reload = reload,
00400           );

Generated on Wed Oct 28 11:45:36 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6