Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:53 2009

## 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  * http://www.speex.org
    00025  * \note This work was motivated by Jeremy McNamara
    00026  * hacked to be configurable by anthm and bkw 9/28/2004
    00027  * \ingroup codecs
    00028  */
    00029
    00030 #include <fcntl.h>
    00031 #include <stdlib.h>
    00032 #include <unistd.h>
    00033 #include <netinet/in.h>
    00034 #include <string.h>
    00035 #include <stdio.h>
    00036 #include <speex.h>
    00037
    00038 /* We require a post 1.1.8 version of Speex to enable preprocessing
    00039    and better type handling */
    00040 #ifdef _SPEEX_TYPES_H
    00041 #include <speex/speex_preprocess.h>
    00042 #endif
    00043
    00044 static int quality = 3;
    00045 static int complexity = 2;
    00046 static int enhancement = 0;
    00047 static int vad = 0;
    00048 static int vbr = 0;
    00049 static float vbr_quality = 4;
    00050 static int abr = 0;
    00051 static int dtx = 0;
    00052
    00053 static int preproc = 0;
    00054 static int pp_vad = 0;
    00055 static int pp_agc = 0;
    00056 static float pp_agc_level = 8000;
    00057 static int pp_denoise = 0;
    00058 static int pp_dereverb = 0;
    00059 static float pp_dereverb_decay = 0.4;
    00060 static float pp_dereverb_level = 0.3;
    00061
    00062 #define TYPE_SILENCE  0x2
    00063 #define TYPE_HIGH  0x0
    00064 #define TYPE_LOW   0x1
    00065 #define TYPE_MASK  0x3
    00066
    00067 #include "asterisk.h"
    00068
    00069 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 211526 $")
    00070
    00071 #include "asterisk/lock.h"
    00072 #include "asterisk/translate.h"
    00073 #include "asterisk/module.h"
    00074 #include "asterisk/config.h"
    00075 #include "asterisk/options.h"
    00076 #include "asterisk/logger.h"
    00077 #include "asterisk/channel.h"
    00078
    00079 /* Sample frame data */
    00080 #include "slin_speex_ex.h"
    00081 #include "speex_slin_ex.h"
    00082
    00083 AST_MUTEX_DEFINE_STATIC(localuser_lock);
    00084 static int localusecnt=0;
    00085
    00086 static char *tdesc = "Speex/PCM16 (signed linear) Codec Translator";
    00087
    00088 struct ast_translator_pvt {
    00089    void *speex;
    00090    struct ast_frame f;
    00091    SpeexBits bits;
    00092    int framesize;
    00093    /* Space to build offset */
    00094    char offset[AST_FRIENDLY_OFFSET];
    00095 #ifdef _SPEEX_TYPES_H
    00096    SpeexPreprocessState *pp;
    00097    /* Buffer for our outgoing frame */
    00098    spx_int16_t outbuf[8000];
    00099    /* Enough to store a full second */
    00100    spx_int16_t buf[8000];
    00101 #else
    00102    short outbuf[8000];
    00103    short buf[8000];
    00104 #endif
    00105
    00106    int tail;
    00107    int silent_state;
    00108 };
    00109
    00110 #define speex_coder_pvt ast_translator_pvt
    00111
    00112 static struct ast_translator_pvt *lintospeex_new(void)
    00113 {
    00114    struct speex_coder_pvt *tmp;
    00115    tmp = malloc(sizeof(struct speex_coder_pvt));
    00116    if (tmp) {
    00117       if (!(tmp->speex = speex_encoder_init(&speex_nb_mode))) {
    00118          free(tmp);
    00119          tmp = NULL;
    00120       } else {
    00121          speex_bits_init(&tmp->bits);
    00122          speex_bits_reset(&tmp->bits);
    00123          speex_encoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize);
    00124          speex_encoder_ctl(tmp->speex, SPEEX_SET_COMPLEXITY, &complexity);
    00125 #ifdef _SPEEX_TYPES_H
    00126          if (preproc) {
    00127             tmp->pp = speex_preprocess_state_init(tmp->framesize, 8000);
    00128             speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_VAD, &pp_vad);
    00129             speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_AGC, &pp_agc);
    00130             speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &pp_agc_level);
    00131             speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DENOISE, &pp_denoise);
    00132             speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB, &pp_dereverb);
    00133             speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &pp_dereverb_decay);
    00134             speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &pp_dereverb_level);
    00135          }
    00136 #endif
    00137          if (!abr && !vbr) {
    00138             speex_encoder_ctl(tmp->speex, SPEEX_SET_QUALITY, &quality);
    00139             if (vad)
    00140                speex_encoder_ctl(tmp->speex, SPEEX_SET_VAD, &vad);
    00141          }
    00142          if (vbr) {
    00143             speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR, &vbr);
    00144             speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR_QUALITY, &vbr_quality);
    00145          }
    00146          if (abr) {
    00147             speex_encoder_ctl(tmp->speex, SPEEX_SET_ABR, &abr);
    00148          }
    00149          if (dtx)
    00150             speex_encoder_ctl(tmp->speex, SPEEX_SET_DTX, &dtx);
    00151          tmp->tail = 0;
    00152          tmp->silent_state = 0;
    00153       }
    00154       localusecnt++;
    00155    }
    00156    return tmp;
    00157 }
    00158
    00159 static struct ast_translator_pvt *speextolin_new(void)
    00160 {
    00161    struct speex_coder_pvt *tmp;
    00162    tmp = malloc(sizeof(struct speex_coder_pvt));
    00163    if (tmp) {
    00164       if (!(tmp->speex = speex_decoder_init(&speex_nb_mode))) {
    00165          free(tmp);
    00166          tmp = NULL;
    00167       } else {
    00168          speex_bits_init(&tmp->bits);
    00169          speex_decoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize);
    00170          if (enhancement)
    00171             speex_decoder_ctl(tmp->speex, SPEEX_SET_ENH, &enhancement);
    00172          tmp->tail = 0;
    00173       }
    00174       localusecnt++;
    00175    }
    00176    return tmp;
    00177 }
    00178
    00179 static struct ast_frame *lintospeex_sample(void)
    00180 {
    00181    static struct ast_frame f;
    00182    f.frametype = AST_FRAME_VOICE;
    00183    f.subclass = AST_FORMAT_SLINEAR;
    00184    f.datalen = sizeof(slin_speex_ex);
    00185    /* Assume 8000 Hz */
    00186    f.samples = sizeof(slin_speex_ex)/2;
    00187    f.mallocd = 0;
    00188    f.offset = 0;
    00189    f.src = __PRETTY_FUNCTION__;
    00190    f.data = slin_speex_ex;
    00191    return &f;
    00192 }
    00193
    00194 static struct ast_frame *speextolin_sample(void)
    00195 {
    00196    static struct ast_frame f;
    00197    f.frametype = AST_FRAME_VOICE;
    00198    f.subclass = AST_FORMAT_SPEEX;
    00199    f.datalen = sizeof(speex_slin_ex);
    00200    /* All frames are 20 ms long */
    00201    f.samples = 160;
    00202    f.mallocd = 0;
    00203    f.offset = 0;
    00204    f.src = __PRETTY_FUNCTION__;
    00205    f.data = speex_slin_ex;
    00206    return &f;
    00207 }
    00208
    00209 static struct ast_frame *speextolin_frameout(struct ast_translator_pvt *tmp)
    00210 {
    00211    if (!tmp->tail)
    00212       return NULL;
    00213    /* Signed linear is no particular frame size, so just send whatever
    00214       we have in the buffer in one lump sum */
    00215    tmp->f.frametype = AST_FRAME_VOICE;
    00216    tmp->f.subclass = AST_FORMAT_SLINEAR;
    00217    tmp->f.datalen = tmp->tail * 2;
    00218    /* Assume 8000 Hz */
    00219    tmp->f.samples = tmp->tail;
    00220    tmp->f.mallocd = 0;
    00221    tmp->f.offset = AST_FRIENDLY_OFFSET;
    00222    tmp->f.src = __PRETTY_FUNCTION__;
    00223    tmp->f.data = tmp->buf;
    00224    /* Reset tail pointer */
    00225    tmp->tail = 0;
    00226    return &tmp->f;
    00227 }
    00228
    00229 static int speextolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
    00230 {
    00231    /* Assuming there's space left, decode into the current buffer at
    00232       the tail location.  Read in as many frames as there are */
    00233    int x;
    00234    int res;
    00235 #ifdef _SPEEX_TYPES_H
    00236    spx_int16_t out[1024];
    00237 #else
    00238    float fout[1024];
    00239 #endif
    00240
    00241    if (f->datalen == 0) {  /* Native PLC interpolation */
    00242       if (tmp->tail + tmp->framesize > sizeof(tmp->buf) / 2) {
    00243          ast_log(LOG_WARNING, "Out of buffer space\n");
    00244          return -1;
    00245       }
    00246 #ifdef _SPEEX_TYPES_H
    00247       speex_decode_int(tmp->speex, NULL, tmp->buf + tmp->tail);
    00248 #else
    00249       speex_decode(tmp->speex, NULL, fout);
    00250       for (x=0;x<tmp->framesize;x++) {
    00251          tmp->buf[tmp->tail + x] = fout[x];
    00252       }
    00253 #endif
    00254       tmp->tail += tmp->framesize;
    00255       return 0;
    00256    }
    00257
    00258    /* Read in bits */
    00259    speex_bits_read_from(&tmp->bits, f->data, f->datalen);
    00260    for(;;) {
    00261 #ifdef _SPEEX_TYPES_H
    00262       res = speex_decode_int(tmp->speex, &tmp->bits, out);
    00263 #else
    00264       res = speex_decode(tmp->speex, &tmp->bits, fout);
    00265 #endif
    00266       if (res < 0)
    00267          break;
    00268       if (tmp->tail + tmp->framesize < sizeof(tmp->buf) / 2) {
    00269          for (x=0;x<tmp->framesize;x++) {
    00270 #ifdef _SPEEX_TYPES_H
    00271             tmp->buf[tmp->tail + x] = out[x];
    00272 #else
    00273             tmp->buf[tmp->tail + x] = fout[x];
    00274 #endif
    00275          }
    00276          tmp->tail += tmp->framesize;
    00277       } else {
    00278          ast_log(LOG_WARNING, "Out of buffer space\n");
    00279          return -1;
    00280       }
    00281
    00282    }
    00283    return 0;
    00284 }
    00285
    00286 static int lintospeex_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
    00287 {
    00288    /* Just add the frames to our stream */
    00289    /* XXX We should look at how old the rest of our stream is, and if it
    00290       is too old, then we should overwrite it entirely, otherwise we can
    00291       get artifacts of earlier talk that do not belong */
    00292    if (tmp->tail + f->datalen/2 < sizeof(tmp->buf) / 2) {
    00293       memcpy((tmp->buf + tmp->tail), f->data, f->datalen);
    00294       tmp->tail += f->datalen/2;
    00295    } else {
    00296       ast_log(LOG_WARNING, "Out of buffer space\n");
    00297       return -1;
    00298    }
    00299    return 0;
    00300 }
    00301
    00302 static struct ast_frame *lintospeex_frameout(struct ast_translator_pvt *tmp)
    00303 {
    00304 #ifndef _SPEEX_TYPES_H
    00305    float fbuf[1024];
    00306    int x;
    00307 #endif
    00308    int len;
    00309    int y=0;
    00310    int is_speech=1;
    00311    /* We can't work on anything less than a frame in size */
    00312    if (tmp->tail < tmp->framesize)
    00313       return NULL;
    00314    tmp->f.frametype = AST_FRAME_VOICE;
    00315    tmp->f.subclass = AST_FORMAT_SPEEX;
    00316    tmp->f.mallocd = 0;
    00317    tmp->f.offset = AST_FRIENDLY_OFFSET;
    00318    tmp->f.src = __PRETTY_FUNCTION__;
    00319    tmp->f.data = tmp->outbuf;
    00320    speex_bits_reset(&tmp->bits);
    00321    while(tmp->tail >= tmp->framesize) {
    00322 #ifdef _SPEEX_TYPES_H
    00323       /* Preprocess audio */
    00324       if(preproc)
    00325          is_speech = speex_preprocess(tmp->pp, tmp->buf, NULL);
    00326       /* Encode a frame of data */
    00327       if (is_speech) {
    00328          /* If DTX enabled speex_encode returns 0 during silence */
    00329          is_speech = speex_encode_int(tmp->speex, tmp->buf, &tmp->bits) || !dtx;
    00330       } else {
    00331          /* 5 zeros interpreted by Speex as silence (submode 0) */
    00332          speex_bits_pack(&tmp->bits, 0, 5);
    00333       }
    00334 #else
    00335       /* Convert to floating point */
    00336       for (x=0;x<tmp->framesize;x++)
    00337          fbuf[x] = tmp->buf[x];
    00338       /* Encode a frame of data */
    00339       is_speech = speex_encode(tmp->speex, fbuf, &tmp->bits) || !dtx;
    00340 #endif
    00341       /* Assume 8000 Hz -- 20 ms */
    00342       tmp->tail -= tmp->framesize;
    00343       /* Move the data at the end of the buffer to the front */
    00344       if (tmp->tail)
    00345          memmove(tmp->buf, tmp->buf + tmp->framesize, tmp->tail * 2);
    00346       y++;
    00347    }
    00348
    00349    /* Use AST_FRAME_CNG to signify the start of any silence period */
    00350    if (!is_speech) {
    00351       if (tmp->silent_state) {
    00352          return NULL;
    00353       } else {
    00354          tmp->silent_state = 1;
    00355          speex_bits_reset(&tmp->bits);
    00356          tmp->f.frametype = AST_FRAME_CNG;
    00357       }
    00358    } else {
    00359       tmp->silent_state = 0;
    00360    }
    00361
    00362    /* Terminate bit stream */
    00363    speex_bits_pack(&tmp->bits, 15, 5);
    00364    len = speex_bits_write(&tmp->bits, (char *)tmp->outbuf, sizeof(tmp->outbuf));
    00365    tmp->f.datalen = len;
    00366    tmp->f.samples = y * 160;
    00367 #if 0
    00368    {
    00369       static int fd = -1;
    00370       if (fd < 0) {
    00371          fd = open("speex.raw", O_WRONLY|O_TRUNC|O_CREAT);
    00372          if (fd > -1) {
    00373             write(fd, tmp->f.data, tmp->f.datalen);
    00374             close(fd);
    00375          }
    00376       }
    00377    }
    00378 #endif
    00379    return &tmp->f;
    00380 }
    00381
    00382 static void speextolin_destroy(struct ast_translator_pvt *pvt)
    00383 {
    00384    speex_decoder_destroy(pvt->speex);
    00385    speex_bits_destroy(&pvt->bits);
    00386    free(pvt);
    00387    localusecnt--;
    00388 }
    00389
    00390 static void lintospeex_destroy(struct ast_translator_pvt *pvt)
    00391 {
    00392 #ifdef _SPEEX_TYPES_H
    00393    if (preproc)
    00394       speex_preprocess_state_destroy(pvt->pp);
    00395 #endif
    00396    speex_encoder_destroy(pvt->speex);
    00397    speex_bits_destroy(&pvt->bits);
    00398    free(pvt);
    00399    localusecnt--;
    00400 }
    00401
    00402 static struct ast_translator speextolin =
    00403    { "speextolin",
    00404       AST_FORMAT_SPEEX, AST_FORMAT_SLINEAR,
    00405       speextolin_new,
    00406       speextolin_framein,
    00407       speextolin_frameout,
    00408       speextolin_destroy,
    00409       speextolin_sample
    00410       };
    00411
    00412 static struct ast_translator lintospeex =
    00413    { "lintospeex",
    00414       AST_FORMAT_SLINEAR, AST_FORMAT_SPEEX,
    00415       lintospeex_new,
    00416       lintospeex_framein,
    00417       lintospeex_frameout,
    00418       lintospeex_destroy,
    00419       lintospeex_sample
    00420    };
    00421
    00422
    00423 static void parse_config(void)
    00424 {
    00425    struct ast_config *cfg;
    00426    struct ast_variable *var;
    00427    int res;
    00428    float res_f;
    00429
    00430    if ((cfg = ast_config_load("codecs.conf"))) {
    00431       if ((var = ast_variable_browse(cfg, "speex"))) {
    00432          while (var) {
    00433             if (!strcasecmp(var->name, "quality")) {
    00434                res = abs(atoi(var->value));
    00435                if (res > -1 && res < 11) {
    00436                   if (option_verbose > 2)
    00437                      ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting Quality to %d\n",res);
    00438                   ast_mutex_lock(&localuser_lock);
    00439                   quality = res;
    00440                   ast_mutex_unlock(&localuser_lock);
    00441                } else
    00442                   ast_log(LOG_ERROR,"Error Quality must be 0-10\n");
    00443             } else if (!strcasecmp(var->name, "complexity")) {
    00444                res = abs(atoi(var->value));
    00445                if (res > -1 && res < 11) {
    00446                   if (option_verbose > 2)
    00447                      ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting Complexity to %d\n",res);
    00448                   ast_mutex_lock(&localuser_lock);
    00449                   complexity = res;
    00450                   ast_mutex_unlock(&localuser_lock);
    00451                } else
    00452                   ast_log(LOG_ERROR,"Error! Complexity must be 0-10\n");
    00453             } else if (!strcasecmp(var->name, "vbr_quality")) {
    00454                if (sscanf(var->value, "%30f", &res_f) == 1 && res_f >= 0 && res_f <= 10) {
    00455                   if (option_verbose > 2)
    00456                      ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting VBR Quality to %f\n",res_f);
    00457                   ast_mutex_lock(&localuser_lock);
    00458                   vbr_quality = res_f;
    00459                   ast_mutex_unlock(&localuser_lock);
    00460                } else
    00461                   ast_log(LOG_ERROR,"Error! VBR Quality must be 0-10\n");
    00462             } else if (!strcasecmp(var->name, "abr_quality")) {
    00463                ast_log(LOG_ERROR,"Error! ABR Quality setting obsolete, set ABR to desired bitrate\n");
    00464             } else if (!strcasecmp(var->name, "enhancement")) {
    00465                ast_mutex_lock(&localuser_lock);
    00466                enhancement = ast_true(var->value) ? 1 : 0;
    00467                if (option_verbose > 2)
    00468                   ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Perceptual Enhancement Mode. [%s]\n",enhancement ? "on" : "off");
    00469                ast_mutex_unlock(&localuser_lock);
    00470             } else if (!strcasecmp(var->name, "vbr")) {
    00471                ast_mutex_lock(&localuser_lock);
    00472                vbr = ast_true(var->value) ? 1 : 0;
    00473                if (option_verbose > 2)
    00474                   ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: VBR Mode. [%s]\n",vbr ? "on" : "off");
    00475                ast_mutex_unlock(&localuser_lock);
    00476             } else if (!strcasecmp(var->name, "abr")) {
    00477                res = abs(atoi(var->value));
    00478                if (res >= 0) {
    00479                   if (option_verbose > 2) {
    00480                      if (res > 0)
    00481                         ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting ABR target bitrate to %d\n",res);
    00482                      else
    00483                         ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Disabling ABR\n");
    00484                   }
    00485                   ast_mutex_lock(&localuser_lock);
    00486                   abr = res;
    00487                   ast_mutex_unlock(&localuser_lock);
    00488                } else
    00489                   ast_log(LOG_ERROR,"Error! ABR target bitrate must be >= 0\n");
    00490             } else if (!strcasecmp(var->name, "vad")) {
    00491                ast_mutex_lock(&localuser_lock);
    00492                vad = ast_true(var->value) ? 1 : 0;
    00493                if (option_verbose > 2)
    00494                   ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: VAD Mode. [%s]\n",vad ? "on" : "off");
    00495                ast_mutex_unlock(&localuser_lock);
    00496             } else if (!strcasecmp(var->name, "dtx")) {
    00497                ast_mutex_lock(&localuser_lock);
    00498                dtx = ast_true(var->value) ? 1 : 0;
    00499                if (option_verbose > 2)
    00500                   ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: DTX Mode. [%s]\n",dtx ? "on" : "off");
    00501                ast_mutex_unlock(&localuser_lock);
    00502             } else if (!strcasecmp(var->name, "preprocess")) {
    00503                ast_mutex_lock(&localuser_lock);
    00504                preproc = ast_true(var->value) ? 1 : 0;
    00505                if (option_verbose > 2)
    00506                   ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessing. [%s]\n",preproc ? "on" : "off");
    00507                ast_mutex_unlock(&localuser_lock);
    00508             } else if (!strcasecmp(var->name, "pp_vad")) {
    00509                ast_mutex_lock(&localuser_lock);
    00510                pp_vad = ast_true(var->value) ? 1 : 0;
    00511                if (option_verbose > 2)
    00512                   ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor VAD. [%s]\n",pp_vad ? "on" : "off");
    00513                ast_mutex_unlock(&localuser_lock);
    00514             } else if (!strcasecmp(var->name, "pp_agc")) {
    00515                ast_mutex_lock(&localuser_lock);
    00516                pp_agc = ast_true(var->value) ? 1 : 0;
    00517                if (option_verbose > 2)
    00518                   ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor AGC. [%s]\n",pp_agc ? "on" : "off");
    00519                ast_mutex_unlock(&localuser_lock);
    00520             } else if (!strcasecmp(var->name, "pp_agc_level")) {
    00521                if (sscanf(var->value, "%30f", &res_f) == 1 && res_f >= 0) {
    00522                   if (option_verbose > 2)
    00523                      ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting preprocessor AGC Level to %f\n",res_f);
    00524                   ast_mutex_lock(&localuser_lock);
    00525                   pp_agc_level = res_f;
    00526                   ast_mutex_unlock(&localuser_lock);
    00527                } else
    00528                   ast_log(LOG_ERROR,"Error! Preprocessor AGC Level must be >= 0\n");
    00529             } else if (!strcasecmp(var->name, "pp_denoise")) {
    00530                ast_mutex_lock(&localuser_lock);
    00531                pp_denoise = ast_true(var->value) ? 1 : 0;
    00532                if (option_verbose > 2)
    00533                   ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor Denoise. [%s]\n",pp_denoise ? "on" : "off");
    00534                ast_mutex_unlock(&localuser_lock);
    00535             } else if (!strcasecmp(var->name, "pp_dereverb")) {
    00536                ast_mutex_lock(&localuser_lock);
    00537                pp_dereverb = ast_true(var->value) ? 1 : 0;
    00538                if (option_verbose > 2)
    00539                   ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor Dereverb. [%s]\n",pp_dereverb ? "on" : "off");
    00540                ast_mutex_unlock(&localuser_lock);
    00541             } else if (!strcasecmp(var->name, "pp_dereverb_decay")) {
    00542                if (sscanf(var->value, "%30f", &res_f) == 1 && res_f >= 0) {
    00543                   if (option_verbose > 2)
    00544                      ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting preprocessor Dereverb Decay to %f\n",res_f);
    00545                   ast_mutex_lock(&localuser_lock);
    00546                   pp_dereverb_decay = res_f;
    00547                   ast_mutex_unlock(&localuser_lock);
    00548                } else
    00549                   ast_log(LOG_ERROR,"Error! Preprocessor Dereverb Decay must be >= 0\n");
    00550             } else if (!strcasecmp(var->name, "pp_dereverb_level")) {
    00551                if (sscanf(var->value, "%30f", &res_f) == 1 && res_f >= 0) {
    00552                   if (option_verbose > 2)
    00553                      ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting preprocessor Dereverb Level to %f\n",res_f);
    00554                   ast_mutex_lock(&localuser_lock);
    00555                   pp_dereverb_level = res_f;
    00556                   ast_mutex_unlock(&localuser_lock);
    00557                } else
    00558                   ast_log(LOG_ERROR,"Error! Preprocessor Dereverb Level must be >= 0\n");
    00559             }
    00560             var = var->next;
    00561          }
    00562       }
    00563       ast_config_destroy(cfg);
    00564    }
    00565 }
    00566
    00567 int reload(void)
    00568 {
    00569    parse_config();
    00570    return 0;
    00571 }
    00572
    00573 int unload_module(void)
    00574 {
    00575    int res;
    00576    ast_mutex_lock(&localuser_lock);
    00577    res = ast_unregister_translator(&lintospeex);
    00578    if (!res)
    00579       res = ast_unregister_translator(&speextolin);
    00580    if (localusecnt)
    00581       res = -1;
    00582    ast_mutex_unlock(&localuser_lock);
    00583    return res;
    00584 }
    00585
    00586 int load_module(void)
    00587 {
    00588    int res;
    00589    parse_config();
    00590    res=ast_register_translator(&speextolin);
    00591    if (!res)
    00592       res=ast_register_translator(&lintospeex);
    00593    else
    00594       ast_unregister_translator(&speextolin);
    00595    return res;
    00596 }
    00597
    00598 char *description(void)
    00599 {
    00600    return tdesc;
    00601 }
    00602
    00603 int usecount(void)
    00604 {
    00605    int res;
    00606    STANDARD_USECOUNT(res);
    00607    return res;
    00608 }
    00609
    00610 char *key()
    00611 {
    00612    return ASTERISK_GPL_KEY;
    00613 }