#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_info * | ast_module_info = &__mod_info |
static struct ast_custom_function | denoise_function |
static struct ast_datastore_info | speex_datastore |
Brett Bryant <bbryant@digium.com>
Definition in file func_speex.c.
#define DEFAULT_AGC_LEVEL 8000.0 |
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.
00359 { 00360 ast_custom_function_unregister(&agc_function); 00361 ast_custom_function_unregister(&denoise_function); 00362 return 0; 00363 }
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] |
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] |
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().