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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } |
| static struct ast_custom_function | agc_function |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct ast_custom_function | denoise_function |
| static struct ast_datastore_info | speex_datastore |
Noise reduction and automatic gain control (AGC)
Definition in file func_speex.c.
| #define DEFAULT_AGC_LEVEL 8000.0 |
Definition at line 51 of file func_speex.c.
Referenced by speex_write().
| static void __reg_module | ( | void | ) | [static] |
Definition at line 384 of file func_speex.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 384 of file func_speex.c.
| static void destroy_callback | ( | void * | data | ) | [static] |
Definition at line 113 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.
{
struct speex_info *si = data;
ast_audiohook_destroy(&si->audiohook);
if (si->rx && si->rx->state) {
speex_preprocess_state_destroy(si->rx->state);
}
if (si->tx && si->tx->state) {
speex_preprocess_state_destroy(si->tx->state);
}
if (si->rx) {
ast_free(si->rx);
}
if (si->tx) {
ast_free(si->tx);
}
ast_free(data);
};
| static int load_module | ( | void | ) | [static] |
Definition at line 370 of file func_speex.c.
References ast_custom_function_register, ast_custom_function_unregister(), AST_MODULE_LOAD_DECLINE, and AST_MODULE_LOAD_SUCCESS.
{
if (ast_custom_function_register(&agc_function)) {
return AST_MODULE_LOAD_DECLINE;
}
if (ast_custom_function_register(&denoise_function)) {
ast_custom_function_unregister(&agc_function);
return AST_MODULE_LOAD_DECLINE;
}
return AST_MODULE_LOAD_SUCCESS;
}
| 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 143 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_format_rate(), AST_FRAME_VOICE, ast_free, AST_MALLOCD_SRC, ast_strdup, ast_datastore::data, ast_frame::data, speex_direction_info::denoise, ast_frame_subclass::format, ast_frame::frametype, speex_info::lastrate, ast_frame::mallocd, ast_frame::ptr, speex_info::rx, speex_direction_info::samples, ast_frame::samples, ast_frame::src, speex_direction_info::state, ast_audiohook::status, ast_frame::subclass, and speex_info::tx.
Referenced by speex_write().
{
struct ast_datastore *datastore = NULL;
struct speex_direction_info *sdi = NULL;
struct speex_info *si = NULL;
char source[80];
/* If the audiohook is stopping it means the channel is shutting down.... but we let the datastore destroy take care of it */
if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE || frame->frametype != AST_FRAME_VOICE) {
return -1;
}
/* We are called with chan already locked */
if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) {
return -1;
}
si = datastore->data;
sdi = (direction == AST_AUDIOHOOK_DIRECTION_READ) ? si->rx : si->tx;
if (!sdi) {
return -1;
}
if ((sdi->samples != frame->samples) || (ast_format_rate(&frame->subclass.format) != si->lastrate)) {
si->lastrate = ast_format_rate(&frame->subclass.format);
if (sdi->state) {
speex_preprocess_state_destroy(sdi->state);
}
if (!(sdi->state = speex_preprocess_state_init((sdi->samples = frame->samples), si->lastrate))) {
return -1;
}
speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_AGC, &sdi->agc);
if (sdi->agc) {
speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_AGC_LEVEL, &sdi->agclevel);
}
speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_DENOISE, &sdi->denoise);
}
speex_preprocess(sdi->state, frame->data.ptr, NULL);
snprintf(source, sizeof(source), "%s/speex", frame->src);
if (frame->mallocd & AST_MALLOCD_SRC) {
ast_free((char *) frame->src);
}
frame->src = ast_strdup(source);
frame->mallocd |= AST_MALLOCD_SRC;
return 0;
}
| static int speex_read | ( | struct ast_channel * | chan, |
| const char * | cmd, | ||
| char * | data, | ||
| char * | buf, | ||
| size_t | len | ||
| ) | [static] |
Definition at line 312 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, and speex_info::tx.
{
struct ast_datastore *datastore = NULL;
struct speex_info *si = NULL;
struct speex_direction_info *sdi = NULL;
if (!chan) {
ast_log(LOG_ERROR, "%s cannot be used without a channel!\n", cmd);
return -1;
}
ast_channel_lock(chan);
if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) {
ast_channel_unlock(chan);
return -1;
}
ast_channel_unlock(chan);
si = datastore->data;
if (!strcasecmp(data, "tx"))
sdi = si->tx;
else if (!strcasecmp(data, "rx"))
sdi = si->rx;
else {
ast_log(LOG_ERROR, "%s(%s) must either \"tx\" or \"rx\"\n", cmd, data);
return -1;
}
if (!strcasecmp(cmd, "agc"))
snprintf(buf, len, "%.01f", sdi ? sdi->agclevel : 0.0);
else
snprintf(buf, len, "%d", sdi ? sdi->denoise : 0);
return 0;
}
| static int speex_write | ( | struct ast_channel * | chan, |
| const char * | cmd, | ||
| char * | data, | ||
| const char * | value | ||
| ) | [static] |
Definition at line 198 of file func_speex.c.
References ast_audiohook_attach(), ast_audiohook_detach(), ast_audiohook_init(), AST_AUDIOHOOK_MANIPULATE_ALL_RATES, 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, speex_info::lastrate, LOG_ERROR, LOG_WARNING, ast_audiohook::manipulate_callback, speex_info::rx, speex_direction_info::samples, speex_callback(), and speex_info::tx.
{
struct ast_datastore *datastore = NULL;
struct speex_info *si = NULL;
struct speex_direction_info **sdi = NULL;
int is_new = 0;
if (!chan) {
ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
return -1;
}
if (strcasecmp(data, "rx") && strcasecmp(data, "tx")) {
ast_log(LOG_ERROR, "Invalid argument provided to the %s function\n", cmd);
return -1;
}
ast_channel_lock(chan);
if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) {
ast_channel_unlock(chan);
if (!(datastore = ast_datastore_alloc(&speex_datastore, NULL))) {
return 0;
}
if (!(si = ast_calloc(1, sizeof(*si)))) {
ast_datastore_free(datastore);
return 0;
}
ast_audiohook_init(&si->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "speex", AST_AUDIOHOOK_MANIPULATE_ALL_RATES);
si->audiohook.manipulate_callback = speex_callback;
si->lastrate = 8000;
is_new = 1;
} else {
ast_channel_unlock(chan);
si = datastore->data;
}
if (!strcasecmp(data, "rx")) {
sdi = &si->rx;
} else {
sdi = &si->tx;
}
if (!*sdi) {
if (!(*sdi = ast_calloc(1, sizeof(**sdi)))) {
return 0;
}
/* Right now, the audiohooks API will _only_ provide us 8 kHz slinear
* audio. When it supports 16 kHz (or any other sample rates, we will
* have to take that into account here. */
(*sdi)->samples = -1;
}
if (!strcasecmp(cmd, "agc")) {
if (!sscanf(value, "%30f", &(*sdi)->agclevel))
(*sdi)->agclevel = ast_true(value) ? DEFAULT_AGC_LEVEL : 0.0;
if ((*sdi)->agclevel > 32768.0) {
ast_log(LOG_WARNING, "AGC(%s)=%.01f is greater than 32768... setting to 32768 instead\n",
((*sdi == si->rx) ? "rx" : "tx"), (*sdi)->agclevel);
(*sdi)->agclevel = 32768.0;
}
(*sdi)->agc = !!((*sdi)->agclevel);
if ((*sdi)->state) {
speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_AGC, &(*sdi)->agc);
if ((*sdi)->agc) {
speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_AGC_LEVEL, &(*sdi)->agclevel);
}
}
} else if (!strcasecmp(cmd, "denoise")) {
(*sdi)->denoise = (ast_true(value) != 0);
if ((*sdi)->state) {
speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_DENOISE, &(*sdi)->denoise);
}
}
if (!(*sdi)->agc && !(*sdi)->denoise) {
if ((*sdi)->state)
speex_preprocess_state_destroy((*sdi)->state);
ast_free(*sdi);
*sdi = NULL;
}
if (!si->rx && !si->tx) {
if (is_new) {
is_new = 0;
} else {
ast_channel_lock(chan);
ast_channel_datastore_remove(chan, datastore);
ast_channel_unlock(chan);
ast_audiohook_remove(chan, &si->audiohook);
ast_audiohook_detach(&si->audiohook);
}
ast_datastore_free(datastore);
}
if (is_new) {
datastore->data = si;
ast_channel_lock(chan);
ast_channel_datastore_add(chan, datastore);
ast_channel_unlock(chan);
ast_audiohook_attach(chan, &si->audiohook);
}
return 0;
}
| static int unload_module | ( | void | ) | [static] |
Definition at line 363 of file func_speex.c.
References ast_custom_function_unregister().
{
ast_custom_function_unregister(&agc_function);
ast_custom_function_unregister(&denoise_function);
return 0;
}
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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static] |
Definition at line 384 of file func_speex.c.
struct ast_custom_function agc_function [static] |
Definition at line 349 of file func_speex.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 384 of file func_speex.c.
struct ast_custom_function denoise_function [static] |
Definition at line 356 of file func_speex.c.
struct ast_datastore_info speex_datastore [static] |
{
.type = "speex",
.destroy = destroy_callback
}
Definition at line 138 of file func_speex.c.