Mon Oct 8 12:39:23 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 = "ac1f6a56484a8820659555499174e588" , .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 377 of file func_speex.c.

static void __unreg_module ( void   )  [static]

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

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

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 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, speex_datastore, 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 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_direction_info::samples, 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    if (strcasecmp(data, "rx") && strcasecmp(data, "tx")) {
00204       ast_log(LOG_ERROR, "Invalid argument provided to the %s function\n", cmd);
00205       return -1;
00206    }
00207 
00208    ast_channel_lock(chan);
00209    if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) {
00210       ast_channel_unlock(chan);
00211 
00212       if (!(datastore = ast_datastore_alloc(&speex_datastore, NULL))) {
00213          return 0;
00214       }
00215 
00216       if (!(si = ast_calloc(1, sizeof(*si)))) {
00217          ast_datastore_free(datastore);
00218          return 0;
00219       }
00220 
00221       ast_audiohook_init(&si->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "speex");
00222       si->audiohook.manipulate_callback = speex_callback;
00223 
00224       is_new = 1;
00225    } else {
00226       ast_channel_unlock(chan);
00227       si = datastore->data;
00228    }
00229 
00230    if (!strcasecmp(data, "rx")) {
00231       sdi = &si->rx;
00232    } else {
00233       sdi = &si->tx;
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 356 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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 377 of file func_speex.c.

struct ast_custom_function agc_function [static]

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

struct ast_custom_function denoise_function [static]

Definition at line 349 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 Mon Oct 8 12:39:23 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7