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

Generated on Thu Apr 16 06:27:30 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6