Asterisk - The Open Source Telephony Project GIT-master-7e7a603
Data Structures | Macros | Functions | Variables
func_speex.c File Reference

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"
Include dependency graph for func_speex.c:

Go to the source code of this file.

Data Structures

struct  speex_direction_info
 
struct  speex_info
 

Macros

#define DEFAULT_AGC_LEVEL   8000.0
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static struct ast_custom_function agc_function
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_custom_function denoise_function
 
static const struct ast_datastore_info speex_datastore
 

Detailed Description

Noise reduction and automatic gain control (AGC)

Author
Brian Degenhardt bmd@d.nosp@m.igiu.nosp@m.m.com
Brett Bryant bbrya.nosp@m.nt@d.nosp@m.igium.nosp@m..com

The Speex 1.2 library - http://www.speex.org

Note
Requires the 1.2 version of the Speex library (which might not be what you find in Linux packages)

Definition in file func_speex.c.

Macro Definition Documentation

◆ DEFAULT_AGC_LEVEL

#define DEFAULT_AGC_LEVEL   8000.0

Definition at line 49 of file func_speex.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 384 of file func_speex.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 384 of file func_speex.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 384 of file func_speex.c.

◆ destroy_callback()

static void destroy_callback ( void *  data)
static

Definition at line 113 of file func_speex.c.

114{
115 struct speex_info *si = data;
116
118
119 if (si->rx && si->rx->state) {
120 speex_preprocess_state_destroy(si->rx->state);
121 }
122
123 if (si->tx && si->tx->state) {
124 speex_preprocess_state_destroy(si->tx->state);
125 }
126
127 if (si->rx) {
128 ast_free(si->rx);
129 }
130
131 if (si->tx) {
132 ast_free(si->tx);
133 }
134
135 ast_free(data);
136};
#define ast_free(a)
Definition: astmm.h:180
int ast_audiohook_destroy(struct ast_audiohook *audiohook)
Destroys an audiohook structure.
Definition: audiohook.c:124
SpeexPreprocessState * state
Definition: func_speex.c:100
struct speex_direction_info * rx
Definition: func_speex.c:110
struct ast_audiohook audiohook
Definition: func_speex.c:108
struct speex_direction_info * tx
Definition: func_speex.c:110

References ast_audiohook_destroy(), ast_free, speex_info::audiohook, speex_info::rx, speex_direction_info::state, and speex_info::tx.

◆ load_module()

static int load_module ( void  )
static

Definition at line 370 of file func_speex.c.

371{
374 }
375
379 }
380
382}
static struct ast_custom_function agc_function
Definition: func_speex.c:349
static struct ast_custom_function denoise_function
Definition: func_speex.c:356
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.

References agc_function, ast_custom_function_register, ast_custom_function_unregister(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, and denoise_function.

◆ speex_callback()

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 143 of file func_speex.c.

144{
145 struct ast_datastore *datastore = NULL;
146 struct speex_direction_info *sdi = NULL;
147 struct speex_info *si = NULL;
148 char source[80];
149
150 /* If the audiohook is stopping it means the channel is shutting down.... but we let the datastore destroy take care of it */
152 return -1;
153 }
154
155 /* We are called with chan already locked */
156 if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) {
157 return -1;
158 }
159
160 si = datastore->data;
161
162 sdi = (direction == AST_AUDIOHOOK_DIRECTION_READ) ? si->rx : si->tx;
163
164 if (!sdi) {
165 return -1;
166 }
167
168 if ((sdi->samples != frame->samples) || (ast_format_get_sample_rate(frame->subclass.format) != si->lastrate)) {
170 if (sdi->state) {
171 speex_preprocess_state_destroy(sdi->state);
172 }
173
174 if (!(sdi->state = speex_preprocess_state_init((sdi->samples = frame->samples), si->lastrate))) {
175 return -1;
176 }
177
178 speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_AGC, &sdi->agc);
179
180 if (sdi->agc) {
181 speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_AGC_LEVEL, &sdi->agclevel);
182 }
183
184 speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_DENOISE, &sdi->denoise);
185 }
186
187 speex_preprocess(sdi->state, frame->data.ptr, NULL);
188 snprintf(source, sizeof(source), "%s/speex", frame->src);
189 if (frame->mallocd & AST_MALLOCD_SRC) {
190 ast_free((char *) frame->src);
191 }
192 frame->src = ast_strdup(source);
193 frame->mallocd |= AST_MALLOCD_SRC;
194
195 return 0;
196}
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
@ AST_AUDIOHOOK_DIRECTION_READ
Definition: audiohook.h:49
@ AST_AUDIOHOOK_STATUS_DONE
Definition: audiohook.h:45
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379
direction
static const struct ast_datastore_info speex_datastore
Definition: func_speex.c:138
#define AST_MALLOCD_SRC
@ AST_FRAME_VOICE
#define NULL
Definition: resample.c:96
enum ast_audiohook_status status
Definition: audiohook.h:108
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66
struct ast_format * format
struct ast_frame_subclass subclass
union ast_frame::@226 data
enum ast_frame_type frametype
const char * src
int lastrate
Definition: func_speex.c:109

References speex_direction_info::agc, speex_direction_info::agclevel, AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_STATUS_DONE, ast_channel_datastore_find(), ast_format_get_sample_rate(), AST_FRAME_VOICE, ast_free, AST_MALLOCD_SRC, ast_strdup, speex_info::audiohook, ast_datastore::data, ast_frame::data, speex_direction_info::denoise, ast_frame_subclass::format, ast_frame::frametype, if(), speex_info::lastrate, ast_frame::mallocd, NULL, ast_frame::ptr, speex_info::rx, speex_direction_info::samples, ast_frame::samples, speex_datastore, ast_frame::src, speex_direction_info::state, ast_audiohook::status, ast_frame::subclass, and speex_info::tx.

Referenced by speex_write().

◆ speex_read()

static int speex_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Definition at line 312 of file func_speex.c.

313{
314 struct ast_datastore *datastore = NULL;
315 struct speex_info *si = NULL;
316 struct speex_direction_info *sdi = NULL;
317
318 if (!chan) {
319 ast_log(LOG_ERROR, "%s cannot be used without a channel!\n", cmd);
320 return -1;
321 }
322
323 ast_channel_lock(chan);
324 if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) {
325 ast_channel_unlock(chan);
326 return -1;
327 }
328 ast_channel_unlock(chan);
329
330 si = datastore->data;
331
332 if (!strcasecmp(data, "tx"))
333 sdi = si->tx;
334 else if (!strcasecmp(data, "rx"))
335 sdi = si->rx;
336 else {
337 ast_log(LOG_ERROR, "%s(%s) must either \"tx\" or \"rx\"\n", cmd, data);
338 return -1;
339 }
340
341 if (!strcasecmp(cmd, "agc"))
342 snprintf(buf, len, "%.01f", sdi ? sdi->agclevel : 0.0);
343 else
344 snprintf(buf, len, "%d", sdi ? sdi->denoise : 0);
345
346 return 0;
347}
#define ast_log
Definition: astobj2.c:42
#define ast_channel_lock(chan)
Definition: channel.h:2922
#define ast_channel_unlock(chan)
Definition: channel.h:2923
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define LOG_ERROR

References speex_direction_info::agclevel, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_log, buf, ast_datastore::data, speex_direction_info::denoise, len(), LOG_ERROR, NULL, speex_info::rx, speex_datastore, and speex_info::tx.

◆ speex_write()

static int speex_write ( struct ast_channel chan,
const char *  cmd,
char *  data,
const char *  value 
)
static

Definition at line 198 of file func_speex.c.

199{
200 struct ast_datastore *datastore = NULL;
201 struct speex_info *si = NULL;
202 struct speex_direction_info **sdi = NULL;
203 int is_new = 0;
204
205 if (!chan) {
206 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
207 return -1;
208 }
209
210 if (strcasecmp(data, "rx") && strcasecmp(data, "tx")) {
211 ast_log(LOG_ERROR, "Invalid argument provided to the %s function\n", cmd);
212 return -1;
213 }
214
215 ast_channel_lock(chan);
216 if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) {
217 ast_channel_unlock(chan);
218
219 if (!(datastore = ast_datastore_alloc(&speex_datastore, NULL))) {
220 return 0;
221 }
222
223 if (!(si = ast_calloc(1, sizeof(*si)))) {
224 ast_datastore_free(datastore);
225 return 0;
226 }
227
230 si->lastrate = 8000;
231 is_new = 1;
232 } else {
233 ast_channel_unlock(chan);
234 si = datastore->data;
235 }
236
237 if (!strcasecmp(data, "rx")) {
238 sdi = &si->rx;
239 } else {
240 sdi = &si->tx;
241 }
242
243 if (!*sdi) {
244 if (!(*sdi = ast_calloc(1, sizeof(**sdi)))) {
245 return 0;
246 }
247 /* Right now, the audiohooks API will _only_ provide us 8 kHz slinear
248 * audio. When it supports 16 kHz (or any other sample rates, we will
249 * have to take that into account here. */
250 (*sdi)->samples = -1;
251 }
252
253 if (!strcasecmp(cmd, "agc")) {
254 if (!sscanf(value, "%30f", &(*sdi)->agclevel))
255 (*sdi)->agclevel = ast_true(value) ? DEFAULT_AGC_LEVEL : 0.0;
256
257 if ((*sdi)->agclevel > 32768.0) {
258 ast_log(LOG_WARNING, "AGC(%s)=%.01f is greater than 32768... setting to 32768 instead\n",
259 ((*sdi == si->rx) ? "rx" : "tx"), (*sdi)->agclevel);
260 (*sdi)->agclevel = 32768.0;
261 }
262
263 (*sdi)->agc = !!((*sdi)->agclevel);
264
265 if ((*sdi)->state) {
266 speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_AGC, &(*sdi)->agc);
267 if ((*sdi)->agc) {
268 speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_AGC_LEVEL, &(*sdi)->agclevel);
269 }
270 }
271 } else if (!strcasecmp(cmd, "denoise")) {
272 (*sdi)->denoise = (ast_true(value) != 0);
273
274 if ((*sdi)->state) {
275 speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_DENOISE, &(*sdi)->denoise);
276 }
277 }
278
279 if (!(*sdi)->agc && !(*sdi)->denoise) {
280 if ((*sdi)->state)
281 speex_preprocess_state_destroy((*sdi)->state);
282
283 ast_free(*sdi);
284 *sdi = NULL;
285 }
286
287 if (!si->rx && !si->tx) {
288 if (is_new) {
289 is_new = 0;
290 } else {
291 ast_channel_lock(chan);
292 ast_channel_datastore_remove(chan, datastore);
293 ast_channel_unlock(chan);
296 }
297
298 ast_datastore_free(datastore);
299 }
300
301 if (is_new) {
302 datastore->data = si;
303 ast_channel_lock(chan);
304 ast_channel_datastore_add(chan, datastore);
305 ast_channel_unlock(chan);
307 }
308
309 return 0;
310}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
@ AST_AUDIOHOOK_MANIPULATE_ALL_RATES
Definition: audiohook.h:75
int ast_audiohook_init(struct ast_audiohook *audiohook, enum ast_audiohook_type type, const char *source, enum ast_audiohook_init_flags flags)
Initialize an audiohook structure.
Definition: audiohook.c:100
int ast_audiohook_remove(struct ast_channel *chan, struct ast_audiohook *audiohook)
Remove an audiohook from a specified channel.
Definition: audiohook.c:721
int ast_audiohook_detach(struct ast_audiohook *audiohook)
Detach audiohook from channel.
Definition: audiohook.c:550
int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audiohook)
Attach audiohook to channel.
Definition: audiohook.c:484
@ AST_AUDIOHOOK_TYPE_MANIPULATE
Definition: audiohook.h:38
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2385
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2394
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
#define DEFAULT_AGC_LEVEL
Definition: func_speex.c:49
static int speex_callback(struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction)
Definition: func_speex.c:143
#define LOG_WARNING
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
ast_audiohook_manipulate_callback manipulate_callback
Definition: audiohook.h:118
int value
Definition: syslog.c:37

References ast_audiohook_attach(), ast_audiohook_detach(), ast_audiohook_init(), AST_AUDIOHOOK_MANIPULATE_ALL_RATES, 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, speex_info::lastrate, LOG_ERROR, LOG_WARNING, ast_audiohook::manipulate_callback, NULL, speex_info::rx, speex_direction_info::samples, speex_callback(), speex_datastore, speex_info::tx, and value.

◆ unload_module()

static int unload_module ( void  )
static

Variable Documentation

◆ __mod_info

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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 384 of file func_speex.c.

◆ agc_function

struct ast_custom_function agc_function
static

Definition at line 349 of file func_speex.c.

Referenced by load_module(), and unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 384 of file func_speex.c.

◆ denoise_function

struct ast_custom_function denoise_function
static

Definition at line 356 of file func_speex.c.

Referenced by load_module(), and unload_module().

◆ speex_datastore

const struct ast_datastore_info speex_datastore
static
Initial value:
= {
.type = "speex",
.destroy = destroy_callback
}
static void destroy_callback(void *data)
Definition: func_speex.c:113

Definition at line 138 of file func_speex.c.

Referenced by speex_callback(), speex_read(), and speex_write().