#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_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 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.
00358 { 00359 ast_custom_function_unregister(&agc_function); 00360 ast_custom_function_unregister(&denoise_function); 00361 return 0; 00362 }
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] |
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] |
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().