[asterisk-commits] dvossel: branch dvossel/hd_conferencing_ftw r308149 - in /team/dvossel/hd_con...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Feb 16 13:00:08 CST 2011


Author: dvossel
Date: Wed Feb 16 13:00:04 2011
New Revision: 308149

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=308149
Log:
Internal AudioHook Whisper and Spy sample rate adjusts depending on audio sources

Modified:
    team/dvossel/hd_conferencing_ftw/funcs/func_pitchshift.c
    team/dvossel/hd_conferencing_ftw/funcs/func_speex.c
    team/dvossel/hd_conferencing_ftw/funcs/func_volume.c
    team/dvossel/hd_conferencing_ftw/include/asterisk/audiohook.h
    team/dvossel/hd_conferencing_ftw/main/audiohook.c
    team/dvossel/hd_conferencing_ftw/main/slinfactory.c
    team/dvossel/hd_conferencing_ftw/res/res_mutestream.c

Modified: team/dvossel/hd_conferencing_ftw/funcs/func_pitchshift.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_conferencing_ftw/funcs/func_pitchshift.c?view=diff&rev=308149&r1=308148&r2=308149
==============================================================================
--- team/dvossel/hd_conferencing_ftw/funcs/func_pitchshift.c (original)
+++ team/dvossel/hd_conferencing_ftw/funcs/func_pitchshift.c Wed Feb 16 13:00:04 2011
@@ -208,7 +208,7 @@
 			return 0;
 		}
 
-		ast_audiohook_init(&shift->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "pitch_shift", AST_AUDIOHOOK_NATIVE_SLIN_CAPABLE);
+		ast_audiohook_init(&shift->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "pitch_shift", AST_AUDIOHOOK_MANIPULATE_ALL_RATES);
 		shift->audiohook.manipulate_callback = pitchshift_cb;
 		datastore->data = shift;
 		new = 1;

Modified: team/dvossel/hd_conferencing_ftw/funcs/func_speex.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_conferencing_ftw/funcs/func_speex.c?view=diff&rev=308149&r1=308148&r2=308149
==============================================================================
--- team/dvossel/hd_conferencing_ftw/funcs/func_speex.c (original)
+++ team/dvossel/hd_conferencing_ftw/funcs/func_speex.c Wed Feb 16 13:00:04 2011
@@ -214,7 +214,7 @@
 			return 0;
 		}
 
-		ast_audiohook_init(&si->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "speex", AST_AUDIOHOOK_NATIVE_SLIN_CAPABLE);
+		ast_audiohook_init(&si->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "speex", AST_AUDIOHOOK_MANIPULATE_ALL_RATES);
 		si->audiohook.manipulate_callback = speex_callback;
 		si->lastrate = 8000;
 		is_new = 1;

Modified: team/dvossel/hd_conferencing_ftw/funcs/func_volume.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_conferencing_ftw/funcs/func_volume.c?view=diff&rev=308149&r1=308148&r2=308149
==============================================================================
--- team/dvossel/hd_conferencing_ftw/funcs/func_volume.c (original)
+++ team/dvossel/hd_conferencing_ftw/funcs/func_volume.c Wed Feb 16 13:00:04 2011
@@ -132,7 +132,7 @@
 			ast_datastore_free(datastore);
 			return 0;
 		}
-		ast_audiohook_init(&vi->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "Volume", AST_AUDIOHOOK_NATIVE_SLIN_CAPABLE);
+		ast_audiohook_init(&vi->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "Volume", AST_AUDIOHOOK_MANIPULATE_ALL_RATES);
 		vi->audiohook.manipulate_callback = volume_callback;
 		ast_set_flag(&vi->audiohook, AST_AUDIOHOOK_WANTS_DTMF);
 		is_new = 1;

Modified: team/dvossel/hd_conferencing_ftw/include/asterisk/audiohook.h
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_conferencing_ftw/include/asterisk/audiohook.h?view=diff&rev=308149&r1=308148&r2=308149
==============================================================================
--- team/dvossel/hd_conferencing_ftw/include/asterisk/audiohook.h (original)
+++ team/dvossel/hd_conferencing_ftw/include/asterisk/audiohook.h Wed Feb 16 13:00:04 2011
@@ -66,11 +66,14 @@
 };
 
 enum ast_audiohook_init_flags {
-	/* Audiohook is capable of handling slinear at any sample rate */
-	AST_AUDIOHOOK_NATIVE_SLIN_CAPABLE = (1 << 0),
-};
-
-#define AST_AUDIOHOOK_SYNC_TOLERANCE 100 /*< Tolerance in milliseconds for audiohooks synchronization */
+	/* Audiohook manipulate callback is capable of handling slinear at any sample rate.
+	 * Without enabling this flag on initialization the manipulation callback is guaranteed
+	 * 8khz audio only. */
+	AST_AUDIOHOOK_MANIPULATE_ALL_RATES = (1 << 0),
+};
+
+#define AST_AUDIOHOOK_SYNC_TOLERANCE 100 /*!< Tolerance in milliseconds for audiohooks synchronization */
+#define AST_AUDIOHOOK_SMALL_QUEUE_TOLERANCE 100 /*!< When small queue is enabled, this is the maximum amount of audio that can remain queued at a time. */
 
 struct ast_audiohook;
 
@@ -113,6 +116,9 @@
 	struct ast_trans_pvt *trans_pvt;                       /*!< Translation path for reading frames */
 	ast_audiohook_manipulate_callback manipulate_callback; /*!< Manipulation callback */
 	struct ast_audiohook_options options;                  /*!< Applicable options */
+	int last_read_rate;                  /*!< The last sample rate used when writing in the read direction to the audiohook. */
+	int last_write_rate;                 /*!< The last sample rate used when writing in the write direction to the audiohook. */
+	int internal_read_write_rate;        /*!< internal read/write rate is the MAX(last_read_rate, last_write_rate) */
 	AST_LIST_ENTRY(ast_audiohook) list;                    /*!< Linked list information */
 };
 

Modified: team/dvossel/hd_conferencing_ftw/main/audiohook.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_conferencing_ftw/main/audiohook.c?view=diff&rev=308149&r1=308148&r2=308149
==============================================================================
--- team/dvossel/hd_conferencing_ftw/main/audiohook.c (original)
+++ team/dvossel/hd_conferencing_ftw/main/audiohook.c Wed Feb 16 13:00:04 2011
@@ -56,6 +56,55 @@
 	AST_LIST_HEAD_NOLOCK(, ast_audiohook) manipulate_list;
 };
 
+static int audiohook_set_internal_rate(struct ast_audiohook *audiohook, int reset)
+{
+	struct ast_format slin;
+	int rate = MAX(audiohook->last_read_rate, audiohook->last_write_rate);
+
+	if (audiohook->internal_read_write_rate == rate) {
+		return 0;
+	}
+
+	audiohook->internal_read_write_rate = rate;
+
+	ast_format_set(&slin, ast_format_slin_by_rate(rate), 0);
+	/* Setup the factories that are needed for this audiohook type */
+	switch (audiohook->type) {
+	case AST_AUDIOHOOK_TYPE_SPY:
+		if (reset) {
+			ast_slinfactory_destroy(&audiohook->read_factory);
+		}
+		ast_slinfactory_init_with_format(&audiohook->read_factory, &slin);
+		/* fall through */
+	case AST_AUDIOHOOK_TYPE_WHISPER:
+		if (reset) {
+			ast_slinfactory_destroy(&audiohook->write_factory);
+		}
+		ast_slinfactory_init_with_format(&audiohook->write_factory, &slin);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int audiohook_update_rate(struct ast_audiohook *audiohook, enum ast_audiohook_direction direction, int rate)
+{
+	switch (direction) {
+	case AST_AUDIOHOOK_DIRECTION_READ:
+		audiohook->last_read_rate = rate;
+		break;
+	case AST_AUDIOHOOK_DIRECTION_WRITE:
+		audiohook->last_write_rate = rate;
+		break;
+	case AST_AUDIOHOOK_DIRECTION_BOTH:
+		audiohook->last_read_rate = rate;
+		audiohook->last_write_rate = rate;
+		break;
+	}
+	return audiohook_set_internal_rate(audiohook, 1);
+}
+
 /*! \brief Initialize an audiohook structure
  * \param audiohook Audiohook structure
  * \param type
@@ -72,18 +121,11 @@
 	ast_mutex_init(&audiohook->lock);
 	ast_cond_init(&audiohook->trigger, NULL);
 
-	/* Setup the factories that are needed for this audiohook type */
-	switch (type) {
-	case AST_AUDIOHOOK_TYPE_SPY:
-		ast_slinfactory_init(&audiohook->read_factory);
-	case AST_AUDIOHOOK_TYPE_WHISPER:
-		ast_slinfactory_init(&audiohook->write_factory);
-		break;
-	default:
-		break;
-	}
-
 	audiohook->init_flags = init_flags;
+	/* initialize internal rate at 8khz, this will adjust if necessary */
+	audiohook->last_read_rate = audiohook->last_write_rate = 8000;
+
+	audiohook_set_internal_rate(audiohook, 0);
 
 	/* Since we are just starting out... this audiohook is new */
 	ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_NEW);
@@ -140,9 +182,9 @@
 	*rwtime = ast_tvnow();
 
 	our_factory_samples = ast_slinfactory_available(factory);
-	our_factory_ms = ast_tvdiff_ms(*rwtime, previous_time) + (our_factory_samples / 8);
+	our_factory_ms = ast_tvdiff_ms(*rwtime, previous_time) + (our_factory_samples / (audiohook->internal_read_write_rate / 1000));
 	other_factory_samples = ast_slinfactory_available(other_factory);
-	other_factory_ms = other_factory_samples / 8;
+	other_factory_ms = other_factory_samples / (audiohook->internal_read_write_rate / 1000);
 
 	if (ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC) && other_factory_samples && (our_factory_ms - other_factory_ms > AST_AUDIOHOOK_SYNC_TOLERANCE)) {
 		ast_debug(1, "Flushing audiohook %p so it remains in sync\n", audiohook);
@@ -150,7 +192,7 @@
 		ast_slinfactory_flush(other_factory);
 	}
 
-	if (ast_test_flag(audiohook, AST_AUDIOHOOK_SMALL_QUEUE) && (our_factory_samples > 640 || other_factory_samples > 640)) {
+	if (ast_test_flag(audiohook, AST_AUDIOHOOK_SMALL_QUEUE) && ((our_factory_ms > AST_AUDIOHOOK_SMALL_QUEUE_TOLERANCE) || (other_factory_ms > AST_AUDIOHOOK_SMALL_QUEUE_TOLERANCE))) {
 		ast_debug(1, "Audiohook %p has stale audio in its factories. Flushing them both\n", audiohook);
 		ast_slinfactory_flush(factory);
 		ast_slinfactory_flush(other_factory);
@@ -193,7 +235,7 @@
 		.datalen = sizeof(buf),
 		.samples = samples,
 	};
-	ast_format_set(&frame.subclass.format, AST_FORMAT_SLINEAR, 0);
+	ast_format_set(&frame.subclass.format, ast_format_slin_by_rate(audiohook->internal_read_write_rate), 0);
 
 	/* Ensure the factory is able to give us the samples we want */
 	if (samples > ast_slinfactory_available(factory))
@@ -220,7 +262,7 @@
 		.datalen = sizeof(buf1),
 		.samples = samples,
 	};
-	ast_format_set(&frame.subclass.format, AST_FORMAT_SLINEAR, 0);
+	ast_format_set(&frame.subclass.format, ast_format_slin_by_rate(audiohook->internal_read_write_rate), 0);
 
 	/* Make sure both factories have the required samples */
 	usable_read = (ast_slinfactory_available(&audiohook->read_factory) >= samples ? 1 : 0);
@@ -303,7 +345,7 @@
 
 /*! \brief Reads a frame in from the audiohook structure
  * \param audiohook Audiohook structure
- * \param samples Number of samples wanted
+ * \param samples Number of samples wanted in requested output format
  * \param direction Direction the audio frame came from
  * \param format Format of frame remote side wants back
  * \return Returns frame on success, NULL on failure
@@ -312,23 +354,39 @@
 {
 	struct ast_frame *read_frame = NULL, *final_frame = NULL;
 	struct ast_format tmp_fmt;
-
-	if (!(read_frame = (direction == AST_AUDIOHOOK_DIRECTION_BOTH ? audiohook_read_frame_both(audiohook, samples) : audiohook_read_frame_single(audiohook, samples, direction))))
+	int samples_converted;
+
+	/* the number of samples requested is based on the format they are requesting.  Inorder
+	 * to process this correctly samples must be converted to our internal sample rate */
+	if (audiohook->internal_read_write_rate == ast_format_rate(format)) {
+		samples_converted = samples;
+	} else if (audiohook->internal_read_write_rate > ast_format_rate(format)) {
+		samples_converted = samples * (audiohook->internal_read_write_rate / (float) ast_format_rate(format));
+	} else {
+		samples_converted = samples * (ast_format_rate(format) / (float) audiohook->internal_read_write_rate);
+	}
+
+	if (!(read_frame = (direction == AST_AUDIOHOOK_DIRECTION_BOTH ?
+		audiohook_read_frame_both(audiohook, samples_converted) :
+		audiohook_read_frame_single(audiohook, samples_converted, direction)))) {
 		return NULL;
+	}
 
 	/* If they don't want signed linear back out, we'll have to send it through the translation path */
-	if (format->id != AST_FORMAT_SLINEAR) {
+	if (format->id != ast_format_slin_by_rate(audiohook->internal_read_write_rate)) {
 		/* Rebuild translation path if different format then previously */
 		if (ast_format_cmp(format, &audiohook->format) == AST_FORMAT_CMP_NOT_EQUAL) {
 			if (audiohook->trans_pvt) {
 				ast_translator_free_path(audiohook->trans_pvt);
 				audiohook->trans_pvt = NULL;
 			}
+
 			/* Setup new translation path for this format... if we fail we can't very well return signed linear so free the frame and return nothing */
-			if (!(audiohook->trans_pvt = ast_translator_build_path(format, ast_format_set(&tmp_fmt, AST_FORMAT_SLINEAR, 0)))) {
+			if (!(audiohook->trans_pvt = ast_translator_build_path(format, ast_format_set(&tmp_fmt, ast_format_slin_by_rate(audiohook->internal_read_write_rate), 0)))) {
 				ast_frfree(read_frame);
 				return NULL;
 			}
+			ast_format_copy(&audiohook->format, format);
 		}
 		/* Convert to requested format, and allow the read in frame to be freed */
 		final_frame = ast_translate(audiohook->trans_pvt, read_frame, 1);
@@ -343,20 +401,8 @@
 {
 	struct ast_audiohook *ah = NULL;
 	audiohook_list->native_slin_compatible = 1;
-	AST_LIST_TRAVERSE(&audiohook_list->spy_list, ah, list) {
-		if (!(ah->init_flags & AST_AUDIOHOOK_NATIVE_SLIN_CAPABLE)) {
-			audiohook_list->native_slin_compatible = 0;
-			return;
-		}
-	}
-	AST_LIST_TRAVERSE(&audiohook_list->whisper_list, ah, list) {
-		if (!(ah->init_flags & AST_AUDIOHOOK_NATIVE_SLIN_CAPABLE)) {
-			audiohook_list->native_slin_compatible = 0;
-			return;
-		}
-	}
 	AST_LIST_TRAVERSE(&audiohook_list->manipulate_list, ah, list) {
-		if (!(ah->init_flags & AST_AUDIOHOOK_NATIVE_SLIN_CAPABLE)) {
+		if (!(ah->init_flags & AST_AUDIOHOOK_MANIPULATE_ALL_RATES)) {
 			audiohook_list->native_slin_compatible = 0;
 			return;
 		}
@@ -731,6 +777,7 @@
 			ast_audiohook_unlock(audiohook);
 			continue;
 		}
+		audiohook_update_rate(audiohook, direction, ast_format_rate(&middle_frame->subclass.format));
 		ast_audiohook_write_frame(audiohook, direction, middle_frame);
 		ast_audiohook_unlock(audiohook);
 	}
@@ -750,6 +797,7 @@
 				ast_audiohook_unlock(audiohook);
 				continue;
 			}
+			audiohook_update_rate(audiohook, direction, ast_format_rate(&middle_frame->subclass.format));
 			if (ast_slinfactory_available(&audiohook->write_factory) >= samples && ast_slinfactory_read(&audiohook->write_factory, read_buf, samples)) {
 				/* Take audio from this whisper source and combine it into our main buffer */
 				for (i = 0, data1 = combine_buf, data2 = read_buf; i < samples; i++, data1++, data2++)
@@ -1037,7 +1085,7 @@
 	}
 
 	/* Setup our audiohook structure so we can manipulate the audio */
-	ast_audiohook_init(&audiohook_volume->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "Volume", AST_AUDIOHOOK_NATIVE_SLIN_CAPABLE);
+	ast_audiohook_init(&audiohook_volume->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "Volume", AST_AUDIOHOOK_MANIPULATE_ALL_RATES);
 	audiohook_volume->audiohook.manipulate_callback = audiohook_volume_callback;
 
 	/* Attach the audiohook_volume blob to the datastore and attach to the channel */

Modified: team/dvossel/hd_conferencing_ftw/main/slinfactory.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_conferencing_ftw/main/slinfactory.c?view=diff&rev=308149&r1=308148&r2=308149
==============================================================================
--- team/dvossel/hd_conferencing_ftw/main/slinfactory.c (original)
+++ team/dvossel/hd_conferencing_ftw/main/slinfactory.c Wed Feb 16 13:00:04 2011
@@ -87,8 +87,11 @@
 
 		if (!sf->trans) {
 			if (!(sf->trans = ast_translator_build_path(&sf->output_format, &f->subclass.format))) {
-				ast_log(LOG_WARNING, "Cannot build a path from %s to %s\n", ast_getformatname(&f->subclass.format),
-					ast_getformatname(&sf->output_format));
+				ast_log(LOG_WARNING, "Cannot build a path from %s (%d)to %s (%d)\n",
+					ast_getformatname(&f->subclass.format),
+					f->subclass.format.id,
+					ast_getformatname(&sf->output_format),
+					sf->output_format.id);
 				return 0;
 			}
 			ast_format_copy(&sf->format, &f->subclass.format);

Modified: team/dvossel/hd_conferencing_ftw/res/res_mutestream.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/hd_conferencing_ftw/res/res_mutestream.c?view=diff&rev=308149&r1=308148&r2=308149
==============================================================================
--- team/dvossel/hd_conferencing_ftw/res/res_mutestream.c (original)
+++ team/dvossel/hd_conferencing_ftw/res/res_mutestream.c Wed Feb 16 13:00:04 2011
@@ -173,7 +173,7 @@
 		ast_datastore_free(datastore);
 		return NULL;
 	}
-	ast_audiohook_init(&mute->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "Mute", AST_AUDIOHOOK_NATIVE_SLIN_CAPABLE);
+	ast_audiohook_init(&mute->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "Mute", AST_AUDIOHOOK_MANIPULATE_ALL_RATES);
 	mute->audiohook.manipulate_callback = mute_callback;
 	datastore->data = mute;
 	return datastore;




More information about the asterisk-commits mailing list