#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_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .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 |
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 356 of file func_speex.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 356 of file func_speex.c.
static void destroy_callback | ( | void * | data | ) | [static] |
Definition at line 64 of file func_speex.c.
References ast_audiohook_destroy(), ast_free, and si.
00065 { 00066 struct speex_info *si = data; 00067 00068 ast_audiohook_destroy(&si->audiohook); 00069 00070 if (si->rx && si->rx->state) { 00071 speex_preprocess_state_destroy(si->rx->state); 00072 } 00073 00074 if (si->tx && si->tx->state) { 00075 speex_preprocess_state_destroy(si->tx->state); 00076 } 00077 00078 if (si->rx) { 00079 ast_free(si->rx); 00080 } 00081 00082 if (si->tx) { 00083 ast_free(si->tx); 00084 } 00085 00086 ast_free(data); 00087 };
static int load_module | ( | void | ) | [static] |
Definition at line 342 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.
00343 { 00344 if (ast_custom_function_register(&agc_function)) { 00345 return AST_MODULE_LOAD_DECLINE; 00346 } 00347 00348 if (ast_custom_function_register(&denoise_function)) { 00349 ast_custom_function_unregister(&agc_function); 00350 return AST_MODULE_LOAD_DECLINE; 00351 } 00352 00353 return AST_MODULE_LOAD_SUCCESS; 00354 }
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 94 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, chan, ast_frame::data, ast_datastore::data, speex_direction_info::denoise, ast_frame::frametype, ast_frame::mallocd, ast_frame::ptr, ast_frame::samples, speex_direction_info::samples, si, speex_datastore, ast_frame::src, speex_direction_info::state, and ast_audiohook::status.
Referenced by speex_write().
00095 { 00096 struct ast_datastore *datastore = NULL; 00097 struct speex_direction_info *sdi = NULL; 00098 struct speex_info *si = NULL; 00099 char source[80]; 00100 00101 /* If the audiohook is stopping it means the channel is shutting down.... but we let the datastore destroy take care of it */ 00102 if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE || frame->frametype != AST_FRAME_VOICE) { 00103 return -1; 00104 } 00105 00106 /* We are called with chan already locked */ 00107 if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) { 00108 return -1; 00109 } 00110 00111 si = datastore->data; 00112 00113 sdi = (direction == AST_AUDIOHOOK_DIRECTION_READ) ? si->rx : si->tx; 00114 00115 if (!sdi) { 00116 return -1; 00117 } 00118 00119 if (sdi->samples != frame->samples) { 00120 if (sdi->state) { 00121 speex_preprocess_state_destroy(sdi->state); 00122 } 00123 00124 if (!(sdi->state = speex_preprocess_state_init((sdi->samples = frame->samples), 8000))) { 00125 return -1; 00126 } 00127 00128 speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_AGC, &sdi->agc); 00129 00130 if (sdi->agc) { 00131 speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_AGC_LEVEL, &sdi->agclevel); 00132 } 00133 00134 speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_DENOISE, &sdi->denoise); 00135 } 00136 00137 speex_preprocess(sdi->state, frame->data.ptr, NULL); 00138 snprintf(source, sizeof(source), "%s/speex", frame->src); 00139 if (frame->mallocd & AST_MALLOCD_SRC) { 00140 ast_free((char *) frame->src); 00141 } 00142 frame->src = ast_strdup(source); 00143 frame->mallocd |= AST_MALLOCD_SRC; 00144 00145 return 0; 00146 }
static int speex_read | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 259 of file func_speex.c.
References speex_direction_info::agclevel, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_log(), chan, ast_datastore::data, speex_direction_info::denoise, LOG_ERROR, si, and speex_datastore.
00260 { 00261 struct ast_datastore *datastore = NULL; 00262 struct speex_info *si = NULL; 00263 struct speex_direction_info *sdi = NULL; 00264 00265 if (!chan) { 00266 ast_log(LOG_ERROR, "%s cannot be used without a channel!\n", cmd); 00267 return -1; 00268 } 00269 00270 ast_channel_lock(chan); 00271 if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) { 00272 ast_channel_unlock(chan); 00273 return -1; 00274 } 00275 ast_channel_unlock(chan); 00276 00277 si = datastore->data; 00278 00279 if (!strcasecmp(data, "tx")) 00280 sdi = si->tx; 00281 else if (!strcasecmp(data, "rx")) 00282 sdi = si->rx; 00283 else { 00284 ast_log(LOG_ERROR, "%s(%s) must either \"tx\" or \"rx\"\n", cmd, data); 00285 return -1; 00286 } 00287 00288 if (!strcasecmp(cmd, "agc")) 00289 snprintf(buf, len, "%.01f", sdi ? sdi->agclevel : 0.0); 00290 else 00291 snprintf(buf, len, "%d", sdi ? sdi->denoise : 0); 00292 00293 return 0; 00294 }
static int speex_write | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 148 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(), chan, ast_datastore::data, DEFAULT_AGC_LEVEL, LOG_ERROR, LOG_WARNING, si, speex_callback(), and speex_datastore.
00149 { 00150 struct ast_datastore *datastore = NULL; 00151 struct speex_info *si = NULL; 00152 struct speex_direction_info **sdi = NULL; 00153 int is_new = 0; 00154 00155 ast_channel_lock(chan); 00156 if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) { 00157 ast_channel_unlock(chan); 00158 00159 if (!(datastore = ast_datastore_alloc(&speex_datastore, NULL))) { 00160 return 0; 00161 } 00162 00163 if (!(si = ast_calloc(1, sizeof(*si)))) { 00164 ast_datastore_free(datastore); 00165 return 0; 00166 } 00167 00168 ast_audiohook_init(&si->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "speex"); 00169 si->audiohook.manipulate_callback = speex_callback; 00170 00171 is_new = 1; 00172 } else { 00173 ast_channel_unlock(chan); 00174 si = datastore->data; 00175 } 00176 00177 if (!strcasecmp(data, "rx")) { 00178 sdi = &si->rx; 00179 } else if (!strcasecmp(data, "tx")) { 00180 sdi = &si->tx; 00181 } else { 00182 ast_log(LOG_ERROR, "Invalid argument provided to the %s function\n", cmd); 00183 00184 if (is_new) { 00185 ast_datastore_free(datastore); 00186 return -1; 00187 } 00188 } 00189 00190 if (!*sdi) { 00191 if (!(*sdi = ast_calloc(1, sizeof(**sdi)))) { 00192 return 0; 00193 } 00194 /* Right now, the audiohooks API will _only_ provide us 8 kHz slinear 00195 * audio. When it supports 16 kHz (or any other sample rates, we will 00196 * have to take that into account here. */ 00197 (*sdi)->samples = -1; 00198 } 00199 00200 if (!strcasecmp(cmd, "agc")) { 00201 if (!sscanf(value, "%30f", &(*sdi)->agclevel)) 00202 (*sdi)->agclevel = ast_true(value) ? DEFAULT_AGC_LEVEL : 0.0; 00203 00204 if ((*sdi)->agclevel > 32768.0) { 00205 ast_log(LOG_WARNING, "AGC(%s)=%.01f is greater than 32768... setting to 32768 instead\n", 00206 ((*sdi == si->rx) ? "rx" : "tx"), (*sdi)->agclevel); 00207 (*sdi)->agclevel = 32768.0; 00208 } 00209 00210 (*sdi)->agc = !!((*sdi)->agclevel); 00211 00212 if ((*sdi)->state) { 00213 speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_AGC, &(*sdi)->agc); 00214 if ((*sdi)->agc) { 00215 speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_AGC_LEVEL, &(*sdi)->agclevel); 00216 } 00217 } 00218 } else if (!strcasecmp(cmd, "denoise")) { 00219 (*sdi)->denoise = (ast_true(value) != 0); 00220 00221 if ((*sdi)->state) { 00222 speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_DENOISE, &(*sdi)->denoise); 00223 } 00224 } 00225 00226 if (!(*sdi)->agc && !(*sdi)->denoise) { 00227 if ((*sdi)->state) 00228 speex_preprocess_state_destroy((*sdi)->state); 00229 00230 ast_free(*sdi); 00231 *sdi = NULL; 00232 } 00233 00234 if (!si->rx && !si->tx) { 00235 if (is_new) { 00236 is_new = 0; 00237 } else { 00238 ast_channel_lock(chan); 00239 ast_channel_datastore_remove(chan, datastore); 00240 ast_channel_unlock(chan); 00241 ast_audiohook_remove(chan, &si->audiohook); 00242 ast_audiohook_detach(&si->audiohook); 00243 } 00244 00245 ast_datastore_free(datastore); 00246 } 00247 00248 if (is_new) { 00249 datastore->data = si; 00250 ast_channel_lock(chan); 00251 ast_channel_datastore_add(chan, datastore); 00252 ast_channel_unlock(chan); 00253 ast_audiohook_attach(chan, &si->audiohook); 00254 } 00255 00256 return 0; 00257 }
static int unload_module | ( | void | ) | [static] |
Definition at line 335 of file func_speex.c.
References agc_function, ast_custom_function_unregister(), and denoise_function.
00336 { 00337 ast_custom_function_unregister(&agc_function); 00338 ast_custom_function_unregister(&denoise_function); 00339 return 0; 00340 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 356 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 356 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 89 of file func_speex.c.
Referenced by speex_callback(), speex_read(), and speex_write().