Asterisk - The Open Source Telephony Project GIT-master-b023714
Loading...
Searching...
No Matches
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 = ASTERISK_GPL_KEY , .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:1562
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}
#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:2371
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
#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
enum ast_frame_type frametype
union ast_frame::@239 data

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, 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:2982
#define ast_channel_unlock(chan)
Definition channel.h:2983
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:758
int ast_audiohook_detach(struct ast_audiohook *audiohook)
Detach audiohook from channel.
Definition audiohook.c:587
int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audiohook)
Attach audiohook to channel.
Definition audiohook.c:521
@ 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:2357
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition channel.c:2366
#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:2235
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 = ASTERISK_GPL_KEY , .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.

355 {
356 .name = "AGC",
357 .write = speex_write,
358 .read = speex_read,
359 .read_max = 22,
360};
static int speex_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition func_speex.c:318
static int speex_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Definition func_speex.c:204

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.

362 {
363 .name = "DENOISE",
364 .write = speex_write,
365 .read = speex_read,
366 .read_max = 22,
367};

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.

144 {
145 .type = "speex",
146 .destroy = destroy_callback
147};

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