From d6a0abf1db5b9d7dc19a68bab22da6340e23a853 Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthm@freeswitch.org>
Date: Fri, 12 Jun 2015 23:55:24 -0500
Subject: [PATCH] FS-7654 #resolve

---
 src/include/switch_resample.h |  4 ++--
 src/switch_core_io.c          | 27 ++++++++++++++++++---------
 src/switch_ivr_async.c        | 34 +++++++++++++++++++++++++++-------
 src/switch_resample.c         | 12 ++++++++----
 4 files changed, 55 insertions(+), 22 deletions(-)

diff --git a/src/include/switch_resample.h b/src/include/switch_resample.h
index eb1a30e5cb..b3fb436c86 100644
--- a/src/include/switch_resample.h
+++ b/src/include/switch_resample.h
@@ -171,8 +171,8 @@ SWITCH_DECLARE(void) switch_change_sln_volume(int16_t *data, uint32_t samples, i
 SWITCH_DECLARE(void) switch_change_sln_volume_granular(int16_t *data, uint32_t samples, int32_t vol);
 ///\}
 
-SWITCH_DECLARE(uint32_t) switch_merge_sln(int16_t *data, uint32_t samples, int16_t *other_data, uint32_t other_samples);
-SWITCH_DECLARE(uint32_t) switch_unmerge_sln(int16_t *data, uint32_t samples, int16_t *other_data, uint32_t other_samples);
+SWITCH_DECLARE(uint32_t) switch_merge_sln(int16_t *data, uint32_t samples, int16_t *other_data, uint32_t other_samples, int channels);
+SWITCH_DECLARE(uint32_t) switch_unmerge_sln(int16_t *data, uint32_t samples, int16_t *other_data, uint32_t other_samples, int channels);
 SWITCH_DECLARE(void) switch_mux_channels(int16_t *data, switch_size_t samples, uint32_t orig_channels, uint32_t channels);
 
 #define switch_resample_calc_buffer_size(_to, _from, _srclen) ((uint32_t)(((float)_to / (float)_from) * (float)_srclen) * 2)
diff --git a/src/switch_core_io.c b/src/switch_core_io.c
index fce2f41df7..64c0d11593 100644
--- a/src/switch_core_io.c
+++ b/src/switch_core_io.c
@@ -496,6 +496,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
 													  session->read_impl.actual_samples_per_second,
 													  session->raw_read_frame.data, &session->raw_read_frame.datalen, &session->raw_read_frame.rate, 
 													  &read_frame->flags);
+
+					session->raw_read_frame.samples = session->raw_read_frame.datalen / 2;
+					session->raw_read_frame.channels = codec->implementation->number_of_channels;
 					codec->cur_frame = NULL;
 					session->read_codec->cur_frame = NULL;
 					switch_thread_rwlock_unlock(session->bug_rwlock);
@@ -521,14 +524,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
 			}
 
 			/* mux or demux to match */
-			if (session->read_impl.number_of_channels != read_frame->codec->implementation->number_of_channels) {
-				uint32_t rlen = session->raw_read_frame.datalen / 2 / read_frame->codec->implementation->number_of_channels;
-				//switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s MUX READ\n", switch_channel_get_name(session->channel));
-				switch_mux_channels((int16_t *) session->raw_read_frame.data, rlen, 
-									read_frame->codec->implementation->number_of_channels, session->read_impl.number_of_channels);
-				session->raw_write_frame.datalen = rlen * 2 * session->read_impl.number_of_channels;
+			if (session->raw_read_frame.channels != session->read_impl.number_of_channels) {
+				uint32_t rlen = session->raw_read_frame.datalen / 2 / session->raw_read_frame.channels;
+				switch_mux_channels((int16_t *) session->raw_read_frame.data, rlen, session->raw_read_frame.channels, session->read_impl.number_of_channels);
+				session->raw_read_frame.datalen = rlen * 2 * session->read_impl.number_of_channels;
+				session->raw_read_frame.samples = session->raw_read_frame.datalen / 2;
+				session->raw_read_frame.channels = session->read_impl.number_of_channels;
 			}
 
+
 			switch (status) {
 			case SWITCH_STATUS_RESAMPLE:
 				if (!session->read_resampler) {
@@ -709,11 +713,16 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
 					switch_mutex_lock(bp->read_mutex);
 					if (bp->read_demux_frame) {
 						uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE];
-						int bytes = read_frame->datalen / 2;
+						int bytes = read_frame->datalen;
+						uint32_t datalen = 0;
+						uint32_t samples = bytes / 2 / bp->read_demux_frame->channels;
 
 						memcpy(data, read_frame->data, read_frame->datalen);
-						switch_unmerge_sln((int16_t *)data, bytes, bp->read_demux_frame->data, bytes);
-						switch_buffer_write(bp->raw_read_buffer, data, read_frame->datalen);
+						datalen = switch_unmerge_sln((int16_t *)data, samples, 
+													 bp->read_demux_frame->data, samples, 
+													 bp->read_demux_frame->channels) * 2 * bp->read_demux_frame->channels;
+
+						switch_buffer_write(bp->raw_read_buffer, data, datalen);
 					} else {
 						switch_buffer_write(bp->raw_read_buffer, read_frame->data, read_frame->datalen);
 					}
diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c
index 6baefb2d55..22fe4b7d52 100644
--- a/src/switch_ivr_async.c
+++ b/src/switch_ivr_async.c
@@ -1566,6 +1566,8 @@ struct eavesdrop_pvt {
 	switch_frame_t demux_frame;
 	int set_decoded_read;
 	int errs;
+	switch_codec_implementation_t read_impl;
+	switch_codec_implementation_t tread_impl;
 	uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE];
 };
 
@@ -1666,18 +1668,21 @@ static switch_bool_t eavesdrop_callback(switch_media_bug_t *bug, void *user_data
 					switch_buffer_lock(ep->r_buffer);
 					bytes = (uint32_t) switch_buffer_read(ep->r_buffer, ep->data, rframe->datalen);
 
-					rframe->datalen = switch_merge_sln(rframe->data, rframe->samples, (int16_t *) ep->data, bytes / 2) * 2;
+					memcpy(rframe->data, ep->data, rframe->datalen);
+					rframe->datalen = switch_merge_sln(rframe->data, rframe->samples, (int16_t *) ep->data, bytes / 2, rframe->channels) * 2 * rframe->channels;
 					rframe->samples = rframe->datalen / 2;
 
 					ep->demux_frame.data = ep->data;
 					ep->demux_frame.datalen = bytes;
 					ep->demux_frame.samples = bytes / 2;
-					
+					ep->demux_frame.channels = rframe->channels;
+
 					switch_buffer_unlock(ep->r_buffer);
 					switch_core_media_bug_set_read_replace_frame(bug, rframe);
 					switch_core_media_bug_set_read_demux_frame(bug, &ep->demux_frame);
 				}
 			}
+
 		}
 		break;
 
@@ -1691,7 +1696,7 @@ static switch_bool_t eavesdrop_callback(switch_media_bug_t *bug, void *user_data
 					switch_buffer_lock(ep->w_buffer);
 					bytes = (uint32_t) switch_buffer_read(ep->w_buffer, data, rframe->datalen);
 
-					rframe->datalen = switch_merge_sln(rframe->data, rframe->samples, (int16_t *) data, bytes / 2) * 2;
+					rframe->datalen = switch_merge_sln(rframe->data, rframe->samples, (int16_t *) data, bytes / 2, rframe->channels) * 2 * rframe->channels;
 					rframe->samples = rframe->datalen / 2;
 
 					switch_buffer_unlock(ep->w_buffer);
@@ -1853,6 +1858,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
 		uint32_t sanity = 600;
 		switch_media_bug_flag_t read_flags = 0, write_flags = 0;
 		const char *vval;
+		int buf_size = 0;
 
 		if (!switch_channel_media_up(channel)) {
 			goto end;
@@ -1935,6 +1941,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
 			goto end;
 		}
 
+		switch_core_session_get_read_impl(session, &read_impl);
+
+		ep->read_impl = read_impl;
+		ep->tread_impl = tread_impl;
+
 		codec_initialized = 1;
 
 		switch_core_session_set_read_codec(session, &codec);
@@ -1942,24 +1953,26 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
 		write_frame.data = buf;
 		write_frame.buflen = sizeof(buf);
 		write_frame.rate = codec.implementation->actual_samples_per_second;
-
+		
 		/* Make sure that at least one leg is bridged, default to both */
 		if (! (flags & (ED_BRIDGE_READ | ED_BRIDGE_WRITE))) {
 			flags |= ED_BRIDGE_READ | ED_BRIDGE_WRITE;
 		}
 
+		buf_size = codec.implementation->decoded_bytes_per_packet * 10;
+
 		ep->eavesdropper = session;
 		ep->flags = flags;
 		switch_mutex_init(&ep->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession));
-		switch_buffer_create_dynamic(&ep->buffer, 2048, 2048, 8192);
+		switch_buffer_create_dynamic(&ep->buffer, buf_size, buf_size, buf_size);
 		switch_buffer_add_mutex(ep->buffer, ep->mutex);
 
 		switch_mutex_init(&ep->w_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession));
-		switch_buffer_create_dynamic(&ep->w_buffer, 2048, 2048, 8192);
+		switch_buffer_create_dynamic(&ep->w_buffer, buf_size, buf_size, buf_size);
 		switch_buffer_add_mutex(ep->w_buffer, ep->w_mutex);
 
 		switch_mutex_init(&ep->r_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession));
-		switch_buffer_create_dynamic(&ep->r_buffer, 2048, 2048, 8192);
+		switch_buffer_create_dynamic(&ep->r_buffer, buf_size, buf_size, buf_size);
 		switch_buffer_add_mutex(ep->r_buffer, ep->r_mutex);
 
 		if (flags & ED_BRIDGE_READ) {
@@ -2178,6 +2191,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
 					write_frame.datalen = (uint32_t) switch_buffer_read(ep->buffer, buf, len);
 					write_frame.samples = write_frame.datalen / 2;
 
+					if (ep->tread_impl.number_of_channels != ep->read_impl.number_of_channels) {
+						uint32_t rlen = write_frame.datalen / 2 / ep->tread_impl.number_of_channels;
+						switch_mux_channels((int16_t *) write_frame.data, rlen, ep->tread_impl.number_of_channels, ep->read_impl.number_of_channels);
+						write_frame.datalen = rlen * 2 * ep->read_impl.number_of_channels;
+						write_frame.samples = write_frame.datalen / 2;
+					}
+					
 					if ((status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0)) != SWITCH_STATUS_SUCCESS) {
 						break;
 					}
diff --git a/src/switch_resample.c b/src/switch_resample.c
index bca11e578e..d9f041b55f 100644
--- a/src/switch_resample.c
+++ b/src/switch_resample.c
@@ -228,18 +228,20 @@ SWITCH_DECLARE(void) switch_generate_sln_silence(int16_t *data, uint32_t samples
 	}
 }
 
-SWITCH_DECLARE(uint32_t) switch_merge_sln(int16_t *data, uint32_t samples, int16_t *other_data, uint32_t other_samples)
+SWITCH_DECLARE(uint32_t) switch_merge_sln(int16_t *data, uint32_t samples, int16_t *other_data, uint32_t other_samples, int channels)
 {
 	int i;
 	int32_t x, z;
 
+	if (channels == 0) channels = 1;
+
 	if (samples > other_samples) {
 		x = other_samples;
 	} else {
 		x = samples;
 	}
 
-	for (i = 0; i < x; i++) {
+	for (i = 0; i < x * channels; i++) {
 		z = data[i] + other_data[i];
 		switch_normalize_to_16bit(z);
 		data[i] = (int16_t) z;
@@ -249,18 +251,20 @@ SWITCH_DECLARE(uint32_t) switch_merge_sln(int16_t *data, uint32_t samples, int16
 }
 
 
-SWITCH_DECLARE(uint32_t) switch_unmerge_sln(int16_t *data, uint32_t samples, int16_t *other_data, uint32_t other_samples)
+SWITCH_DECLARE(uint32_t) switch_unmerge_sln(int16_t *data, uint32_t samples, int16_t *other_data, uint32_t other_samples, int channels)
 {
 	int i;
 	int32_t x;
 
+	if (channels == 0) channels = 1;
+
 	if (samples > other_samples) {
 		x = other_samples;
 	} else {
 		x = samples;
 	}
 
-	for (i = 0; i < x; i++) {
+	for (i = 0; i < x * channels; i++) {
 		data[i] -= other_data[i];
 	}