Wed Aug 18 22:34:24 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"

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 356 of file func_speex.c.

static void __unreg_module ( void   )  [static]

Definition at line 356 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 342 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.

00343 {
00344    if (ast_custom_function_register(&agc_function)) {
00345       return AST_MODULE_LOAD_DECLINE;
00346    }
00347 
00348    if (ast_custom_function_register(&denoise_function)) {
00349       ast_custom_function_unregister(&agc_function);
00350       return AST_MODULE_LOAD_DECLINE;
00351    }
00352 
00353    return AST_MODULE_LOAD_SUCCESS;
00354 }

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_FRAME_VOICE, ast_free, AST_MALLOCD_SRC, ast_strdup, speex_info::audiohook, chan, ast_frame::data, ast_datastore::data, speex_direction_info::denoise, ast_frame::frametype, ast_frame::mallocd, ast_frame::ptr, ast_frame::samples, speex_direction_info::samples, si, speex_datastore, ast_frame::src, 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    char source[80];
00100 
00101    /* If the audiohook is stopping it means the channel is shutting down.... but we let the datastore destroy take care of it */
00102    if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE || frame->frametype != AST_FRAME_VOICE) {
00103       return -1;
00104    }
00105 
00106    /* We are called with chan already locked */
00107    if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) {
00108       return -1;
00109    }
00110 
00111    si = datastore->data;
00112 
00113    sdi = (direction == AST_AUDIOHOOK_DIRECTION_READ) ? si->rx : si->tx;
00114 
00115    if (!sdi) {
00116       return -1;
00117    }
00118 
00119    if (sdi->samples != frame->samples) {
00120       if (sdi->state) {
00121          speex_preprocess_state_destroy(sdi->state);
00122       }
00123 
00124       if (!(sdi->state = speex_preprocess_state_init((sdi->samples = frame->samples), 8000))) {
00125          return -1;
00126       }
00127 
00128       speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_AGC, &sdi->agc);
00129 
00130       if (sdi->agc) {
00131          speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_AGC_LEVEL, &sdi->agclevel);
00132       }
00133 
00134       speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_DENOISE, &sdi->denoise);
00135    }
00136 
00137    speex_preprocess(sdi->state, frame->data.ptr, NULL);
00138    snprintf(source, sizeof(source), "%s/speex", frame->src);
00139    if (frame->mallocd & AST_MALLOCD_SRC) {
00140       ast_free((char *) frame->src);
00141    }
00142    frame->src = ast_strdup(source);
00143    frame->mallocd |= AST_MALLOCD_SRC;
00144 
00145    return 0;
00146 }

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

Definition at line 259 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.

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

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

Definition at line 148 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.

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

static int unload_module ( void   )  [static]

Definition at line 335 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 356 of file func_speex.c.

struct ast_custom_function agc_function [static]

Definition at line 296 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 356 of file func_speex.c.

struct ast_custom_function denoise_function [static]

Definition at line 316 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 Wed Aug 18 22:34:24 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7