[asterisk-commits] bbryant: branch bbryant/noise_reduction_and_agc r114837 - /team/bbryant/noise...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Apr 29 13:23:15 CDT 2008
Author: bbryant
Date: Tue Apr 29 13:23:15 2008
New Revision: 114837
URL: http://svn.digium.com/view/asterisk?view=rev&rev=114837
Log:
Update progress. Everything seems to be working except for AGC() .. strange line noise.
Modified:
team/bbryant/noise_reduction_and_agc/funcs/func_speex.c
Modified: team/bbryant/noise_reduction_and_agc/funcs/func_speex.c
URL: http://svn.digium.com/view/asterisk/team/bbryant/noise_reduction_and_agc/funcs/func_speex.c?view=diff&rev=114837&r1=114836&r2=114837
==============================================================================
--- team/bbryant/noise_reduction_and_agc/funcs/func_speex.c (original)
+++ team/bbryant/noise_reduction_and_agc/funcs/func_speex.c Tue Apr 29 13:23:15 2008
@@ -38,7 +38,6 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <speex/speex_preprocess.h>
-
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
@@ -47,15 +46,173 @@
#define DEFAULT_AGC_LEVEL 8000.0
-static int agc_write(struct ast_channel *chan, const char *cmd, char *data,
- const char *value)
-{
- return 0;
-}
+struct agc_info {
+ struct ast_audiohook audiohook;
+ float tx_level, rx_level;
+ SpeexPreprocessState *preprocess_state;
+};
+
+struct denoise_info {
+ struct ast_audiohook audiohook;
+ uint8_t tx_enabled, rx_enabled;
+ SpeexPreprocessState *preprocess_state;
+};
+
+static void agc_destroy_callback(void *data)
+{
+ struct agc_info *ai = data;
+
+ ast_audiohook_destroy(&ai->audiohook);
+
+ ast_free(data);
+};
+
+static void denoise_destroy_callback(void *data)
+{
+ struct denoise_info *di = data;
+
+ ast_audiohook_destroy(&di->audiohook);
+
+ ast_free(data);
+}
+
+static const struct ast_datastore_info agc_datastore = {
+ .type = "agc",
+ .destroy = agc_destroy_callback
+};
+
+static const struct ast_datastore_info denoise_datastore = {
+ .type = "denois",
+ .destroy = denoise_destroy_callback
+};
+
+static int agc_callback(struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction)
+{
+ struct ast_datastore *datastore = NULL;
+ struct agc_info *ai = NULL;
+ float agclevel;
+
+ /* If the audiohook is stopping it means the channel is shutting down.... but we let the datastore destroy take care of it */
+ if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE)
+ return 0;
+
+ if (!(datastore = ast_channel_datastore_find(chan, &agc_datastore, NULL)))
+ return 0;
+
+ ai = datastore->data;
+
+ /* If we don't have a voice frame, or there's no agc level for the direction of this frame... exit */
+ if (frame->frametype != AST_FRAME_VOICE ||
+ !(agclevel = (direction == AST_AUDIOHOOK_DIRECTION_READ) ? ai->rx_level : ai->tx_level))
+ return 0;
+
+ speex_preprocess_ctl(ai->preprocess_state, SPEEX_PREPROCESS_SET_AGC_LEVEL, &agclevel);
+ speex_preprocess(ai->preprocess_state, frame->data, NULL); /* TODO: how does speex know when the frame's data (void *) ends */
+
+ return 0;
+}
+
+static int agc_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
+{
+ struct ast_datastore *datastore = NULL;
+ struct agc_info *ai = NULL;
+ int is_new = 0;
+ float *agcval = NULL;
+
+ if (!(datastore = ast_channel_datastore_find(chan, &agc_datastore, NULL))) {
+ if (!(datastore = ast_channel_datastore_alloc(&agc_datastore, NULL)))
+ return 0;
+ if (!(ai = ast_calloc(1, sizeof(*ai)))) {
+ ast_channel_datastore_free(datastore);
+ return 0;
+ }
+
+ ast_audiohook_init(&ai->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "agc");
+ ai->audiohook.manipulate_callback = agc_callback;
+
+ is_new = 1;
+ } else {
+ ai = datastore->data;
+ }
+
+ if (!strcasecmp(data, "tx"))
+ agcval = &ai->tx_level;
+ else if (!strcasecmp(data, "rx"))
+ agcval = &ai->rx_level;
+
+ if (agcval && !sscanf(value, "%f", agcval))
+ *agcval = (ast_true(value)) ? DEFAULT_AGC_LEVEL : 0;
+
+ if (is_new) {
+ ai->preprocess_state = speex_preprocess_state_init(160, 8000);
+ datastore->data = ai;
+ ast_channel_datastore_add(chan, datastore);
+ ast_audiohook_attach(chan, &ai->audiohook);
+ }
+
+ return 0;
+}
+
+static int denoise_callback(struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction)
+{
+ static int yes = 1; /* TODO: global identifier that would work? */
+ struct ast_datastore *datastore = NULL;
+ struct denoise_info *di = NULL;
+
+ /* If the audiohook is stopping it means the channel is shutting down.... but we let the datastore destroy take care of it */
+ if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE)
+ return 0;
+
+ if (!(datastore = ast_channel_datastore_find(chan, &denoise_datastore, NULL)))
+ return 0;
+
+ di = datastore->data;
+
+ if (frame->frametype != AST_FRAME_VOICE ||
+ ((direction == AST_AUDIOHOOK_DIRECTION_READ) ? di->rx_enabled : di->tx_enabled))
+ return 0;
+
+ speex_preprocess_ctl(di->preprocess_state, SPEEX_PREPROCESS_SET_DENOISE, &yes);
+ speex_preprocess(di->preprocess_state, frame->data, NULL);
+
+ return 0;
+}
+
static int denoise_write(struct ast_channel *chan, const char *cmd, char *data,
const char *value)
{
+ struct ast_datastore *datastore = NULL;
+ struct denoise_info *di = NULL;
+ int is_new = 0;
+
+ if (!(datastore = ast_channel_datastore_find(chan, &denoise_datastore, NULL))) {
+ if (!(datastore = ast_channel_datastore_alloc(&denoise_datastore, NULL)))
+ return 0;
+ if (!(di = ast_calloc(1, sizeof(*di)))) {
+ ast_channel_datastore_free(datastore);
+ return 0;
+ }
+
+ ast_audiohook_init(&di->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "denoise");
+ di->audiohook.manipulate_callback = denoise_callback;
+
+ is_new = 1;
+ } else {
+ di = datastore->data;
+ }
+
+ if (!strcasecmp(data, "tx"))
+ di->tx_enabled = ast_true(value);
+ else if (!strcasecmp(data, "rx"))
+ di->rx_enabled = ast_true(value);
+
+ if (is_new) {
+ datastore->data = di;
+ ast_channel_datastore_add(chan, datastore);
+ ast_audiohook_attach(chan, &di->audiohook);
+ }
+
return 0;
}
More information about the asterisk-commits
mailing list