[asterisk-commits] dvossel: branch dvossel/hd_confbridge r310133 - in /team/dvossel/hd_confbridg...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Mar 8 15:32:31 CST 2011


Author: dvossel
Date: Tue Mar  8 15:32:24 2011
New Revision: 310133

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=310133
Log:
Addition of the 'drop_silence' ConfBridge option for removing silence from mixing

Modified:
    team/dvossel/hd_confbridge/apps/app_confbridge.c
    team/dvossel/hd_confbridge/apps/confbridge/conf_config_parser.c
    team/dvossel/hd_confbridge/apps/confbridge/include/confbridge.h
    team/dvossel/hd_confbridge/configs/confbridge.conf.sample
    team/dvossel/hd_confbridge/include/asterisk/bridging.h
    team/dvossel/hd_confbridge/include/asterisk/bridging_features.h
    team/dvossel/hd_confbridge/include/asterisk/dsp.h
    team/dvossel/hd_confbridge/main/bridging.c
    team/dvossel/hd_confbridge/main/dsp.c

Modified: team/dvossel/hd_confbridge/apps/app_confbridge.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_confbridge/apps/app_confbridge.c?view=diff&rev=310133&r1=310132&r2=310133
==============================================================================
--- team/dvossel/hd_confbridge/apps/app_confbridge.c (original)
+++ team/dvossel/hd_confbridge/apps/app_confbridge.c Tue Mar  8 15:32:24 2011
@@ -608,9 +608,13 @@
 	volume_adjustments[0] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_READ);
 	volume_adjustments[1] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_WRITE);
 
-		/* If the caller should be joined already muted, make it so */
+	/* If the caller should be joined already muted, make it so */
 	if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_STARTMUTED)) {
 		conference_bridge_user.features.mute = 1;
+	}
+
+	if (conference_bridge_user.u_profile.drop_silence) {
+		conference_bridge_user.features.detect_silence = conference_bridge_user.u_profile.drop_silence;
 	}
 
 	/* Grab join/leave sounds from the channel */

Modified: team/dvossel/hd_confbridge/apps/confbridge/conf_config_parser.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_confbridge/apps/confbridge/conf_config_parser.c?view=diff&rev=310133&r1=310132&r2=310133
==============================================================================
--- team/dvossel/hd_confbridge/apps/confbridge/conf_config_parser.c (original)
+++ team/dvossel/hd_confbridge/apps/confbridge/conf_config_parser.c Tue Mar  8 15:32:24 2011
@@ -35,6 +35,8 @@
 
 #define CONF_CONFIG "confbridge.conf"
 
+#define DEFAULT_SILENCE_THRESHOLD 3000  /* ms of silence before audio is dropped from mixing */
+
 static struct ao2_container *user_profiles;
 static struct ao2_container *bridge_profiles;
 static struct ao2_container *menus;
@@ -184,6 +186,7 @@
 	ao2_lock(u_profile);
 	/* set defaults */
 	u_profile->flags = 0;
+	u_profile->drop_silence = 0;
 	for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
 		if (!strcasecmp(var->name, "type")) {
 			continue;
@@ -219,6 +222,15 @@
 			u_profile->flags = ast_true(var->value) ?
 				u_profile->flags | USER_OPT_WAITMARKED :
 				u_profile->flags & ~USER_OPT_WAITMARKED;
+		} else if (!strcasecmp(var->name, "drop_silence")) {
+			if (ast_true(var->value)) {
+				u_profile->drop_silence = DEFAULT_SILENCE_THRESHOLD;
+			} else if (ast_false(var->value)) {
+				u_profile->drop_silence = 0;
+			} else if (sscanf(var->value, "%30u", &u_profile->drop_silence) != 1) {
+				ast_log(LOG_WARNING, "drop_silence '%s' at line %d of %s is not supported.\n",
+						var->value, var->lineno, CONF_CONFIG);
+			}
 		} else {
 			ast_log(LOG_WARNING, "Unknown option '%s' at line %d of %s is not supported.\n",
 				var->name, var->lineno, CONF_CONFIG);
@@ -418,6 +430,12 @@
 	ast_cli(a->fd,"Wait Marked:         %s\n",
 		u_profile.flags & USER_OPT_WAITMARKED ?
 		"enabled" : "disabled");
+	if (u_profile.drop_silence) {
+		ast_cli(a->fd,"Drop Silence:        %dms\n",
+			u_profile.drop_silence);
+	} else {
+		ast_cli(a->fd,"Drop Silence:        disabled\n");
+	}
 	ast_cli(a->fd,"\n");
 
 	return CLI_SUCCESS;

Modified: team/dvossel/hd_confbridge/apps/confbridge/include/confbridge.h
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_confbridge/apps/confbridge/include/confbridge.h?view=diff&rev=310133&r1=310132&r2=310133
==============================================================================
--- team/dvossel/hd_confbridge/apps/confbridge/include/confbridge.h (original)
+++ team/dvossel/hd_confbridge/apps/confbridge/include/confbridge.h Tue Mar  8 15:32:24 2011
@@ -85,6 +85,7 @@
 struct user_profile {
 	char name[64];
 	unsigned int flags;
+	unsigned int drop_silence; /*!< Number of ms of silence before dropping audio. If 0, never drop silence. */
 	int delme;
 };
 

Modified: team/dvossel/hd_confbridge/configs/confbridge.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_confbridge/configs/confbridge.conf.sample?view=diff&rev=310133&r1=310132&r2=310133
==============================================================================
--- team/dvossel/hd_confbridge/configs/confbridge.conf.sample (original)
+++ team/dvossel/hd_confbridge/configs/confbridge.conf.sample Tue Mar  8 15:32:24 2011
@@ -20,8 +20,19 @@
                           ; caller.  Off by default.
 ;announce_only_user=yes   ; Sets if the only user announcement should be played
                           ; when a channel enters a empty conference.  On by default.
-;wait_marked=yes      ; Sets if the user must wait for a marked user to enter before
-                      ; joining the conference. Off by default
+;wait_marked=yes   ; Sets if the user must wait for a marked user to enter before
+                   ; joining the conference. Off by default
+;drop_silence=yes      ; Sets if a channel's audio should be dropped from mixing
+                       ; after a certain number of milliseconds of silence is detected.
+                       ; Once the user begins talking audio will enter back into
+                       ; the bridge.  This option will improve the performance
+                       ; of the conference bridge when large numbers of people are present.
+                       ; By default this option is off.  When set to yes, audio will
+                       ; be dropped from conference bridge mixing after 3000 milliseconds
+                       ; (3 seconds) of silence is detected.  The number of 
+                       ; milliseconds can be configured as well by assigning
+                       ; this option the number of milliseconds to wait before detecting 
+                       ; silence instead of yes/no.
 
 [default_bridge]
 type=bridge

Modified: team/dvossel/hd_confbridge/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_confbridge/include/asterisk/bridging.h?view=diff&rev=310133&r1=310132&r2=310133
==============================================================================
--- team/dvossel/hd_confbridge/include/asterisk/bridging.h (original)
+++ team/dvossel/hd_confbridge/include/asterisk/bridging.h Tue Mar  8 15:32:24 2011
@@ -63,6 +63,7 @@
 #endif
 
 #include "asterisk/bridging_features.h"
+#include "asterisk/dsp.h"
 
 /*! \brief Capabilities for a bridge technology */
 enum ast_bridge_capability {
@@ -139,6 +140,8 @@
 	struct ast_bridge_features *features;
 	/*! Queue of DTMF digits used for DTMF streaming */
 	char dtmf_stream_q[8];
+	/*! DSP used for silence and noise detection */
+	struct ast_dsp *dsp;
 	/*! Linked list information */
 	AST_LIST_ENTRY(ast_bridge_channel) entry;
 };

Modified: team/dvossel/hd_confbridge/include/asterisk/bridging_features.h
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_confbridge/include/asterisk/bridging_features.h?view=diff&rev=310133&r1=310132&r2=310133
==============================================================================
--- team/dvossel/hd_confbridge/include/asterisk/bridging_features.h (original)
+++ team/dvossel/hd_confbridge/include/asterisk/bridging_features.h Tue Mar  8 15:32:24 2011
@@ -99,6 +99,10 @@
 	AST_LIST_HEAD_NOLOCK(, ast_bridge_features_hook) hooks;
 	/*! Feature flags that are enabled */
 	struct ast_flags feature_flags;
+	/*! The number of ms of silence before channel read audio is dropped as
+	 * silence from the bridge. When this varaible is 0, audio is never dropped
+	 * due to silence. */
+	unsigned int detect_silence;
 	/*! Bit to indicate that this structure is useful and should be considered when looking for features */
 	unsigned int usable:1;
 	/*! Bit to indicate whether the channel/bridge is muted or not */

Modified: team/dvossel/hd_confbridge/include/asterisk/dsp.h
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_confbridge/include/asterisk/dsp.h?view=diff&rev=310133&r1=310132&r2=310133
==============================================================================
--- team/dvossel/hd_confbridge/include/asterisk/dsp.h (original)
+++ team/dvossel/hd_confbridge/include/asterisk/dsp.h Tue Mar  8 15:32:24 2011
@@ -74,6 +74,10 @@
 struct ast_dsp *ast_dsp_new(void);
 
 void ast_dsp_free(struct ast_dsp *dsp);
+
+/*! \brief Retrieve the sample rate this DSP structure was
+ * created with */
+unsigned int ast_dsp_get_sample_rate(const struct ast_dsp *dsp);
 
 /*! \brief Set threshold value for silence */
 void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold);

Modified: team/dvossel/hd_confbridge/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_confbridge/main/bridging.c?view=diff&rev=310133&r1=310132&r2=310133
==============================================================================
--- team/dvossel/hd_confbridge/main/bridging.c (original)
+++ team/dvossel/hd_confbridge/main/bridging.c Tue Mar  8 15:32:24 2011
@@ -273,6 +273,48 @@
 	}
 }
 
+/*!
+ * \internal
+ *
+ * \brief This function places itself in the middle of the channel's read audio
+ * path to allow the bridge to perform preprocessing audio features before
+ * the bridging technology see's the frame.
+ *
+ * \note This function expects the frame to be in slinear format.
+ * \note 
+ *
+ * \retval frame after preprocessing is complete.
+ */
+static struct ast_frame *bridge_channel_preprocess_read_audio(struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
+{
+	int detect_silence = MAX(bridge_channel->bridge->features.detect_silence, (bridge_channel->features ? bridge_channel->features->detect_silence : 0));
+
+	if (detect_silence) {
+		int totalsilence = 0;
+		/* make sure we have a dsp for the correct sample rate. A change in sample rate in a
+		 * single direction does not happen often, but our DSP needs to be made aware of such a change. */
+		if (bridge_channel->dsp &&
+			(ast_dsp_get_sample_rate(bridge_channel->dsp) != ast_format_rate(&frame->subclass.format))) {
+
+			ast_dsp_free(bridge_channel->dsp);
+			bridge_channel->dsp = NULL;
+		}
+		if (!bridge_channel->dsp && !(bridge_channel->dsp = ast_dsp_new_with_rate(ast_format_rate(&frame->subclass.format)))) {
+			return frame;
+		}
+
+		/* if silence is detected and the total is above the threshold, drop the audio */
+		if (ast_dsp_silence(bridge_channel->dsp, frame, &totalsilence) &&
+			(totalsilence > detect_silence)) {
+
+			ast_frfree(frame);
+			return &ast_null_frame;
+		}
+	}
+
+	return frame;
+}
+
 void ast_bridge_handle_trip(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_channel *chan, int outfd)
 {
 	/* If no bridge channel has been provided and the actual channel has been provided find it */
@@ -293,6 +335,8 @@
 		} else {
 			if (frame->frametype == AST_FRAME_DTMF_BEGIN) {
 				frame = bridge_handle_dtmf(bridge, bridge_channel, frame);
+			} else if (frame->frametype == AST_FRAME_VOICE && ast_format_is_slinear(&frame->subclass.format)) {
+				frame = bridge_channel_preprocess_read_audio(bridge_channel, frame);
 			}
 			/* Simply write the frame out to the bridge technology if it still exists */
 			if (frame) {
@@ -1021,6 +1065,17 @@
 	return state;
 }
 
+static struct ast_bridge_channel *free_bridge_channel(struct ast_bridge_channel *bridge_channel)
+{
+	/* Destroy elements of the bridge channel structure and the bridge channel structure itself */
+	ast_dsp_free(bridge_channel->dsp);
+	ast_mutex_destroy(&bridge_channel->lock);
+	ast_cond_destroy(&bridge_channel->cond);
+
+	ast_free(bridge_channel);
+	return NULL;
+}
+
 /*! \brief Thread responsible for imparted bridged channels */
 static void *bridge_channel_thread(void *data)
 {
@@ -1036,10 +1091,7 @@
 		ast_hangup(bridge_channel->chan);
 	}
 
-	/* Destroy elements of the bridge channel structure and the bridge channel structure itself */
-	ast_mutex_destroy(&bridge_channel->lock);
-	ast_cond_destroy(&bridge_channel->cond);
-	ast_free(bridge_channel);
+	free_bridge_channel(bridge_channel);
 
 	return NULL;
 }
@@ -1069,9 +1121,7 @@
 	/* Actually create the thread that will handle the channel */
 	if (ast_pthread_create(&bridge_channel->thread, NULL, bridge_channel_thread, bridge_channel)) {
 		ao2_ref(bridge, -1);
-		ast_cond_destroy(&bridge_channel->cond);
-		ast_mutex_destroy(&bridge_channel->lock);
-		ast_free(bridge_channel);
+		free_bridge_channel(bridge_channel);
 		return -1;
 	}
 

Modified: team/dvossel/hd_confbridge/main/dsp.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_confbridge/main/dsp.c?view=diff&rev=310133&r1=310132&r2=310133
==============================================================================
--- team/dvossel/hd_confbridge/main/dsp.c (original)
+++ team/dvossel/hd_confbridge/main/dsp.c Tue Mar  8 15:32:24 2011
@@ -1516,6 +1516,11 @@
 	dsp->ringtimeout= 0;
 }
 
+unsigned int ast_dsp_get_sample_rate(const struct ast_dsp *dsp)
+{
+	return dsp->sample_rate;
+}
+
 static struct ast_dsp *__ast_dsp_new(unsigned int sample_rate)
 {
 	struct ast_dsp *dsp;




More information about the asterisk-commits mailing list