[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