Sat Aug 6 00:39:28 2011

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

Generated on Sat Aug 6 00:39:28 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7