[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