Fri Jul 24 00:41:45 2009

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"

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 = "a9c98e5d177805051735cb5b0b16b0a0" , .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 351 of file func_speex.c.

static void __unreg_module ( void   )  [static]

Definition at line 351 of file func_speex.c.

static void destroy_callback ( void *  data  )  [static]

Definition at line 64 of file func_speex.c.

References ast_audiohook_destroy(), ast_free, and si.

00065 {
00066    struct speex_info *si = data;
00067 
00068    ast_audiohook_destroy(&si->audiohook);
00069 
00070    if (si->rx && si->rx->state) {
00071       speex_preprocess_state_destroy(si->rx->state);
00072    }
00073 
00074    if (si->tx && si->tx->state) {
00075       speex_preprocess_state_destroy(si->tx->state);
00076    }
00077 
00078    if (si->rx) {
00079       ast_free(si->rx);
00080    }
00081 
00082    if (si->tx) {
00083       ast_free(si->tx);
00084    }
00085 
00086    ast_free(data);
00087 };

static int load_module ( void   )  [static]

Definition at line 337 of file func_speex.c.

References agc_function, ast_custom_function_register, ast_custom_function_unregister(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, and denoise_function.

00338 {
00339    if (ast_custom_function_register(&agc_function)) {
00340       return AST_MODULE_LOAD_DECLINE;
00341    }
00342 
00343    if (ast_custom_function_register(&denoise_function)) {
00344       ast_custom_function_unregister(&agc_function);
00345       return AST_MODULE_LOAD_DECLINE;
00346    }
00347 
00348    return AST_MODULE_LOAD_SUCCESS;
00349 }

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 94 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_channel_lock, ast_channel_unlock, AST_FRAME_VOICE, speex_info::audiohook, chan, ast_frame::data, ast_datastore::data, speex_direction_info::denoise, ast_frame::frametype, ast_frame::ptr, ast_frame::samples, speex_direction_info::samples, si, speex_datastore, speex_direction_info::state, and ast_audiohook::status.

Referenced by speex_write().

00095 {
00096    struct ast_datastore *datastore = NULL;
00097    struct speex_direction_info *sdi = NULL;
00098    struct speex_info *si = NULL;
00099 
00100    /* If the audiohook is stopping it means the channel is shutting down.... but we let the datastore destroy take care of it */
00101    if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE || frame->frametype != AST_FRAME_VOICE) {
00102       return 0;
00103    }
00104    
00105    ast_channel_lock(chan);
00106    if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) {
00107       ast_channel_unlock(chan);
00108       return 0;
00109    }
00110    ast_channel_unlock(chan);
00111 
00112    si = datastore->data;
00113 
00114    sdi = (direction == AST_AUDIOHOOK_DIRECTION_READ) ? si->rx : si->tx;
00115 
00116    if (!sdi) {
00117       return 0;
00118    }
00119 
00120    if (sdi->samples != frame->samples) {
00121       if (sdi->state) {
00122          speex_preprocess_state_destroy(sdi->state);
00123       }
00124 
00125       if (!(sdi->state = speex_preprocess_state_init((sdi->samples = frame->samples), 8000))) {
00126          return -1;
00127       }
00128       
00129       speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_AGC, &sdi->agc);
00130 
00131       if (sdi->agc) {
00132          speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_AGC_LEVEL, &sdi->agclevel);
00133       }
00134 
00135       speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_DENOISE, &sdi->denoise);
00136    }
00137 
00138    speex_preprocess(sdi->state, frame->data.ptr, NULL);
00139 
00140    return 0;
00141 }

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

Definition at line 254 of file func_speex.c.

References speex_direction_info::agclevel, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_log(), chan, ast_datastore::data, speex_direction_info::denoise, LOG_ERROR, si, and speex_datastore.

00255 {
00256    struct ast_datastore *datastore = NULL;
00257    struct speex_info *si = NULL;
00258    struct speex_direction_info *sdi = NULL;
00259 
00260    if (!chan) {
00261       ast_log(LOG_ERROR, "%s cannot be used without a channel!\n", cmd);
00262       return -1;
00263    }
00264 
00265    ast_channel_lock(chan);
00266    if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) {
00267       ast_channel_unlock(chan);
00268       return -1;
00269    }
00270    ast_channel_unlock(chan);
00271 
00272    si = datastore->data;
00273 
00274    if (!strcasecmp(data, "tx"))
00275       sdi = si->tx;
00276    else if (!strcasecmp(data, "rx"))
00277       sdi = si->rx;
00278    else {
00279       ast_log(LOG_ERROR, "%s(%s) must either \"tx\" or \"rx\"\n", cmd, data);
00280       return -1;
00281    }
00282 
00283    if (!strcasecmp(cmd, "agc"))
00284       snprintf(buf, len, "%.01f", sdi ? sdi->agclevel : 0.0);
00285    else
00286       snprintf(buf, len, "%d", sdi ? sdi->denoise : 0);
00287 
00288    return 0;
00289 }

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

Definition at line 143 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(), chan, ast_datastore::data, DEFAULT_AGC_LEVEL, LOG_ERROR, LOG_WARNING, si, speex_callback(), and speex_datastore.

00144 {
00145    struct ast_datastore *datastore = NULL;
00146    struct speex_info *si = NULL;
00147    struct speex_direction_info **sdi = NULL;
00148    int is_new = 0;
00149 
00150    ast_channel_lock(chan);
00151    if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) {
00152       ast_channel_unlock(chan);
00153 
00154       if (!(datastore = ast_datastore_alloc(&speex_datastore, NULL))) {
00155          return 0;
00156       }
00157 
00158       if (!(si = ast_calloc(1, sizeof(*si)))) {
00159          ast_datastore_free(datastore);
00160          return 0;
00161       }
00162 
00163       ast_audiohook_init(&si->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "speex");
00164       si->audiohook.manipulate_callback = speex_callback;
00165 
00166       is_new = 1;
00167    } else {
00168       ast_channel_unlock(chan);
00169       si = datastore->data;
00170    }
00171 
00172    if (!strcasecmp(data, "rx")) {
00173       sdi = &si->rx;
00174    } else if (!strcasecmp(data, "tx")) {
00175       sdi = &si->tx;
00176    } else {
00177       ast_log(LOG_ERROR, "Invalid argument provided to the %s function\n", cmd);
00178 
00179       if (is_new) {
00180          ast_datastore_free(datastore);
00181          return -1;
00182       }
00183    }
00184 
00185    if (!*sdi) {
00186       if (!(*sdi = ast_calloc(1, sizeof(**sdi)))) {
00187          return 0;
00188       }
00189       /* Right now, the audiohooks API will _only_ provide us 8 kHz slinear
00190        * audio.  When it supports 16 kHz (or any other sample rates, we will
00191        * have to take that into account here. */
00192       (*sdi)->samples = -1;
00193    }
00194 
00195    if (!strcasecmp(cmd, "agc")) {
00196       if (!sscanf(value, "%f", &(*sdi)->agclevel))
00197          (*sdi)->agclevel = ast_true(value) ? DEFAULT_AGC_LEVEL : 0.0;
00198    
00199       if ((*sdi)->agclevel > 32768.0) {
00200          ast_log(LOG_WARNING, "AGC(%s)=%.01f is greater than 32768... setting to 32768 instead\n", 
00201                ((*sdi == si->rx) ? "rx" : "tx"), (*sdi)->agclevel);
00202          (*sdi)->agclevel = 32768.0;
00203       }
00204    
00205       (*sdi)->agc = !!((*sdi)->agclevel);
00206 
00207       if ((*sdi)->state) {
00208          speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_AGC, &(*sdi)->agc);
00209          if ((*sdi)->agc) {
00210             speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_AGC_LEVEL, &(*sdi)->agclevel);
00211          }
00212       }
00213    } else if (!strcasecmp(cmd, "denoise")) {
00214       (*sdi)->denoise = (ast_true(value) != 0);
00215 
00216       if ((*sdi)->state) {
00217          speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_DENOISE, &(*sdi)->denoise);
00218       }
00219    }
00220 
00221    if (!(*sdi)->agc && !(*sdi)->denoise) {
00222       if ((*sdi)->state)
00223          speex_preprocess_state_destroy((*sdi)->state);
00224 
00225       ast_free(*sdi);
00226       *sdi = NULL;
00227    }
00228 
00229    if (!si->rx && !si->tx) {
00230       if (is_new) {
00231          is_new = 0;
00232       } else {
00233          ast_channel_lock(chan);
00234          ast_channel_datastore_remove(chan, datastore);
00235          ast_channel_unlock(chan);
00236          ast_audiohook_remove(chan, &si->audiohook);
00237          ast_audiohook_detach(&si->audiohook);
00238       }
00239       
00240       ast_datastore_free(datastore);
00241    }
00242 
00243    if (is_new) { 
00244       datastore->data = si;
00245       ast_channel_lock(chan);
00246       ast_channel_datastore_add(chan, datastore);
00247       ast_channel_unlock(chan);
00248       ast_audiohook_attach(chan, &si->audiohook);
00249    }
00250 
00251    return 0;
00252 }

static int unload_module ( void   )  [static]

Definition at line 330 of file func_speex.c.

References agc_function, ast_custom_function_unregister(), and denoise_function.


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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } [static]

Definition at line 351 of file func_speex.c.

struct ast_custom_function agc_function [static]

Definition at line 291 of file func_speex.c.

Referenced by load_module(), and unload_module().

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 351 of file func_speex.c.

struct ast_custom_function denoise_function [static]

Definition at line 311 of file func_speex.c.

Referenced by load_module(), and unload_module().

struct ast_datastore_info speex_datastore [static]

Initial value:

 {
   .type = "speex",
   .destroy = destroy_callback
}

Definition at line 89 of file func_speex.c.

Referenced by speex_callback(), speex_read(), and speex_write().


Generated on Fri Jul 24 00:41:45 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7