Mon Jun 27 16:51:14 2011

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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 50 of file func_speex.c.

Referenced by speex_write().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 378 of file func_speex.c.

static void __unreg_module ( void   )  [static]

Definition at line 378 of file func_speex.c.

static void destroy_callback ( void *  data  )  [static]

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

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

static int load_module ( void   )  [static]

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

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

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 141 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().

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

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

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

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

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

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

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

static int unload_module ( void   )  [static]

Definition at line 357 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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 378 of file func_speex.c.

struct ast_custom_function agc_function [static]

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

struct ast_custom_function denoise_function [static]

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

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


Generated on Mon Jun 27 16:51:14 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7