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 __MODULE_INFO_SECTION | __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Noise reduction and Automatic Gain Control (AGC)" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } |
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 49 of file func_speex.c.
Referenced by speex_write().
static void __reg_module | ( | void | ) | [static] |
Definition at line 375 of file func_speex.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 375 of file func_speex.c.
static void destroy_callback | ( | void * | data | ) | [static] |
Definition at line 110 of file func_speex.c.
References ast_audiohook_destroy(), ast_free, speex_info::audiohook, speex_info::rx, si, 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 361 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 140 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, 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, si, ast_frame::src, speex_direction_info::state, ast_audiohook::status, 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) { if (sdi->state) { speex_preprocess_state_destroy(sdi->state); } if (!(sdi->state = speex_preprocess_state_init((sdi->samples = frame->samples), 8000))) { 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 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, si, 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 194 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, ast_audiohook::manipulate_callback, speex_info::rx, si, 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; 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"); si->audiohook.manipulate_callback = speex_callback; is_new = 1; } else { ast_channel_unlock(chan); si = datastore->data; } if (!strcasecmp(data, "rx")) { sdi = &si->rx; } else if (!strcasecmp(data, "tx")) { sdi = &si->tx; } else { ast_log(LOG_ERROR, "Invalid argument provided to the %s function\n", cmd); if (is_new) { ast_datastore_free(datastore); return -1; } } 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 354 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 __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Noise reduction and Automatic Gain Control (AGC)" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } [static] |
Definition at line 375 of file func_speex.c.
struct ast_custom_function agc_function [static] |
{ .name = "AGC", .write = speex_write, .read = speex_read }
Definition at line 342 of file func_speex.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 375 of file func_speex.c.
struct ast_custom_function denoise_function [static] |
{ .name = "DENOISE", .write = speex_write, .read = speex_read }
Definition at line 348 of file func_speex.c.
struct ast_datastore_info speex_datastore [static] |
{ .type = "speex", .destroy = destroy_callback }
Definition at line 135 of file func_speex.c.