#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 351 of file func_speex.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 351 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 337 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.
00338 { 00339 if (ast_custom_function_register(&agc_function)) { 00340 return AST_MODULE_LOAD_DECLINE; 00341 } 00342 00343 if (ast_custom_function_register(&denoise_function)) { 00344 ast_custom_function_unregister(&agc_function); 00345 return AST_MODULE_LOAD_DECLINE; 00346 } 00347 00348 return AST_MODULE_LOAD_SUCCESS; 00349 }
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_channel_lock, ast_channel_unlock, AST_FRAME_VOICE, speex_info::audiohook, chan, ast_frame::data, ast_datastore::data, speex_direction_info::denoise, ast_frame::frametype, ast_frame::ptr, ast_frame::samples, speex_direction_info::samples, si, speex_datastore, 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 00100 /* If the audiohook is stopping it means the channel is shutting down.... but we let the datastore destroy take care of it */ 00101 if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE || frame->frametype != AST_FRAME_VOICE) { 00102 return 0; 00103 } 00104 00105 ast_channel_lock(chan); 00106 if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) { 00107 ast_channel_unlock(chan); 00108 return 0; 00109 } 00110 ast_channel_unlock(chan); 00111 00112 si = datastore->data; 00113 00114 sdi = (direction == AST_AUDIOHOOK_DIRECTION_READ) ? si->rx : si->tx; 00115 00116 if (!sdi) { 00117 return 0; 00118 } 00119 00120 if (sdi->samples != frame->samples) { 00121 if (sdi->state) { 00122 speex_preprocess_state_destroy(sdi->state); 00123 } 00124 00125 if (!(sdi->state = speex_preprocess_state_init((sdi->samples = frame->samples), 8000))) { 00126 return -1; 00127 } 00128 00129 speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_AGC, &sdi->agc); 00130 00131 if (sdi->agc) { 00132 speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_AGC_LEVEL, &sdi->agclevel); 00133 } 00134 00135 speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_DENOISE, &sdi->denoise); 00136 } 00137 00138 speex_preprocess(sdi->state, frame->data.ptr, NULL); 00139 00140 return 0; 00141 }
static int speex_read | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 254 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.
00255 { 00256 struct ast_datastore *datastore = NULL; 00257 struct speex_info *si = NULL; 00258 struct speex_direction_info *sdi = NULL; 00259 00260 if (!chan) { 00261 ast_log(LOG_ERROR, "%s cannot be used without a channel!\n", cmd); 00262 return -1; 00263 } 00264 00265 ast_channel_lock(chan); 00266 if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) { 00267 ast_channel_unlock(chan); 00268 return -1; 00269 } 00270 ast_channel_unlock(chan); 00271 00272 si = datastore->data; 00273 00274 if (!strcasecmp(data, "tx")) 00275 sdi = si->tx; 00276 else if (!strcasecmp(data, "rx")) 00277 sdi = si->rx; 00278 else { 00279 ast_log(LOG_ERROR, "%s(%s) must either \"tx\" or \"rx\"\n", cmd, data); 00280 return -1; 00281 } 00282 00283 if (!strcasecmp(cmd, "agc")) 00284 snprintf(buf, len, "%.01f", sdi ? sdi->agclevel : 0.0); 00285 else 00286 snprintf(buf, len, "%d", sdi ? sdi->denoise : 0); 00287 00288 return 0; 00289 }
static int speex_write | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 143 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.
00144 { 00145 struct ast_datastore *datastore = NULL; 00146 struct speex_info *si = NULL; 00147 struct speex_direction_info **sdi = NULL; 00148 int is_new = 0; 00149 00150 ast_channel_lock(chan); 00151 if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) { 00152 ast_channel_unlock(chan); 00153 00154 if (!(datastore = ast_datastore_alloc(&speex_datastore, NULL))) { 00155 return 0; 00156 } 00157 00158 if (!(si = ast_calloc(1, sizeof(*si)))) { 00159 ast_datastore_free(datastore); 00160 return 0; 00161 } 00162 00163 ast_audiohook_init(&si->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "speex"); 00164 si->audiohook.manipulate_callback = speex_callback; 00165 00166 is_new = 1; 00167 } else { 00168 ast_channel_unlock(chan); 00169 si = datastore->data; 00170 } 00171 00172 if (!strcasecmp(data, "rx")) { 00173 sdi = &si->rx; 00174 } else if (!strcasecmp(data, "tx")) { 00175 sdi = &si->tx; 00176 } else { 00177 ast_log(LOG_ERROR, "Invalid argument provided to the %s function\n", cmd); 00178 00179 if (is_new) { 00180 ast_datastore_free(datastore); 00181 return -1; 00182 } 00183 } 00184 00185 if (!*sdi) { 00186 if (!(*sdi = ast_calloc(1, sizeof(**sdi)))) { 00187 return 0; 00188 } 00189 /* Right now, the audiohooks API will _only_ provide us 8 kHz slinear 00190 * audio. When it supports 16 kHz (or any other sample rates, we will 00191 * have to take that into account here. */ 00192 (*sdi)->samples = -1; 00193 } 00194 00195 if (!strcasecmp(cmd, "agc")) { 00196 if (!sscanf(value, "%f", &(*sdi)->agclevel)) 00197 (*sdi)->agclevel = ast_true(value) ? DEFAULT_AGC_LEVEL : 0.0; 00198 00199 if ((*sdi)->agclevel > 32768.0) { 00200 ast_log(LOG_WARNING, "AGC(%s)=%.01f is greater than 32768... setting to 32768 instead\n", 00201 ((*sdi == si->rx) ? "rx" : "tx"), (*sdi)->agclevel); 00202 (*sdi)->agclevel = 32768.0; 00203 } 00204 00205 (*sdi)->agc = !!((*sdi)->agclevel); 00206 00207 if ((*sdi)->state) { 00208 speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_AGC, &(*sdi)->agc); 00209 if ((*sdi)->agc) { 00210 speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_AGC_LEVEL, &(*sdi)->agclevel); 00211 } 00212 } 00213 } else if (!strcasecmp(cmd, "denoise")) { 00214 (*sdi)->denoise = (ast_true(value) != 0); 00215 00216 if ((*sdi)->state) { 00217 speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_DENOISE, &(*sdi)->denoise); 00218 } 00219 } 00220 00221 if (!(*sdi)->agc && !(*sdi)->denoise) { 00222 if ((*sdi)->state) 00223 speex_preprocess_state_destroy((*sdi)->state); 00224 00225 ast_free(*sdi); 00226 *sdi = NULL; 00227 } 00228 00229 if (!si->rx && !si->tx) { 00230 if (is_new) { 00231 is_new = 0; 00232 } else { 00233 ast_channel_lock(chan); 00234 ast_channel_datastore_remove(chan, datastore); 00235 ast_channel_unlock(chan); 00236 ast_audiohook_remove(chan, &si->audiohook); 00237 ast_audiohook_detach(&si->audiohook); 00238 } 00239 00240 ast_datastore_free(datastore); 00241 } 00242 00243 if (is_new) { 00244 datastore->data = si; 00245 ast_channel_lock(chan); 00246 ast_channel_datastore_add(chan, datastore); 00247 ast_channel_unlock(chan); 00248 ast_audiohook_attach(chan, &si->audiohook); 00249 } 00250 00251 return 0; 00252 }
static int unload_module | ( | void | ) | [static] |
Definition at line 330 of file func_speex.c.
References agc_function, ast_custom_function_unregister(), and denoise_function.
00331 { 00332 ast_custom_function_unregister(&agc_function); 00333 ast_custom_function_unregister(&denoise_function); 00334 return 0; 00335 }
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 351 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 351 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().