Fri Nov 12 12:03:18 2010

Asterisk developer's documentation


func_speex.c File Reference

Noise reduction and automatic gain control (AGC). More...

#include "asterisk.h"
#include <speex/speex_preprocess.h>
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/audiohook.h"
Include dependency graph for func_speex.c:

Go to the source code of this file.

Data Structures

struct  speex_direction_info
struct  speex_info

Defines

#define DEFAULT_AGC_LEVEL   8000.0

Functions

static void __reg_module (void)
static void __unreg_module (void)
static void destroy_callback (void *data)
static int load_module (void)
static int speex_callback (struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction)
static int speex_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int speex_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Noise reduction and Automatic Gain Control (AGC)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, }
static struct ast_custom_function agc_function
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_custom_function denoise_function
static struct ast_datastore_info speex_datastore

Detailed Description

Noise reduction and automatic gain control (AGC).

Author:
Brian Degenhardt <bmd@digium.com>
Brett Bryant <bbryant@digium.com>
ExtRef:
The Speex library - http://www.speex.org

Definition in file func_speex.c.


Define Documentation

#define DEFAULT_AGC_LEVEL   8000.0

Definition at line 49 of file func_speex.c.

Referenced by speex_write().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 375 of file func_speex.c.

static void __unreg_module ( void   )  [static]

Definition at line 375 of file func_speex.c.

static void destroy_callback ( void *  data  )  [static]

Definition at line 110 of file func_speex.c.

References ast_audiohook_destroy(), ast_free, speex_info::audiohook, speex_info::rx, speex_direction_info::state, and speex_info::tx.

00111 {
00112    struct speex_info *si = data;
00113 
00114    ast_audiohook_destroy(&si->audiohook);
00115 
00116    if (si->rx && si->rx->state) {
00117       speex_preprocess_state_destroy(si->rx->state);
00118    }
00119 
00120    if (si->tx && si->tx->state) {
00121       speex_preprocess_state_destroy(si->tx->state);
00122    }
00123 
00124    if (si->rx) {
00125       ast_free(si->rx);
00126    }
00127 
00128    if (si->tx) {
00129       ast_free(si->tx);
00130    }
00131 
00132    ast_free(data);
00133 };

static int load_module ( void   )  [static]
static int speex_callback ( struct ast_audiohook audiohook,
struct ast_channel chan,
struct ast_frame frame,
enum ast_audiohook_direction  direction 
) [static]

Definition at line 140 of file func_speex.c.

References speex_direction_info::agc, speex_direction_info::agclevel, AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_STATUS_DONE, ast_channel_datastore_find(), AST_FRAME_VOICE, ast_free, AST_MALLOCD_SRC, ast_strdup, ast_frame::data, ast_datastore::data, speex_direction_info::denoise, ast_frame::frametype, ast_frame::mallocd, ast_frame::ptr, speex_info::rx, ast_frame::samples, speex_direction_info::samples, ast_frame::src, speex_direction_info::state, ast_audiohook::status, and speex_info::tx.

Referenced by speex_write().

00141 {
00142    struct ast_datastore *datastore = NULL;
00143    struct speex_direction_info *sdi = NULL;
00144    struct speex_info *si = NULL;
00145    char source[80];
00146 
00147    /* If the audiohook is stopping it means the channel is shutting down.... but we let the datastore destroy take care of it */
00148    if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE || frame->frametype != AST_FRAME_VOICE) {
00149       return -1;
00150    }
00151 
00152    /* We are called with chan already locked */
00153    if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) {
00154       return -1;
00155    }
00156 
00157    si = datastore->data;
00158 
00159    sdi = (direction == AST_AUDIOHOOK_DIRECTION_READ) ? si->rx : si->tx;
00160 
00161    if (!sdi) {
00162       return -1;
00163    }
00164 
00165    if (sdi->samples != frame->samples) {
00166       if (sdi->state) {
00167          speex_preprocess_state_destroy(sdi->state);
00168       }
00169 
00170       if (!(sdi->state = speex_preprocess_state_init((sdi->samples = frame->samples), 8000))) {
00171          return -1;
00172       }
00173 
00174       speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_AGC, &sdi->agc);
00175 
00176       if (sdi->agc) {
00177          speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_AGC_LEVEL, &sdi->agclevel);
00178       }
00179 
00180       speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_DENOISE, &sdi->denoise);
00181    }
00182 
00183    speex_preprocess(sdi->state, frame->data.ptr, NULL);
00184    snprintf(source, sizeof(source), "%s/speex", frame->src);
00185    if (frame->mallocd & AST_MALLOCD_SRC) {
00186       ast_free((char *) frame->src);
00187    }
00188    frame->src = ast_strdup(source);
00189    frame->mallocd |= AST_MALLOCD_SRC;
00190 
00191    return 0;
00192 }

static int speex_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 305 of file func_speex.c.

References speex_direction_info::agclevel, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_log(), ast_datastore::data, speex_direction_info::denoise, LOG_ERROR, speex_info::rx, and speex_info::tx.

00306 {
00307    struct ast_datastore *datastore = NULL;
00308    struct speex_info *si = NULL;
00309    struct speex_direction_info *sdi = NULL;
00310 
00311    if (!chan) {
00312       ast_log(LOG_ERROR, "%s cannot be used without a channel!\n", cmd);
00313       return -1;
00314    }
00315 
00316    ast_channel_lock(chan);
00317    if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) {
00318       ast_channel_unlock(chan);
00319       return -1;
00320    }
00321    ast_channel_unlock(chan);
00322 
00323    si = datastore->data;
00324 
00325    if (!strcasecmp(data, "tx"))
00326       sdi = si->tx;
00327    else if (!strcasecmp(data, "rx"))
00328       sdi = si->rx;
00329    else {
00330       ast_log(LOG_ERROR, "%s(%s) must either \"tx\" or \"rx\"\n", cmd, data);
00331       return -1;
00332    }
00333 
00334    if (!strcasecmp(cmd, "agc"))
00335       snprintf(buf, len, "%.01f", sdi ? sdi->agclevel : 0.0);
00336    else
00337       snprintf(buf, len, "%d", sdi ? sdi->denoise : 0);
00338 
00339    return 0;
00340 }

static int speex_write ( struct ast_channel chan,
const char *  cmd,
char *  data,
const char *  value 
) [static]

Definition at line 194 of file func_speex.c.

References ast_audiohook_attach(), ast_audiohook_detach(), ast_audiohook_init(), ast_audiohook_remove(), AST_AUDIOHOOK_TYPE_MANIPULATE, ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_datastore_free(), ast_free, ast_log(), ast_true(), speex_info::audiohook, ast_datastore::data, DEFAULT_AGC_LEVEL, LOG_ERROR, LOG_WARNING, ast_audiohook::manipulate_callback, speex_info::rx, speex_callback(), and speex_info::tx.

00195 {
00196    struct ast_datastore *datastore = NULL;
00197    struct speex_info *si = NULL;
00198    struct speex_direction_info **sdi = NULL;
00199    int is_new = 0;
00200 
00201    ast_channel_lock(chan);
00202    if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) {
00203       ast_channel_unlock(chan);
00204 
00205       if (!(datastore = ast_datastore_alloc(&speex_datastore, NULL))) {
00206          return 0;
00207       }
00208 
00209       if (!(si = ast_calloc(1, sizeof(*si)))) {
00210          ast_datastore_free(datastore);
00211          return 0;
00212       }
00213 
00214       ast_audiohook_init(&si->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "speex");
00215       si->audiohook.manipulate_callback = speex_callback;
00216 
00217       is_new = 1;
00218    } else {
00219       ast_channel_unlock(chan);
00220       si = datastore->data;
00221    }
00222 
00223    if (!strcasecmp(data, "rx")) {
00224       sdi = &si->rx;
00225    } else if (!strcasecmp(data, "tx")) {
00226       sdi = &si->tx;
00227    } else {
00228       ast_log(LOG_ERROR, "Invalid argument provided to the %s function\n", cmd);
00229 
00230       if (is_new) {
00231          ast_datastore_free(datastore);
00232          return -1;
00233       }
00234    }
00235 
00236    if (!*sdi) {
00237       if (!(*sdi = ast_calloc(1, sizeof(**sdi)))) {
00238          return 0;
00239       }
00240       /* Right now, the audiohooks API will _only_ provide us 8 kHz slinear
00241        * audio.  When it supports 16 kHz (or any other sample rates, we will
00242        * have to take that into account here. */
00243       (*sdi)->samples = -1;
00244    }
00245 
00246    if (!strcasecmp(cmd, "agc")) {
00247       if (!sscanf(value, "%30f", &(*sdi)->agclevel))
00248          (*sdi)->agclevel = ast_true(value) ? DEFAULT_AGC_LEVEL : 0.0;
00249    
00250       if ((*sdi)->agclevel > 32768.0) {
00251          ast_log(LOG_WARNING, "AGC(%s)=%.01f is greater than 32768... setting to 32768 instead\n", 
00252                ((*sdi == si->rx) ? "rx" : "tx"), (*sdi)->agclevel);
00253          (*sdi)->agclevel = 32768.0;
00254       }
00255    
00256       (*sdi)->agc = !!((*sdi)->agclevel);
00257 
00258       if ((*sdi)->state) {
00259          speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_AGC, &(*sdi)->agc);
00260          if ((*sdi)->agc) {
00261             speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_AGC_LEVEL, &(*sdi)->agclevel);
00262          }
00263       }
00264    } else if (!strcasecmp(cmd, "denoise")) {
00265       (*sdi)->denoise = (ast_true(value) != 0);
00266 
00267       if ((*sdi)->state) {
00268          speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_DENOISE, &(*sdi)->denoise);
00269       }
00270    }
00271 
00272    if (!(*sdi)->agc && !(*sdi)->denoise) {
00273       if ((*sdi)->state)
00274          speex_preprocess_state_destroy((*sdi)->state);
00275 
00276       ast_free(*sdi);
00277       *sdi = NULL;
00278    }
00279 
00280    if (!si->rx && !si->tx) {
00281       if (is_new) {
00282          is_new = 0;
00283       } else {
00284          ast_channel_lock(chan);
00285          ast_channel_datastore_remove(chan, datastore);
00286          ast_channel_unlock(chan);
00287          ast_audiohook_remove(chan, &si->audiohook);
00288          ast_audiohook_detach(&si->audiohook);
00289       }
00290       
00291       ast_datastore_free(datastore);
00292    }
00293 
00294    if (is_new) { 
00295       datastore->data = si;
00296       ast_channel_lock(chan);
00297       ast_channel_datastore_add(chan, datastore);
00298       ast_channel_unlock(chan);
00299       ast_audiohook_attach(chan, &si->audiohook);
00300    }
00301 
00302    return 0;
00303 }

static int unload_module ( void   )  [static]

Definition at line 354 of file func_speex.c.

References ast_custom_function_unregister().


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Noise reduction and Automatic Gain Control (AGC)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, } [static]

Definition at line 375 of file func_speex.c.

Initial value:
 {
   .name = "AGC",
   .write = speex_write,
   .read = speex_read
}

Definition at line 342 of file func_speex.c.

Definition at line 375 of file func_speex.c.

Initial value:
 {
   .name = "DENOISE",
   .write = speex_write,
   .read = speex_read
}

Definition at line 348 of file func_speex.c.

Initial value:
 {
   .type = "speex",
   .destroy = destroy_callback
}

Definition at line 135 of file func_speex.c.


Generated by  doxygen 1.6.2