Sat Aug 6 00:39:28 2011

Asterisk developer's documentation


codec_lpc10.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * The lpc10 code is from a library used by nautilus, modified to be a bit
00009  * nicer to the compiler.
00010  * See http://www.arl.wustl.edu/~jaf/ 
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 Translate between signed linear and LPC10 (Linear Predictor Code)
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 <stdlib.h>
00036 #include <unistd.h>
00037 #include <netinet/in.h>
00038 #include <string.h>
00039 #include <stdio.h>
00040 
00041 #include "asterisk/lock.h"
00042 #include "asterisk/translate.h"
00043 #include "asterisk/config.h"
00044 #include "asterisk/options.h"
00045 #include "asterisk/module.h"
00046 #include "asterisk/logger.h"
00047 #include "asterisk/channel.h"
00048 #include "asterisk/utils.h"
00049 
00050 #include "lpc10/lpc10.h"
00051 
00052 /* Sample frame data */
00053 #include "slin_lpc10_ex.h"
00054 #include "lpc10_slin_ex.h"
00055 
00056 /* We use a very strange format here...  I have no idea why...  The frames are 180
00057    samples long, which isn't even an even number of milliseconds...  Not only that
00058    but we hvae to waste two bits of each frame to keep them ending on a byte boundary
00059    because the frames are 54 bits long */
00060 
00061 #define LPC10_BYTES_IN_COMPRESSED_FRAME (LPC10_BITS_IN_COMPRESSED_FRAME + 7)/8
00062 
00063 #define  BUFFER_SAMPLES 8000
00064 
00065 struct lpc10_coder_pvt {
00066    union {
00067       struct lpc10_encoder_state *enc;
00068       struct lpc10_decoder_state *dec;
00069    } lpc10;
00070    /* Enough to store a full second */
00071    short buf[BUFFER_SAMPLES];
00072    int longer;
00073 };
00074 
00075 static int lpc10_enc_new(struct ast_trans_pvt *pvt)
00076 {
00077    struct lpc10_coder_pvt *tmp = pvt->pvt;
00078 
00079    return (tmp->lpc10.enc = create_lpc10_encoder_state()) ? 0 : -1;
00080 }
00081 
00082 static int lpc10_dec_new(struct ast_trans_pvt *pvt)
00083 {
00084    struct lpc10_coder_pvt *tmp = pvt->pvt;
00085 
00086    return (tmp->lpc10.dec = create_lpc10_decoder_state()) ? 0 : -1;
00087 }
00088 
00089 static struct ast_frame *lintolpc10_sample(void)
00090 {
00091    static struct ast_frame f;
00092    f.frametype = AST_FRAME_VOICE;
00093    f.subclass = AST_FORMAT_SLINEAR;
00094    f.datalen = sizeof(slin_lpc10_ex);
00095    /* Assume 8000 Hz */
00096    f.samples = LPC10_SAMPLES_PER_FRAME;
00097    f.mallocd = 0;
00098    f.offset = 0;
00099    f.src = __PRETTY_FUNCTION__;
00100    f.data = slin_lpc10_ex;
00101    return &f;
00102 }
00103 
00104 static struct ast_frame *lpc10tolin_sample(void)
00105 {
00106    static struct ast_frame f;
00107    f.frametype = AST_FRAME_VOICE;
00108    f.subclass = AST_FORMAT_LPC10;
00109    f.datalen = sizeof(lpc10_slin_ex);
00110    /* All frames are 22 ms long (maybe a little more -- why did he choose
00111       LPC10_SAMPLES_PER_FRAME sample frames anyway?? */
00112    f.samples = LPC10_SAMPLES_PER_FRAME;
00113    f.mallocd = 0;
00114    f.offset = 0;
00115    f.src = __PRETTY_FUNCTION__;
00116    f.data = lpc10_slin_ex;
00117    return &f;
00118 }
00119 
00120 static void extract_bits(INT32 *bits, unsigned char *c)
00121 {
00122    int x;
00123    for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
00124       if (*c & (0x80 >> (x & 7)))
00125          bits[x] = 1;
00126       else
00127          bits[x] = 0;
00128       if ((x & 7) == 7)
00129          c++;
00130    }
00131 }
00132 
00133 /* XXX note lpc10_encode() produces one bit per word in bits[] */
00134 static void build_bits(unsigned char *c, INT32 *bits)
00135 {
00136    unsigned char mask=0x80;
00137    int x;
00138    *c = 0;
00139    for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
00140       if (bits[x])
00141          *c |= mask;
00142       mask = mask >> 1;
00143       if ((x % 8)==7) {
00144          c++;
00145          *c = 0;
00146          mask = 0x80;
00147       }
00148    }
00149 }
00150 
00151 static int lpc10tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00152 {
00153    struct lpc10_coder_pvt *tmp = pvt->pvt;
00154    int16_t *dst = (int16_t *)pvt->outbuf;
00155    int len = 0;
00156 
00157    while (len + LPC10_BYTES_IN_COMPRESSED_FRAME <= f->datalen) {
00158       int x;
00159       float tmpbuf[LPC10_SAMPLES_PER_FRAME];
00160       INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME]; /* XXX see note */
00161       if (pvt->samples + LPC10_SAMPLES_PER_FRAME > BUFFER_SAMPLES) {
00162          ast_log(LOG_WARNING, "Out of buffer space\n");
00163          return -1;
00164       }
00165       extract_bits(bits, f->data + len);
00166       if (lpc10_decode(bits, tmpbuf, tmp->lpc10.dec)) {
00167          ast_log(LOG_WARNING, "Invalid lpc10 data\n");
00168          return -1;
00169       }
00170       for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
00171          /* Convert to a short between -1.0 and 1.0 */
00172          dst[pvt->samples + x] = (int16_t)(32768.0 * tmpbuf[x]);
00173       }
00174 
00175       pvt->samples += LPC10_SAMPLES_PER_FRAME;
00176       pvt->datalen += 2*LPC10_SAMPLES_PER_FRAME;
00177       len += LPC10_BYTES_IN_COMPRESSED_FRAME;
00178    }
00179    if (len != f->datalen) 
00180       printf("Decoded %d, expected %d\n", len, f->datalen);
00181    return 0;
00182 }
00183 
00184 static int lintolpc10_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00185 {
00186    struct lpc10_coder_pvt *tmp = pvt->pvt;
00187 
00188    /* Just add the frames to our stream */
00189    if (pvt->samples + f->samples > BUFFER_SAMPLES) {
00190       ast_log(LOG_WARNING, "Out of buffer space\n");
00191       return -1;
00192    }
00193    memcpy(tmp->buf + pvt->samples, f->data, f->datalen);
00194    pvt->samples += f->samples;
00195    return 0;
00196 }
00197 
00198 static struct ast_frame *lintolpc10_frameout(struct ast_trans_pvt *pvt)
00199 {
00200    struct lpc10_coder_pvt *tmp = pvt->pvt;
00201    int x;
00202    int datalen = 0;  /* output frame */
00203    int samples = 0;  /* output samples */
00204    float tmpbuf[LPC10_SAMPLES_PER_FRAME];
00205    INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];  /* XXX what ??? */
00206    /* We can't work on anything less than a frame in size */
00207    if (pvt->samples < LPC10_SAMPLES_PER_FRAME)
00208       return NULL;
00209    while (pvt->samples >=  LPC10_SAMPLES_PER_FRAME) {
00210       /* Encode a frame of data */
00211       for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++)
00212          tmpbuf[x] = (float)tmp->buf[x + samples] / 32768.0;
00213       lpc10_encode(tmpbuf, bits, tmp->lpc10.enc);
00214       build_bits((unsigned char *) pvt->outbuf + datalen, bits);
00215       datalen += LPC10_BYTES_IN_COMPRESSED_FRAME;
00216       samples += LPC10_SAMPLES_PER_FRAME;
00217       pvt->samples -= LPC10_SAMPLES_PER_FRAME;
00218       /* Use one of the two left over bits to record if this is a 22 or 23 ms frame...
00219          important for IAX use */
00220       tmp->longer = 1 - tmp->longer;
00221    }
00222    /* Move the data at the end of the buffer to the front */
00223    if (pvt->samples)
00224       memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
00225    return ast_trans_frameout(pvt, datalen, samples);
00226 }
00227 
00228 
00229 static void lpc10_destroy(struct ast_trans_pvt *arg)
00230 {
00231    struct lpc10_coder_pvt *pvt = arg->pvt;
00232    /* Enc and DEC are both just allocated, so they can be freed */
00233    free(pvt->lpc10.enc);
00234 }
00235 
00236 static struct ast_translator lpc10tolin = {
00237    .name = "lpc10tolin", 
00238    .srcfmt = AST_FORMAT_LPC10,
00239    .dstfmt = AST_FORMAT_SLINEAR,
00240    .newpvt = lpc10_dec_new,
00241    .framein = lpc10tolin_framein,
00242    .destroy = lpc10_destroy,
00243    .sample = lpc10tolin_sample,
00244    .desc_size = sizeof(struct lpc10_coder_pvt),
00245    .buffer_samples = BUFFER_SAMPLES,
00246    .buf_size = BUFFER_SAMPLES * 2,
00247 };
00248 
00249 static struct ast_translator lintolpc10 = {
00250    .name = "lintolpc10", 
00251    .srcfmt = AST_FORMAT_SLINEAR,
00252    .dstfmt = AST_FORMAT_LPC10,
00253    .newpvt = lpc10_enc_new,
00254    .framein = lintolpc10_framein,
00255    .frameout = lintolpc10_frameout,
00256    .destroy = lpc10_destroy,
00257    .sample = lintolpc10_sample,
00258    .desc_size = sizeof(struct lpc10_coder_pvt),
00259    .buffer_samples = BUFFER_SAMPLES,
00260    .buf_size = LPC10_BYTES_IN_COMPRESSED_FRAME * (1 + BUFFER_SAMPLES / LPC10_SAMPLES_PER_FRAME),
00261 };
00262 
00263 static int reload(void)
00264 {
00265         return 0;
00266 }
00267 
00268 
00269 static int unload_module(void)
00270 {
00271    int res;
00272 
00273    res = ast_unregister_translator(&lintolpc10);
00274    res |= ast_unregister_translator(&lpc10tolin);
00275 
00276    return res;
00277 }
00278 
00279 static int load_module(void)
00280 {
00281    int res;
00282 
00283    res=ast_register_translator(&lpc10tolin);
00284    if (!res) 
00285       res=ast_register_translator(&lintolpc10);
00286    else
00287       ast_unregister_translator(&lpc10tolin);
00288 
00289    return res;
00290 }
00291 
00292 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "LPC10 2.4kbps Coder/Decoder",
00293       .load = load_module,
00294       .unload = unload_module,
00295       .reload = reload,
00296           );

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