[asterisk-commits] dvossel: branch dvossel/hd_confbridge r310284 - /team/dvossel/hd_confbridge/b...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Mar 10 12:25:49 CST 2011
Author: dvossel
Date: Thu Mar 10 12:25:47 2011
New Revision: 310284
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=310284
Log:
Experimental change to how softmix mixes out a channel's own audio.
Modified:
team/dvossel/hd_confbridge/bridges/bridge_softmix.c
Modified: team/dvossel/hd_confbridge/bridges/bridge_softmix.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_confbridge/bridges/bridge_softmix.c?view=diff&rev=310284&r1=310283&r2=310284
==============================================================================
--- team/dvossel/hd_confbridge/bridges/bridge_softmix.c (original)
+++ team/dvossel/hd_confbridge/bridges/bridge_softmix.c Thu Mar 10 12:25:47 2011
@@ -60,12 +60,12 @@
/*! \brief Number of samples we are dealing with */
#define SOFTMIX_SAMPLES(rate) (SOFTMIX_DATALEN(rate) / 2)
-/*! \brief Number of mixing iterations to perform between
- * gathering statistics. */
-#define SOFTMIX_STAT_INTERVAL 50
-
-/*! \brief Define used to turn on 16 kHz audio support */
-/* #define SOFTMIX_16_SUPPORT */
+/*! \brief Number of mixing iterations to perform between gathering statistics. */
+#define SOFTMIX_STAT_INTERVAL 100
+
+/* This is the threshold in ms at which a channel's own audio will stop getting
+ * mixed out its own write audio stream because it is not talking. */
+#define SILENCE_THRESHOLD 4000
/*! \brief Structure which contains per-channel mixing information */
struct softmix_channel {
@@ -74,7 +74,13 @@
/*! Factory which contains audio read in from the channel */
struct ast_slinfactory factory;
/*! Frame that contains mixed audio to be written out to the channel */
- struct ast_frame frame;
+ struct ast_frame write_frame;
+ /*! Frame that contains mixed audio read from the channel */
+ struct ast_frame read_frame;
+ /*! DSP for detecting silence */
+ struct ast_dsp *dsp;
+ /*! The total amount of silence up until the last audio frame */
+ int totalsilence;
/*! Bit used to indicate that the channel provided audio for this mixing interval */
int have_audio:1;
/*! Bit used to indicate that a frame is available to be written out to the channel */
@@ -179,10 +185,33 @@
AST_LIST_TRAVERSE_SAFE_END;
}
-
/*!
* \internal
- * \brief Process a softmix channels write audio
+ * \brief Get the next available audio on the softmix channel's read stream
+ * and determine if it should be mixed out or not on the write stream.
+ *
+ * \retval pointer to buffer containing the exact number of samples requested on success.
+ * \retval NULL if no samples are present
+ */
+static int16_t *softmix_process_read_audio(struct softmix_channel *sc, unsigned int num_samples)
+{
+ sc->have_audio = 0;
+ if ((ast_slinfactory_available(&sc->factory) >= num_samples) &&
+ ast_slinfactory_read(&sc->factory, sc->our_buf, num_samples)) {
+ sc->totalsilence = 0;
+ ast_dsp_silence(sc->dsp, &sc->read_frame, &sc->totalsilence);
+ if (sc->totalsilence < SILENCE_THRESHOLD) {
+ sc->have_audio = 1; /* tell the write process we have audio to be mixed out */
+ }
+ ast_mutex_unlock(&sc->lock);
+ return sc->our_buf;
+ }
+ return NULL;
+}
+
+/*!
+ * \internal
+ * \brief Process a softmix channel's write audio
*
* \details This function will remove the channel's talking from its own audio if present and
* possibly even do the channel's write translation for it depending on how many other
@@ -195,9 +224,10 @@
struct softmix_translate_helper_entry *entry = NULL;
int i;
- /* If we provided audio then take it out while in slinear format. */
+ /* If we provided audio that was not determined to be silence,
+ * then take it out while in slinear format. */
if (sc->have_audio) {
- for (i = 0; i < sc->frame.samples; i++) {
+ for (i = 0; i < sc->write_frame.samples; i++) {
ast_slinear_saturated_subtract(&sc->final_buf[i], &sc->our_buf[i]);
}
/* do not do any special write translate optimization if we had to make
@@ -215,13 +245,13 @@
entry->trans_pvt = ast_translator_build_path(&entry->dst_format, &trans_helper->slin_src);
}
if (entry->trans_pvt && !entry->out_frame) {
- entry->out_frame = ast_translate(entry->trans_pvt, &sc->frame, 0);
+ entry->out_frame = ast_translate(entry->trans_pvt, &sc->write_frame, 0);
}
if (entry->out_frame && (entry->out_frame->datalen < MAX_DATALEN)) {
- ast_format_copy(&sc->frame.subclass.format, &entry->out_frame->subclass.format);
+ ast_format_copy(&sc->write_frame.subclass.format, &entry->out_frame->subclass.format);
memcpy(sc->final_buf, entry->out_frame->data.ptr, entry->out_frame->datalen);
- sc->frame.datalen = entry->out_frame->datalen;
- sc->frame.samples = entry->out_frame->samples;
+ sc->write_frame.datalen = entry->out_frame->datalen;
+ sc->write_frame.samples = entry->out_frame->samples;
}
break;
}
@@ -240,6 +270,7 @@
ast_frfree(entry->out_frame);
entry->out_frame = NULL;
}
+ entry->num_times_requested = 0;
}
}
@@ -287,20 +318,32 @@
ast_mutex_lock(&sc->lock);
if (reset) {
ast_slinfactory_destroy(&sc->factory);
- }
- /* Setup frame parameters */
- sc->frame.frametype = AST_FRAME_VOICE;
-
- ast_format_set(&sc->frame.subclass.format, ast_format_slin_by_rate(rate), 0);
- sc->frame.data.ptr = sc->final_buf;
- sc->frame.datalen = SOFTMIX_DATALEN(rate);
- sc->frame.samples = SOFTMIX_SAMPLES(rate);
+ ast_dsp_free(sc->dsp);
+ }
+ /* Setup read/write frame parameters */
+ sc->write_frame.frametype = AST_FRAME_VOICE;
+ ast_format_set(&sc->write_frame.subclass.format, ast_format_slin_by_rate(rate), 0);
+ sc->write_frame.data.ptr = sc->final_buf;
+ sc->write_frame.datalen = SOFTMIX_DATALEN(rate);
+ sc->write_frame.samples = SOFTMIX_SAMPLES(rate);
+
+ sc->read_frame.frametype = AST_FRAME_VOICE;
+ ast_format_set(&sc->read_frame.subclass.format, ast_format_slin_by_rate(rate), 0);
+ sc->read_frame.data.ptr = sc->our_buf;
+ sc->read_frame.datalen = SOFTMIX_DATALEN(rate);
+ sc->read_frame.samples = SOFTMIX_SAMPLES(rate);
+
/* Setup smoother */
- ast_slinfactory_init_with_format(&sc->factory, &sc->frame.subclass.format);
-
- ast_set_read_format(bridge_channel->chan, &sc->frame.subclass.format);
- ast_set_write_format(bridge_channel->chan, &sc->frame.subclass.format);
+ ast_slinfactory_init_with_format(&sc->factory, &sc->write_frame.subclass.format);
+
+ /* set new read and write formats on channel. */
+ ast_set_read_format(bridge_channel->chan, &sc->write_frame.subclass.format);
+ ast_set_write_format(bridge_channel->chan, &sc->write_frame.subclass.format);
+
+ /* set up new DSP */
+ sc->dsp = ast_dsp_new_with_rate(rate);
+
ast_mutex_unlock(&sc->lock);
}
@@ -341,6 +384,9 @@
/* Drop the factory */
ast_slinfactory_destroy(&sc->factory);
+
+ /* Drop the DSP */
+ ast_dsp_free(sc->dsp);
/* Eep! drop ourselves */
ast_free(sc);
@@ -375,7 +421,7 @@
/* If a frame is ready to be written out, do so */
if (sc->have_frame) {
- ast_write(bridge_channel->chan, &sc->frame);
+ ast_write(bridge_channel->chan, &sc->write_frame);
sc->have_frame = 0;
}
@@ -393,7 +439,7 @@
ast_mutex_lock(&sc->lock);
if (sc->have_frame) {
- ast_write(bridge_channel->chan, &sc->frame);
+ ast_write(bridge_channel->chan, &sc->write_frame);
sc->have_frame = 0;
}
@@ -621,12 +667,8 @@
/* Try to get audio from the factory if available */
ast_mutex_lock(&sc->lock);
- sc->have_audio = 0;
- if ((ast_slinfactory_available(&sc->factory) >= softmix_samples) &&
- ast_slinfactory_read(&sc->factory, sc->our_buf, softmix_samples)) {
- mixing_array.buffers[mixing_array.used_entries] = sc->our_buf;
+ if ((mixing_array.buffers[mixing_array.used_entries] = softmix_process_read_audio(sc, softmix_samples))) {
mixing_array.used_entries++;
- sc->have_audio = 1;
}
ast_mutex_unlock(&sc->lock);
}
@@ -650,11 +692,11 @@
ast_mutex_lock(&sc->lock);
/* Make SLINEAR write frame from local buffer */
- if (sc->frame.subclass.format.id != cur_slin_id) {
- ast_format_set(&sc->frame.subclass.format, cur_slin_id, 0);
- }
- sc->frame.datalen = softmix_datalen;
- sc->frame.samples = softmix_samples;
+ if (sc->write_frame.subclass.format.id != cur_slin_id) {
+ ast_format_set(&sc->write_frame.subclass.format, cur_slin_id, 0);
+ }
+ sc->write_frame.datalen = softmix_datalen;
+ sc->write_frame.samples = softmix_samples;
memcpy(sc->final_buf, buf, softmix_datalen);
/* process the softmix channel's new write audio */
@@ -721,11 +763,7 @@
if (!(softmix_bridge.format_capabilities = ast_format_cap_alloc())) {
return AST_MODULE_LOAD_DECLINE;
}
-#ifdef SOFTMIX_16_SUPPORT
- ast_format_cap_add(softmix_bridge.format_capabilities, ast_format_set(&tmp, AST_FORMAT_SLINEAR16, 0));
-#else
ast_format_cap_add(softmix_bridge.format_capabilities, ast_format_set(&tmp, AST_FORMAT_SLINEAR, 0));
-#endif
return ast_bridge_technology_register(&softmix_bridge);
}
More information about the asterisk-commits
mailing list