Sat Mar 10 01:55:26 2012

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_LOAD_ORDER , .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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
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 1.2 library - http://www.speex.org
Note:
Requires the 1.2 version of the Speex library (which might not be what you find in Linux packages)

Definition in file func_speex.c.


Define Documentation

#define DEFAULT_AGC_LEVEL   8000.0

Definition at line 51 of file func_speex.c.

Referenced by speex_write().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 379 of file func_speex.c.

static void __unreg_module ( void   )  [static]

Definition at line 379 of file func_speex.c.

static void destroy_callback ( void *  data  )  [static]

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

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

static int load_module ( void   )  [static]

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

00366 {
00367    if (ast_custom_function_register(&agc_function)) {
00368       return AST_MODULE_LOAD_DECLINE;
00369    }
00370 
00371    if (ast_custom_function_register(&denoise_function)) {
00372       ast_custom_function_unregister(&agc_function);
00373       return AST_MODULE_LOAD_DECLINE;
00374    }
00375 
00376    return AST_MODULE_LOAD_SUCCESS;
00377 }

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 142 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, 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, speex_datastore, ast_frame::src, speex_direction_info::state, ast_audiohook::status, and speex_info::tx.

Referenced by speex_write().

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

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

Definition at line 307 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, speex_datastore, and speex_info::tx.

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

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

Definition at line 196 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, speex_info::rx, speex_callback(), speex_datastore, and speex_info::tx.

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

static int unload_module ( void   )  [static]

Definition at line 358 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_LOAD_ORDER , .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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 379 of file func_speex.c.

struct ast_custom_function agc_function [static]

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

struct ast_custom_function denoise_function [static]

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

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


Generated on Sat Mar 10 01:55:26 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7