Sat Apr 26 2014 22:01:35

Asterisk developer's documentation


codec_speex.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  *
00009  * See http://www.asterisk.org for more information about
00010  * the Asterisk project. Please do not directly contact
00011  * any of the maintainers of this project for assistance;
00012  * the project provides a web site, mailing lists and IRC
00013  * channels for your use.
00014  *
00015  * This program is free software, distributed under the terms of
00016  * the GNU General Public License Version 2. See the LICENSE file
00017  * at the top of the source tree.
00018  */
00019 
00020 /*! \file
00021  *
00022  * \brief Translate between signed linear and Speex (Open Codec)
00023  *
00024  * \note This work was motivated by Jeremy McNamara 
00025  * hacked to be configurable by anthm and bkw 9/28/2004
00026  *
00027  * \ingroup codecs
00028  *
00029  * \extref The Speex library - http://www.speex.org
00030  *
00031  */
00032 
00033 /*** MODULEINFO
00034    <depend>speex</depend>
00035    <depend>speex_preprocess</depend>
00036    <use type="external">speexdsp</use>
00037    <support_level>core</support_level>
00038  ***/
00039 
00040 #include "asterisk.h"
00041 
00042 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328259 $")
00043 
00044 #include <speex/speex.h>
00045 
00046 /* We require a post 1.1.8 version of Speex to enable preprocessing
00047    and better type handling */   
00048 #ifdef _SPEEX_TYPES_H
00049 #include <speex/speex_preprocess.h>
00050 #endif
00051 
00052 #include "asterisk/translate.h"
00053 #include "asterisk/module.h"
00054 #include "asterisk/config.h"
00055 #include "asterisk/utils.h"
00056 
00057 /* codec variables */
00058 static int quality = 3;
00059 static int complexity = 2;
00060 static int enhancement = 0;
00061 static int vad = 0;
00062 static int vbr = 0;
00063 static float vbr_quality = 4;
00064 static int abr = 0;
00065 static int dtx = 0;  /* set to 1 to enable silence detection */
00066 
00067 static int preproc = 0;
00068 static int pp_vad = 0;
00069 static int pp_agc = 0;
00070 static float pp_agc_level = 8000; /* XXX what is this 8000 ? */
00071 static int pp_denoise = 0;
00072 static int pp_dereverb = 0;
00073 static float pp_dereverb_decay = 0.4;
00074 static float pp_dereverb_level = 0.3;
00075 
00076 #define TYPE_SILENCE  0x2
00077 #define TYPE_HIGH  0x0
00078 #define TYPE_LOW   0x1
00079 #define TYPE_MASK  0x3
00080 
00081 #define  BUFFER_SAMPLES 8000
00082 #define  SPEEX_SAMPLES  160
00083 
00084 /* Sample frame data */
00085 #include "asterisk/slin.h"
00086 #include "ex_speex.h"
00087 
00088 struct speex_coder_pvt {
00089    void *speex;
00090    SpeexBits bits;
00091    int framesize;
00092    int silent_state;
00093 #ifdef _SPEEX_TYPES_H
00094    SpeexPreprocessState *pp;
00095    spx_int16_t buf[BUFFER_SAMPLES];
00096 #else
00097    int16_t buf[BUFFER_SAMPLES];  /* input, waiting to be compressed */
00098 #endif
00099 };
00100 
00101 static int speex_encoder_construct(struct ast_trans_pvt *pvt, const SpeexMode *profile, int sampling_rate)
00102 {
00103    struct speex_coder_pvt *tmp = pvt->pvt;
00104 
00105    if (!(tmp->speex = speex_encoder_init(profile)))
00106       return -1;
00107 
00108    speex_bits_init(&tmp->bits);
00109    speex_bits_reset(&tmp->bits);
00110    speex_encoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize);
00111    speex_encoder_ctl(tmp->speex, SPEEX_SET_COMPLEXITY, &complexity);
00112 #ifdef _SPEEX_TYPES_H
00113    if (preproc) {
00114       tmp->pp = speex_preprocess_state_init(tmp->framesize, sampling_rate);
00115       speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_VAD, &pp_vad);
00116       speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_AGC, &pp_agc);
00117       speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &pp_agc_level);
00118       speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DENOISE, &pp_denoise);
00119       speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB, &pp_dereverb);
00120       speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &pp_dereverb_decay);
00121       speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &pp_dereverb_level);
00122    }
00123 #endif
00124    if (!abr && !vbr) {
00125       speex_encoder_ctl(tmp->speex, SPEEX_SET_QUALITY, &quality);
00126       if (vad)
00127          speex_encoder_ctl(tmp->speex, SPEEX_SET_VAD, &vad);
00128    }
00129    if (vbr) {
00130       speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR, &vbr);
00131       speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR_QUALITY, &vbr_quality);
00132    }
00133    if (abr)
00134       speex_encoder_ctl(tmp->speex, SPEEX_SET_ABR, &abr);
00135    if (dtx)
00136       speex_encoder_ctl(tmp->speex, SPEEX_SET_DTX, &dtx); 
00137    tmp->silent_state = 0;
00138 
00139    return 0;
00140 }
00141 
00142 static int lintospeex_new(struct ast_trans_pvt *pvt)
00143 {
00144    return speex_encoder_construct(pvt, &speex_nb_mode, 8000);
00145 }
00146 
00147 static int lin16tospeexwb_new(struct ast_trans_pvt *pvt)
00148 {
00149    return speex_encoder_construct(pvt, &speex_wb_mode, 16000);
00150 }
00151 
00152 static int lin32tospeexuwb_new(struct ast_trans_pvt *pvt)
00153 {
00154    return speex_encoder_construct(pvt, &speex_uwb_mode, 32000);
00155 }
00156 
00157 static int speex_decoder_construct(struct ast_trans_pvt *pvt, const SpeexMode *profile)
00158 {
00159    struct speex_coder_pvt *tmp = pvt->pvt;
00160    
00161    if (!(tmp->speex = speex_decoder_init(profile)))
00162       return -1;
00163 
00164    speex_bits_init(&tmp->bits);
00165    speex_decoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize);
00166    if (enhancement)
00167       speex_decoder_ctl(tmp->speex, SPEEX_SET_ENH, &enhancement);
00168 
00169    return 0;
00170 }
00171 
00172 static int speextolin_new(struct ast_trans_pvt *pvt)
00173 {
00174    return speex_decoder_construct(pvt, &speex_nb_mode);
00175 }
00176 
00177 static int speexwbtolin16_new(struct ast_trans_pvt *pvt)
00178 {
00179    return speex_decoder_construct(pvt, &speex_wb_mode);
00180 }
00181 
00182 static int speexuwbtolin32_new(struct ast_trans_pvt *pvt)
00183 {
00184    return speex_decoder_construct(pvt, &speex_uwb_mode);
00185 }
00186 
00187 /*! \brief convert and store into outbuf */
00188 static int speextolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00189 {
00190    struct speex_coder_pvt *tmp = pvt->pvt;
00191 
00192    /* Assuming there's space left, decode into the current buffer at
00193       the tail location.  Read in as many frames as there are */
00194    int x;
00195    int res;
00196    int16_t *dst = pvt->outbuf.i16;
00197    /* XXX fout is a temporary buffer, may have different types */
00198 #ifdef _SPEEX_TYPES_H
00199    spx_int16_t fout[1024];
00200 #else
00201    float fout[1024];
00202 #endif
00203 
00204    if (f->datalen == 0) {  /* Native PLC interpolation */
00205       if (pvt->samples + tmp->framesize > BUFFER_SAMPLES) {
00206          ast_log(LOG_WARNING, "Out of buffer space\n");
00207          return -1;
00208       }
00209 #ifdef _SPEEX_TYPES_H
00210       speex_decode_int(tmp->speex, NULL, dst + pvt->samples);
00211 #else
00212       speex_decode(tmp->speex, NULL, fout);
00213       for (x=0;x<tmp->framesize;x++) {
00214          dst[pvt->samples + x] = (int16_t)fout[x];
00215       }
00216 #endif
00217       pvt->samples += tmp->framesize;
00218       pvt->datalen += 2 * tmp->framesize; /* 2 bytes/sample */
00219       return 0;
00220    }
00221 
00222    /* Read in bits */
00223    speex_bits_read_from(&tmp->bits, f->data.ptr, f->datalen);
00224    for (;;) {
00225 #ifdef _SPEEX_TYPES_H
00226       res = speex_decode_int(tmp->speex, &tmp->bits, fout);
00227 #else
00228       res = speex_decode(tmp->speex, &tmp->bits, fout);
00229 #endif
00230       if (res < 0)
00231          break;
00232       if (pvt->samples + tmp->framesize > BUFFER_SAMPLES) {
00233          ast_log(LOG_WARNING, "Out of buffer space\n");
00234          return -1;
00235       }
00236       for (x = 0 ; x < tmp->framesize; x++)
00237          dst[pvt->samples + x] = (int16_t)fout[x];
00238       pvt->samples += tmp->framesize;
00239       pvt->datalen += 2 * tmp->framesize; /* 2 bytes/sample */
00240    }
00241    return 0;
00242 }
00243 
00244 /*! \brief store input frame in work buffer */
00245 static int lintospeex_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00246 {
00247    struct speex_coder_pvt *tmp = pvt->pvt;
00248 
00249    /* XXX We should look at how old the rest of our stream is, and if it
00250       is too old, then we should overwrite it entirely, otherwise we can
00251       get artifacts of earlier talk that do not belong */
00252    memcpy(tmp->buf + pvt->samples, f->data.ptr, f->datalen);
00253    pvt->samples += f->samples;
00254    return 0;
00255 }
00256 
00257 /*! \brief convert work buffer and produce output frame */
00258 static struct ast_frame *lintospeex_frameout(struct ast_trans_pvt *pvt)
00259 {
00260    struct speex_coder_pvt *tmp = pvt->pvt;
00261    int is_speech=1;
00262    int datalen = 0;  /* output bytes */
00263    int samples = 0;  /* output samples */
00264 
00265    /* We can't work on anything less than a frame in size */
00266    if (pvt->samples < tmp->framesize)
00267       return NULL;
00268    speex_bits_reset(&tmp->bits);
00269    while (pvt->samples >= tmp->framesize) {
00270 #ifdef _SPEEX_TYPES_H
00271       /* Preprocess audio */
00272       if (preproc)
00273          is_speech = speex_preprocess(tmp->pp, tmp->buf + samples, NULL);
00274       /* Encode a frame of data */
00275       if (is_speech) {
00276          /* If DTX enabled speex_encode returns 0 during silence */
00277          is_speech = speex_encode_int(tmp->speex, tmp->buf + samples, &tmp->bits) || !dtx;
00278       } else {
00279          /* 5 zeros interpreted by Speex as silence (submode 0) */
00280          speex_bits_pack(&tmp->bits, 0, 5);
00281       }
00282 #else
00283       {
00284          float fbuf[1024];
00285          int x;
00286          /* Convert to floating point */
00287          for (x = 0; x < tmp->framesize; x++)
00288             fbuf[x] = tmp->buf[samples + x];
00289          /* Encode a frame of data */
00290          is_speech = speex_encode(tmp->speex, fbuf, &tmp->bits) || !dtx;
00291       }
00292 #endif
00293       samples += tmp->framesize;
00294       pvt->samples -= tmp->framesize;
00295    }
00296 
00297    /* Move the data at the end of the buffer to the front */
00298    if (pvt->samples)
00299       memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
00300 
00301    /* Use AST_FRAME_CNG to signify the start of any silence period */
00302    if (is_speech) {
00303       tmp->silent_state = 0;
00304    } else {
00305       if (tmp->silent_state) {
00306          return NULL;
00307       } else {
00308          tmp->silent_state = 1;
00309          speex_bits_reset(&tmp->bits);
00310          memset(&pvt->f, 0, sizeof(pvt->f));
00311          pvt->f.frametype = AST_FRAME_CNG;
00312          pvt->f.samples = samples;
00313          /* XXX what now ? format etc... */
00314       }
00315    }
00316 
00317    /* Terminate bit stream */
00318    speex_bits_pack(&tmp->bits, 15, 5);
00319    datalen = speex_bits_write(&tmp->bits, pvt->outbuf.c, pvt->t->buf_size);
00320    return ast_trans_frameout(pvt, datalen, samples);
00321 }
00322 
00323 static void speextolin_destroy(struct ast_trans_pvt *arg)
00324 {
00325    struct speex_coder_pvt *pvt = arg->pvt;
00326 
00327    speex_decoder_destroy(pvt->speex);
00328    speex_bits_destroy(&pvt->bits);
00329 }
00330 
00331 static void lintospeex_destroy(struct ast_trans_pvt *arg)
00332 {
00333    struct speex_coder_pvt *pvt = arg->pvt;
00334 #ifdef _SPEEX_TYPES_H
00335    if (preproc)
00336       speex_preprocess_state_destroy(pvt->pp);
00337 #endif
00338    speex_encoder_destroy(pvt->speex);
00339    speex_bits_destroy(&pvt->bits);
00340 }
00341 
00342 static struct ast_translator speextolin = {
00343    .name = "speextolin", 
00344    .newpvt = speextolin_new,
00345    .framein = speextolin_framein,
00346    .destroy = speextolin_destroy,
00347    .sample = speex_sample,
00348    .desc_size = sizeof(struct speex_coder_pvt),
00349    .buffer_samples = BUFFER_SAMPLES,
00350    .buf_size = BUFFER_SAMPLES * 2,
00351    .native_plc = 1,
00352 };
00353 
00354 static struct ast_translator lintospeex = {
00355    .name = "lintospeex", 
00356    .newpvt = lintospeex_new,
00357    .framein = lintospeex_framein,
00358    .frameout = lintospeex_frameout,
00359    .destroy = lintospeex_destroy,
00360    .sample = slin8_sample,
00361    .desc_size = sizeof(struct speex_coder_pvt),
00362    .buffer_samples = BUFFER_SAMPLES,
00363    .buf_size = BUFFER_SAMPLES * 2, /* XXX maybe a lot less ? */
00364 };
00365 
00366 static struct ast_translator speexwbtolin16 = {
00367    .name = "speexwbtolin16", 
00368    .newpvt = speexwbtolin16_new,
00369    .framein = speextolin_framein,
00370    .destroy = speextolin_destroy,
00371    .sample = speex16_sample,
00372    .desc_size = sizeof(struct speex_coder_pvt),
00373    .buffer_samples = BUFFER_SAMPLES,
00374    .buf_size = BUFFER_SAMPLES * 2,
00375    .native_plc = 1,
00376 };
00377 
00378 static struct ast_translator lin16tospeexwb = {
00379    .name = "lin16tospeexwb", 
00380    .newpvt = lin16tospeexwb_new,
00381    .framein = lintospeex_framein,
00382    .frameout = lintospeex_frameout,
00383    .destroy = lintospeex_destroy,
00384    .sample = slin16_sample,
00385    .desc_size = sizeof(struct speex_coder_pvt),
00386    .buffer_samples = BUFFER_SAMPLES,
00387    .buf_size = BUFFER_SAMPLES * 2, /* XXX maybe a lot less ? */
00388 };
00389 
00390 static struct ast_translator speexuwbtolin32 = {
00391    .name = "speexuwbtolin32", 
00392    .newpvt = speexuwbtolin32_new,
00393    .framein = speextolin_framein,
00394    .destroy = speextolin_destroy,
00395    .desc_size = sizeof(struct speex_coder_pvt),
00396    .buffer_samples = BUFFER_SAMPLES,
00397    .buf_size = BUFFER_SAMPLES * 2,
00398    .native_plc = 1,
00399 };
00400 
00401 static struct ast_translator lin32tospeexuwb = {
00402    .name = "lin32tospeexuwb", 
00403    .newpvt = lin32tospeexuwb_new,
00404    .framein = lintospeex_framein,
00405    .frameout = lintospeex_frameout,
00406    .destroy = lintospeex_destroy,
00407    .desc_size = sizeof(struct speex_coder_pvt),
00408    .buffer_samples = BUFFER_SAMPLES,
00409    .buf_size = BUFFER_SAMPLES * 2, /* XXX maybe a lot less ? */
00410 };
00411 
00412 static int parse_config(int reload) 
00413 {
00414    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00415    struct ast_config *cfg = ast_config_load("codecs.conf", config_flags);
00416    struct ast_variable *var;
00417    int res;
00418    float res_f;
00419 
00420    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID)
00421       return 0;
00422 
00423    for (var = ast_variable_browse(cfg, "speex"); var; var = var->next) {
00424       if (!strcasecmp(var->name, "quality")) {
00425          res = abs(atoi(var->value));
00426          if (res > -1 && res < 11) {
00427             ast_verb(3, "CODEC SPEEX: Setting Quality to %d\n",res);
00428             quality = res;
00429          } else 
00430             ast_log(LOG_ERROR,"Error Quality must be 0-10\n");
00431       } else if (!strcasecmp(var->name, "complexity")) {
00432          res = abs(atoi(var->value));
00433          if (res > -1 && res < 11) {
00434             ast_verb(3, "CODEC SPEEX: Setting Complexity to %d\n",res);
00435             complexity = res;
00436          } else 
00437             ast_log(LOG_ERROR,"Error! Complexity must be 0-10\n");
00438       } else if (!strcasecmp(var->name, "vbr_quality")) {
00439          if (sscanf(var->value, "%30f", &res_f) == 1 && res_f >= 0 && res_f <= 10) {
00440             ast_verb(3, "CODEC SPEEX: Setting VBR Quality to %f\n",res_f);
00441             vbr_quality = res_f;
00442          } else
00443             ast_log(LOG_ERROR,"Error! VBR Quality must be 0-10\n");
00444       } else if (!strcasecmp(var->name, "abr_quality")) {
00445          ast_log(LOG_ERROR,"Error! ABR Quality setting obsolete, set ABR to desired bitrate\n");
00446       } else if (!strcasecmp(var->name, "enhancement")) {
00447          enhancement = ast_true(var->value) ? 1 : 0;
00448          ast_verb(3, "CODEC SPEEX: Perceptual Enhancement Mode. [%s]\n",enhancement ? "on" : "off");
00449       } else if (!strcasecmp(var->name, "vbr")) {
00450          vbr = ast_true(var->value) ? 1 : 0;
00451          ast_verb(3, "CODEC SPEEX: VBR Mode. [%s]\n",vbr ? "on" : "off");
00452       } else if (!strcasecmp(var->name, "abr")) {
00453          res = abs(atoi(var->value));
00454          if (res >= 0) {
00455                if (res > 0)
00456                ast_verb(3, "CODEC SPEEX: Setting ABR target bitrate to %d\n",res);
00457                else
00458                ast_verb(3, "CODEC SPEEX: Disabling ABR\n");
00459             abr = res;
00460          } else 
00461             ast_log(LOG_ERROR,"Error! ABR target bitrate must be >= 0\n");
00462       } else if (!strcasecmp(var->name, "vad")) {
00463          vad = ast_true(var->value) ? 1 : 0;
00464          ast_verb(3, "CODEC SPEEX: VAD Mode. [%s]\n",vad ? "on" : "off");
00465       } else if (!strcasecmp(var->name, "dtx")) {
00466          dtx = ast_true(var->value) ? 1 : 0;
00467          ast_verb(3, "CODEC SPEEX: DTX Mode. [%s]\n",dtx ? "on" : "off");
00468       } else if (!strcasecmp(var->name, "preprocess")) {
00469          preproc = ast_true(var->value) ? 1 : 0;
00470          ast_verb(3, "CODEC SPEEX: Preprocessing. [%s]\n",preproc ? "on" : "off");
00471       } else if (!strcasecmp(var->name, "pp_vad")) {
00472          pp_vad = ast_true(var->value) ? 1 : 0;
00473          ast_verb(3, "CODEC SPEEX: Preprocessor VAD. [%s]\n",pp_vad ? "on" : "off");
00474       } else if (!strcasecmp(var->name, "pp_agc")) {
00475          pp_agc = ast_true(var->value) ? 1 : 0;
00476          ast_verb(3, "CODEC SPEEX: Preprocessor AGC. [%s]\n",pp_agc ? "on" : "off");
00477       } else if (!strcasecmp(var->name, "pp_agc_level")) {
00478          if (sscanf(var->value, "%30f", &res_f) == 1 && res_f >= 0) {
00479             ast_verb(3, "CODEC SPEEX: Setting preprocessor AGC Level to %f\n",res_f);
00480             pp_agc_level = res_f;
00481          } else
00482             ast_log(LOG_ERROR,"Error! Preprocessor AGC Level must be >= 0\n");
00483       } else if (!strcasecmp(var->name, "pp_denoise")) {
00484          pp_denoise = ast_true(var->value) ? 1 : 0;
00485          ast_verb(3, "CODEC SPEEX: Preprocessor Denoise. [%s]\n",pp_denoise ? "on" : "off");
00486       } else if (!strcasecmp(var->name, "pp_dereverb")) {
00487          pp_dereverb = ast_true(var->value) ? 1 : 0;
00488          ast_verb(3, "CODEC SPEEX: Preprocessor Dereverb. [%s]\n",pp_dereverb ? "on" : "off");
00489       } else if (!strcasecmp(var->name, "pp_dereverb_decay")) {
00490          if (sscanf(var->value, "%30f", &res_f) == 1 && res_f >= 0) {
00491             ast_verb(3, "CODEC SPEEX: Setting preprocessor Dereverb Decay to %f\n",res_f);
00492             pp_dereverb_decay = res_f;
00493          } else
00494             ast_log(LOG_ERROR,"Error! Preprocessor Dereverb Decay must be >= 0\n");
00495       } else if (!strcasecmp(var->name, "pp_dereverb_level")) {
00496          if (sscanf(var->value, "%30f", &res_f) == 1 && res_f >= 0) {
00497             ast_verb(3, "CODEC SPEEX: Setting preprocessor Dereverb Level to %f\n",res_f);
00498             pp_dereverb_level = res_f;
00499          } else
00500             ast_log(LOG_ERROR,"Error! Preprocessor Dereverb Level must be >= 0\n");
00501       }
00502    }
00503    ast_config_destroy(cfg);
00504    return 0;
00505 }
00506 
00507 static int reload(void) 
00508 {
00509    if (parse_config(1))
00510       return AST_MODULE_LOAD_DECLINE;
00511    return AST_MODULE_LOAD_SUCCESS;
00512 }
00513 
00514 static int unload_module(void)
00515 {
00516    int res = 0;
00517 
00518    res |= ast_unregister_translator(&speextolin);
00519    res |= ast_unregister_translator(&lintospeex);
00520    res |= ast_unregister_translator(&speexwbtolin16);
00521    res |= ast_unregister_translator(&lin16tospeexwb);
00522    res |= ast_unregister_translator(&speexuwbtolin32);
00523    res |= ast_unregister_translator(&lin32tospeexuwb);
00524 
00525 
00526    return res;
00527 }
00528 
00529 static int load_module(void)
00530 {
00531    int res = 0;
00532 
00533    if (parse_config(0))
00534       return AST_MODULE_LOAD_DECLINE;
00535 
00536 
00537    ast_format_set(&speextolin.src_format, AST_FORMAT_SPEEX, 0);
00538    ast_format_set(&speextolin.dst_format, AST_FORMAT_SLINEAR, 0);
00539 
00540    ast_format_set(&lintospeex.src_format, AST_FORMAT_SLINEAR, 0);
00541    ast_format_set(&lintospeex.dst_format, AST_FORMAT_SPEEX, 0);
00542 
00543    ast_format_set(&speexwbtolin16.src_format, AST_FORMAT_SPEEX16, 0);
00544    ast_format_set(&speexwbtolin16.dst_format, AST_FORMAT_SLINEAR16, 0);
00545 
00546    ast_format_set(&lin16tospeexwb.src_format, AST_FORMAT_SLINEAR16, 0);
00547    ast_format_set(&lin16tospeexwb.dst_format, AST_FORMAT_SPEEX16, 0);
00548 
00549    ast_format_set(&speexuwbtolin32.src_format, AST_FORMAT_SPEEX32, 0);
00550    ast_format_set(&speexuwbtolin32.dst_format, AST_FORMAT_SLINEAR32, 0);
00551 
00552    ast_format_set(&lin32tospeexuwb.src_format, AST_FORMAT_SLINEAR32, 0);
00553    ast_format_set(&lin32tospeexuwb.dst_format, AST_FORMAT_SPEEX32, 0);
00554 
00555    res |= ast_register_translator(&speextolin);
00556    res |= ast_register_translator(&lintospeex);
00557    res |= ast_register_translator(&speexwbtolin16);
00558    res |= ast_register_translator(&lin16tospeexwb);
00559    res |= ast_register_translator(&speexuwbtolin32);
00560    res |= ast_register_translator(&lin32tospeexuwb);
00561 
00562 
00563    return res;
00564 }
00565 
00566 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Speex Coder/Decoder",
00567       .load = load_module,
00568       .unload = unload_module,
00569       .reload = reload,
00570           );