Asterisk - The Open Source Telephony Project GIT-master-754dea3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 390 of file func_speex.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 390 of file func_speex.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 390 of file func_speex.c.

◆ destroy_callback()

static void destroy_callback ( void *  data)
static

Definition at line 119 of file func_speex.c.

120{
121 struct speex_info *si = data;
122
124
125 if (si->rx && si->rx->state) {
126 speex_preprocess_state_destroy(si->rx->state);
127 }
128
129 if (si->tx && si->tx->state) {
130 speex_preprocess_state_destroy(si->tx->state);
131 }
132
133 if (si->rx) {
134 ast_free(si->rx);
135 }
136
137 if (si->tx) {
138 ast_free(si->tx);
139 }
140
141 ast_free(data);
142};
#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:106
struct speex_direction_info * rx
Definition: func_speex.c:116
struct ast_audiohook audiohook
Definition: func_speex.c:114
struct speex_direction_info * tx
Definition: func_speex.c:116

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

377{
380 }
381
385 }
386
388}
static struct ast_custom_function agc_function
Definition: func_speex.c:355
static struct ast_custom_function denoise_function
Definition: func_speex.c:362
@ 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:1559
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 149 of file func_speex.c.

150{
151 struct ast_datastore *datastore = NULL;
152 struct speex_direction_info *sdi = NULL;
153 struct speex_info *si = NULL;
154 char source[80];
155
156 /* If the audiohook is stopping it means the channel is shutting down.... but we let the datastore destroy take care of it */
158 return -1;
159 }
160
161 /* We are called with chan already locked */
162 if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) {
163 return -1;
164 }
165
166 si = datastore->data;
167
168 sdi = (direction == AST_AUDIOHOOK_DIRECTION_READ) ? si->rx : si->tx;
169
170 if (!sdi) {
171 return -1;
172 }
173
174 if ((sdi->samples != frame->samples) || (ast_format_get_sample_rate(frame->subclass.format) != si->lastrate)) {
176 if (sdi->state) {
177 speex_preprocess_state_destroy(sdi->state);
178 }
179
180 if (!(sdi->state = speex_preprocess_state_init((sdi->samples = frame->samples), si->lastrate))) {
181 return -1;
182 }
183
184 speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_AGC, &sdi->agc);
185
186 if (sdi->agc) {
187 speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_AGC_LEVEL, &sdi->agclevel);
188 }
189
190 speex_preprocess_ctl(sdi->state, SPEEX_PREPROCESS_SET_DENOISE, &sdi->denoise);
191 }
192
193 speex_preprocess(sdi->state, frame->data.ptr, NULL);
194 snprintf(source, sizeof(source), "%s/speex", frame->src);
195 if (frame->mallocd & AST_MALLOCD_SRC) {
196 ast_free((char *) frame->src);
197 }
198 frame->src = ast_strdup(source);
199 frame->mallocd |= AST_MALLOCD_SRC;
200
201 return 0;
202}
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:2428
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:144
#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
union ast_frame::@228 data
struct ast_frame_subclass subclass
enum ast_frame_type frametype
const char * src
int lastrate
Definition: func_speex.c:115

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

319{
320 struct ast_datastore *datastore = NULL;
321 struct speex_info *si = NULL;
322 struct speex_direction_info *sdi = NULL;
323
324 if (!chan) {
325 ast_log(LOG_ERROR, "%s cannot be used without a channel!\n", cmd);
326 return -1;
327 }
328
329 ast_channel_lock(chan);
330 if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) {
331 ast_channel_unlock(chan);
332 return -1;
333 }
334 ast_channel_unlock(chan);
335
336 si = datastore->data;
337
338 if (!strcasecmp(data, "tx"))
339 sdi = si->tx;
340 else if (!strcasecmp(data, "rx"))
341 sdi = si->rx;
342 else {
343 ast_log(LOG_ERROR, "%s(%s) must either \"tx\" or \"rx\"\n", cmd, data);
344 return -1;
345 }
346
347 if (!strcasecmp(cmd, "agc"))
348 snprintf(buf, len, "%.01f", sdi ? sdi->agclevel : 0.0);
349 else
350 snprintf(buf, len, "%d", sdi ? sdi->denoise : 0);
351
352 return 0;
353}
#define ast_log
Definition: astobj2.c:42
#define ast_channel_lock(chan)
Definition: channel.h:2970
#define ast_channel_unlock(chan)
Definition: channel.h:2971
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 204 of file func_speex.c.

205{
206 struct ast_datastore *datastore = NULL;
207 struct speex_info *si = NULL;
208 struct speex_direction_info **sdi = NULL;
209 int is_new = 0;
210
211 if (!chan) {
212 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
213 return -1;
214 }
215
216 if (strcasecmp(data, "rx") && strcasecmp(data, "tx")) {
217 ast_log(LOG_ERROR, "Invalid argument provided to the %s function\n", cmd);
218 return -1;
219 }
220
221 ast_channel_lock(chan);
222 if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) {
223 ast_channel_unlock(chan);
224
225 if (!(datastore = ast_datastore_alloc(&speex_datastore, NULL))) {
226 return 0;
227 }
228
229 if (!(si = ast_calloc(1, sizeof(*si)))) {
230 ast_datastore_free(datastore);
231 return 0;
232 }
233
236 si->lastrate = 8000;
237 is_new = 1;
238 } else {
239 ast_channel_unlock(chan);
240 si = datastore->data;
241 }
242
243 if (!strcasecmp(data, "rx")) {
244 sdi = &si->rx;
245 } else {
246 sdi = &si->tx;
247 }
248
249 if (!*sdi) {
250 if (!(*sdi = ast_calloc(1, sizeof(**sdi)))) {
251 return 0;
252 }
253 /* Right now, the audiohooks API will _only_ provide us 8 kHz slinear
254 * audio. When it supports 16 kHz (or any other sample rates, we will
255 * have to take that into account here. */
256 (*sdi)->samples = -1;
257 }
258
259 if (!strcasecmp(cmd, "agc")) {
260 if (!sscanf(value, "%30f", &(*sdi)->agclevel))
261 (*sdi)->agclevel = ast_true(value) ? DEFAULT_AGC_LEVEL : 0.0;
262
263 if ((*sdi)->agclevel > 32768.0) {
264 ast_log(LOG_WARNING, "AGC(%s)=%.01f is greater than 32768... setting to 32768 instead\n",
265 ((*sdi == si->rx) ? "rx" : "tx"), (*sdi)->agclevel);
266 (*sdi)->agclevel = 32768.0;
267 }
268
269 (*sdi)->agc = !!((*sdi)->agclevel);
270
271 if ((*sdi)->state) {
272 speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_AGC, &(*sdi)->agc);
273 if ((*sdi)->agc) {
274 speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_AGC_LEVEL, &(*sdi)->agclevel);
275 }
276 }
277 } else if (!strcasecmp(cmd, "denoise")) {
278 (*sdi)->denoise = (ast_true(value) != 0);
279
280 if ((*sdi)->state) {
281 speex_preprocess_ctl((*sdi)->state, SPEEX_PREPROCESS_SET_DENOISE, &(*sdi)->denoise);
282 }
283 }
284
285 if (!(*sdi)->agc && !(*sdi)->denoise) {
286 if ((*sdi)->state)
287 speex_preprocess_state_destroy((*sdi)->state);
288
289 ast_free(*sdi);
290 *sdi = NULL;
291 }
292
293 if (!si->rx && !si->tx) {
294 if (is_new) {
295 is_new = 0;
296 } else {
297 ast_channel_lock(chan);
298 ast_channel_datastore_remove(chan, datastore);
299 ast_channel_unlock(chan);
302 }
303
304 ast_datastore_free(datastore);
305 }
306
307 if (is_new) {
308 datastore->data = si;
309 ast_channel_lock(chan);
310 ast_channel_datastore_add(chan, datastore);
311 ast_channel_unlock(chan);
313 }
314
315 return 0;
316}
#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:749
int ast_audiohook_detach(struct ast_audiohook *audiohook)
Detach audiohook from channel.
Definition: audiohook.c:578
int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audiohook)
Attach audiohook to channel.
Definition: audiohook.c:512
@ 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:2414
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2423
#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:149
#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 390 of file func_speex.c.

◆ agc_function

struct ast_custom_function agc_function
static

Definition at line 355 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 390 of file func_speex.c.

◆ denoise_function

struct ast_custom_function denoise_function
static

Definition at line 362 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:119

Definition at line 144 of file func_speex.c.

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