Fri Sep 29 11:12:29 2006

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: 7221 $")
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, "%f", &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, "%f", &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, "%f", &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, "%f", &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 }

Generated on Fri Sep 29 11:12:29 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7