mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-19 17:54:13 +00:00
first pass of stereo support
This commit is contained in:
1 parent
7f36607ea5
commit
928a989de1
20 files changed
+592
-205
No files matched your search
@@ -359,6 +359,7 @@ typedef struct conference_obj {
|
||||
switch_mutex_t *flag_mutex;
|
||||
uint32_t rate;
|
||||
uint32_t interval;
|
||||
uint32_t channels;
|
||||
switch_mutex_t *mutex;
|
||||
conference_member_t *members;
|
||||
conference_member_t *floor_holder;
|
||||
@@ -2532,7 +2533,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
|
||||
conference_obj_t *conference = (conference_obj_t *) obj;
|
||||
conference_member_t *imember, *omember;
|
||||
uint32_t samples = switch_samples_per_packet(conference->rate, conference->interval);
|
||||
uint32_t bytes = samples * 2;
|
||||
uint32_t bytes = samples * 2 * conference->channels;
|
||||
uint8_t ready = 0, total = 0;
|
||||
switch_timer_t timer = { 0 };
|
||||
switch_event_t *event;
|
||||
@@ -2595,12 +2596,12 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
|
||||
|
||||
while (globals.running && !switch_test_flag(conference, CFLAG_DESTRUCT)) {
|
||||
switch_size_t file_sample_len = samples;
|
||||
switch_size_t file_data_len = samples * 2;
|
||||
switch_size_t file_data_len = samples * 2 * conference->channels;
|
||||
int has_file_data = 0, members_with_video = 0;
|
||||
uint32_t conf_energy = 0;
|
||||
int nomoh = 0;
|
||||
conference_member_t *floor_holder, *video_bridge_members[2] = { 0 };
|
||||
|
||||
conference_member_t *floor_holder, *video_bridge_members[2] = { 0 };
|
||||
|
||||
/* Sync the conference to a single timing source */
|
||||
if (switch_core_timer_next(&timer) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_set_flag(conference, CFLAG_DESTRUCT);
|
||||
@@ -2744,11 +2745,13 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
|
||||
conference->fnode->leadin--;
|
||||
} else if (!conference->fnode->done) {
|
||||
file_sample_len = samples;
|
||||
|
||||
if (conference->fnode->type == NODE_TYPE_SPEECH) {
|
||||
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_BLOCKING;
|
||||
|
||||
|
||||
if (switch_core_speech_read_tts(conference->fnode->sh, file_frame, &file_data_len, &flags) == SWITCH_STATUS_SUCCESS) {
|
||||
file_sample_len = file_data_len / 2;
|
||||
file_sample_len = file_data_len / 2 / conference->fnode->sh->channels;
|
||||
|
||||
} else {
|
||||
file_sample_len = file_data_len = 0;
|
||||
}
|
||||
@@ -2780,8 +2783,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
|
||||
} else {
|
||||
if (has_file_data) {
|
||||
switch_size_t x;
|
||||
|
||||
for (x = 0; x < file_sample_len; x++) {
|
||||
for (x = 0; x < file_sample_len * conference->channels; x++) {
|
||||
int32_t z;
|
||||
int16_t *muxed;
|
||||
|
||||
@@ -2792,27 +2794,29 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
|
||||
muxed[x] = (int16_t) z;
|
||||
}
|
||||
} else {
|
||||
memcpy(file_frame, async_file_frame, file_sample_len * 2);
|
||||
memcpy(file_frame, async_file_frame, file_sample_len * 2 * conference->channels);
|
||||
has_file_data = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (ready || has_file_data) {
|
||||
/* Use more bits in the main_frame to preserve the exact sum of the audio samples. */
|
||||
int main_frame[SWITCH_RECOMMENDED_BUFFER_SIZE / 2] = { 0 };
|
||||
int16_t write_frame[SWITCH_RECOMMENDED_BUFFER_SIZE / 2] = { 0 };
|
||||
int main_frame[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };
|
||||
int16_t write_frame[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };
|
||||
|
||||
|
||||
/* Init the main frame with file data if there is any. */
|
||||
bptr = (int16_t *) file_frame;
|
||||
if (has_file_data && file_sample_len) {
|
||||
|
||||
for (x = 0; x < bytes / 2; x++) {
|
||||
if (x <= file_sample_len) {
|
||||
if (x <= file_sample_len * conference->channels) {
|
||||
main_frame[x] = (int32_t) bptr[x];
|
||||
} else {
|
||||
memset(&main_frame[x], 255, sizeof(main_frame[x]));
|
||||
//printf("FUCCCK %d <= %ld (%ld/%d)\n", x, file_sample_len * conference->channels, file_sample_len, conference->channels);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2876,8 +2880,10 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
|
||||
}
|
||||
|
||||
bptr = (int16_t *) omember->frame;
|
||||
for (x = 0; x < bytes / 2; x++) {
|
||||
|
||||
for (x = 0; x < bytes / 2 ; x++) {
|
||||
z = main_frame[x];
|
||||
|
||||
/* bptr[x] represents my own contribution to this audio sample */
|
||||
if (switch_test_flag(omember, MFLAG_HAS_AUDIO) && x <= omember->read / 2) {
|
||||
z -= (int32_t) bptr[x];
|
||||
@@ -3678,6 +3684,27 @@ static void check_agc_levels(conference_member_t *member)
|
||||
}
|
||||
|
||||
|
||||
static void member_check_channels(switch_frame_t *frame, conference_member_t *member, switch_bool_t in)
|
||||
{
|
||||
if (member->conference->channels != member->read_impl.number_of_channels) {
|
||||
uint32_t rlen;
|
||||
int from, to;
|
||||
|
||||
if (in) {
|
||||
to = member->conference->channels;
|
||||
from = member->read_impl.number_of_channels;
|
||||
} else {
|
||||
from = member->conference->channels;
|
||||
to = member->read_impl.number_of_channels;
|
||||
}
|
||||
|
||||
rlen = frame->datalen / 2 / from;
|
||||
|
||||
switch_mux_channels((int16_t *) frame->data, rlen, from, to);
|
||||
|
||||
frame->datalen = rlen * 2 * to;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* marshall frames from the call leg to the conference thread for muxing to other call legs */
|
||||
@@ -3729,6 +3756,8 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v
|
||||
break;
|
||||
}
|
||||
|
||||
member_check_channels(read_frame, member, SWITCH_TRUE);
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_VIDEO) && !switch_test_flag(member, MFLAG_ACK_VIDEO)) {
|
||||
switch_set_flag_locked(member, MFLAG_ACK_VIDEO);
|
||||
switch_channel_clear_flag(channel, CF_VIDEO_ECHO);
|
||||
@@ -3827,7 +3856,7 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v
|
||||
switch_change_sln_volume_granular(read_frame->data, read_frame->datalen / 2, member->agc_volume_in_level);
|
||||
}
|
||||
|
||||
if ((samples = read_frame->datalen / sizeof(*data))) {
|
||||
if ((samples = read_frame->datalen / sizeof(*data) / member->read_impl.number_of_channels)) {
|
||||
for (i = 0; i < samples; i++) {
|
||||
energy += abs(data[j]);
|
||||
j += member->read_impl.number_of_channels;
|
||||
@@ -3980,9 +4009,9 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v
|
||||
int16_t *bptr = (int16_t *) read_frame->data;
|
||||
int len = (int) read_frame->datalen;
|
||||
|
||||
switch_resample_process(read_resampler, bptr, len / 2);
|
||||
memcpy(member->resample_out, read_resampler->to, read_resampler->to_len * 2);
|
||||
len = read_resampler->to_len * 2;
|
||||
switch_resample_process(read_resampler, bptr, len / 2 / member->conference->channels);
|
||||
memcpy(member->resample_out, read_resampler->to, read_resampler->to_len * 2 * member->conference->channels);
|
||||
len = read_resampler->to_len * 2 * member->conference->channels;
|
||||
datalen = len;
|
||||
data = member->resample_out;
|
||||
} else {
|
||||
@@ -4039,8 +4068,8 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v
|
||||
|
||||
static void member_add_file_data(conference_member_t *member, int16_t *data, switch_size_t file_data_len)
|
||||
{
|
||||
switch_size_t file_sample_len = file_data_len / 2;
|
||||
int16_t file_frame[SWITCH_RECOMMENDED_BUFFER_SIZE / 2] = { 0 };
|
||||
switch_size_t file_sample_len;
|
||||
int16_t file_frame[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };
|
||||
|
||||
|
||||
switch_mutex_lock(member->fnode_mutex);
|
||||
@@ -4049,6 +4078,8 @@ static void member_add_file_data(conference_member_t *member, int16_t *data, swi
|
||||
goto done;
|
||||
}
|
||||
|
||||
file_sample_len = file_data_len / 2 / member->conference->channels;
|
||||
|
||||
/* if we are done, clean it up */
|
||||
if (member->fnode->done) {
|
||||
conference_file_node_t *fnode;
|
||||
@@ -4071,15 +4102,15 @@ static void member_add_file_data(conference_member_t *member, int16_t *data, swi
|
||||
} else {
|
||||
if (member->fnode->type == NODE_TYPE_SPEECH) {
|
||||
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_BLOCKING;
|
||||
|
||||
|
||||
if (switch_core_speech_read_tts(member->fnode->sh, file_frame, &file_data_len, &flags) == SWITCH_STATUS_SUCCESS) {
|
||||
file_sample_len = file_data_len / 2;
|
||||
file_sample_len = file_data_len / 2 / member->conference->channels;
|
||||
} else {
|
||||
file_sample_len = file_data_len = 0;
|
||||
}
|
||||
} else if (member->fnode->type == NODE_TYPE_FILE) {
|
||||
switch_core_file_read(&member->fnode->fh, file_frame, &file_sample_len);
|
||||
file_data_len = file_sample_len * 2;
|
||||
file_data_len = file_sample_len * 2 * member->fnode->fh.channels;
|
||||
}
|
||||
|
||||
if (file_sample_len <= 0) {
|
||||
@@ -4092,7 +4123,7 @@ static void member_add_file_data(conference_member_t *member, int16_t *data, swi
|
||||
switch_change_sln_volume(file_frame, (uint32_t)file_sample_len, member->volume_out_level);
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)file_sample_len; i++) {
|
||||
for (i = 0; i < (int)file_sample_len * member->conference->channels; i++) {
|
||||
if (member->fnode->mux) {
|
||||
sample = data[i] + file_frame[i];
|
||||
switch_normalize_to_16bit(sample);
|
||||
@@ -4157,7 +4188,7 @@ static void conference_loop_output(conference_member_t *member)
|
||||
//csamples = samples;
|
||||
tsamples = member->orig_read_impl.samples_per_packet;
|
||||
low_count = 0;
|
||||
bytes = samples * 2;
|
||||
bytes = samples * 2 * member->conference->channels;
|
||||
call_list = NULL;
|
||||
cp = NULL;
|
||||
|
||||
@@ -4165,7 +4196,7 @@ static void conference_loop_output(conference_member_t *member)
|
||||
|
||||
switch_assert(member->conference != NULL);
|
||||
|
||||
flush_len = switch_samples_per_packet(member->conference->rate, member->conference->interval) * 10;
|
||||
flush_len = switch_samples_per_packet(member->conference->rate, member->conference->interval) * 10 * member->conference->channels;
|
||||
|
||||
if (switch_core_timer_init(&timer, member->conference->timer_name, interval, tsamples, NULL) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_ERROR, "Timer Setup Failed. Conference Cannot Start\n");
|
||||
@@ -4331,7 +4362,7 @@ static void conference_loop_output(conference_member_t *member)
|
||||
mux_used = (uint32_t) switch_buffer_inuse(member->mux_buffer);
|
||||
|
||||
use_timer = 1;
|
||||
|
||||
|
||||
if (mux_used) {
|
||||
if (mux_used < bytes) {
|
||||
if (++low_count >= 5) {
|
||||
@@ -4354,7 +4385,7 @@ static void conference_loop_output(conference_member_t *member)
|
||||
low_count = 0;
|
||||
if ((write_frame.datalen = (uint32_t) switch_buffer_read(use_buffer, write_frame.data, bytes))) {
|
||||
if (write_frame.datalen) {
|
||||
write_frame.samples = write_frame.datalen / 2;
|
||||
write_frame.samples = write_frame.datalen / 2 / member->conference->channels;
|
||||
|
||||
if( !switch_test_flag(member, MFLAG_CAN_HEAR)) {
|
||||
memset(write_frame.data, 255, write_frame.datalen);
|
||||
@@ -4369,6 +4400,9 @@ static void conference_loop_output(conference_member_t *member)
|
||||
if (member->fnode) {
|
||||
member_add_file_data(member, write_frame.data, write_frame.datalen);
|
||||
}
|
||||
|
||||
member_check_channels(&write_frame, member, SWITCH_FALSE);
|
||||
|
||||
if (switch_core_session_write_frame(member->session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_mutex_unlock(member->audio_out_mutex);
|
||||
break;
|
||||
@@ -4383,6 +4417,7 @@ static void conference_loop_output(conference_member_t *member)
|
||||
memset(write_frame.data, 255, write_frame.datalen);
|
||||
write_frame.timestamp = timer.samplecount;
|
||||
member_add_file_data(member, write_frame.data, write_frame.datalen);
|
||||
member_check_channels(&write_frame, member, SWITCH_FALSE);
|
||||
if (switch_core_session_write_frame(member->session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||
break;
|
||||
@@ -4399,6 +4434,8 @@ static void conference_loop_output(conference_member_t *member)
|
||||
write_frame.samples = samples;
|
||||
write_frame.timestamp = timer.samplecount;
|
||||
|
||||
member_check_channels(&write_frame, member, SWITCH_FALSE);
|
||||
|
||||
if (switch_core_session_write_frame(member->session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||
break;
|
||||
@@ -4521,7 +4558,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data_buf_len = samples * sizeof(int16_t);
|
||||
data_buf_len = samples * sizeof(int16_t) * conference->channels;
|
||||
switch_zmalloc(data_buf, data_buf_len);
|
||||
|
||||
switch_mutex_lock(globals.hash_mutex);
|
||||
@@ -4574,7 +4611,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
|
||||
fh.pre_buffer_datalen = SWITCH_DEFAULT_FILE_BUFFER_LEN;
|
||||
|
||||
if (switch_core_file_open(&fh,
|
||||
rec->path, (uint8_t) 1, conference->rate, SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT,
|
||||
rec->path, (uint8_t) conference->channels, conference->rate, SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT,
|
||||
rec->pool) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening File [%s]\n", rec->path);
|
||||
|
||||
@@ -4917,7 +4954,7 @@ static switch_status_t conference_play_file(conference_obj_t *conference, char *
|
||||
|
||||
/* Open the file */
|
||||
fnode->fh.pre_buffer_datalen = SWITCH_DEFAULT_FILE_BUFFER_LEN;
|
||||
if (switch_core_file_open(&fnode->fh, file, (uint8_t) 1, conference->rate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, pool) !=
|
||||
if (switch_core_file_open(&fnode->fh, file, (uint8_t) conference->channels, conference->rate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, pool) !=
|
||||
SWITCH_STATUS_SUCCESS) {
|
||||
switch_event_t *event;
|
||||
|
||||
@@ -5043,7 +5080,7 @@ static switch_status_t conference_member_play_file(conference_member_t *member,
|
||||
/* Open the file */
|
||||
fnode->fh.pre_buffer_datalen = SWITCH_DEFAULT_FILE_BUFFER_LEN;
|
||||
if (switch_core_file_open(&fnode->fh,
|
||||
file, (uint8_t) 1, member->conference->rate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT,
|
||||
file, (uint8_t) member->conference->channels, member->conference->rate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT,
|
||||
pool) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_core_destroy_memory_pool(&pool);
|
||||
status = SWITCH_STATUS_NOTFOUND;
|
||||
@@ -5109,7 +5146,7 @@ static switch_status_t conference_member_say(conference_member_t *member, char *
|
||||
if (!member->sh) {
|
||||
memset(&member->lsh, 0, sizeof(member->lsh));
|
||||
if (switch_core_speech_open(&member->lsh, conference->tts_engine, conference->tts_voice,
|
||||
conference->rate, conference->interval, &flags, switch_core_session_get_pool(member->session)) !=
|
||||
conference->rate, conference->interval, conference->channels, &flags, switch_core_session_get_pool(member->session)) !=
|
||||
SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_ERROR, "Invalid TTS module [%s]!\n", conference->tts_engine);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
@@ -5198,7 +5235,7 @@ static switch_status_t conference_say(conference_obj_t *conference, const char *
|
||||
if (!conference->sh) {
|
||||
memset(&conference->lsh, 0, sizeof(conference->lsh));
|
||||
if (switch_core_speech_open(&conference->lsh, conference->tts_engine, conference->tts_voice,
|
||||
conference->rate, conference->interval, &flags, NULL) != SWITCH_STATUS_SUCCESS) {
|
||||
conference->rate, conference->interval, conference->channels, &flags, NULL) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid TTS module [%s]!\n", conference->tts_engine);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
@@ -8075,14 +8112,15 @@ static int setup_media(conference_member_t *member, conference_obj_t *conference
|
||||
if (switch_core_codec_init(&member->read_codec,
|
||||
"L16",
|
||||
NULL, read_impl.actual_samples_per_second, read_impl.microseconds_per_packet / 1000,
|
||||
1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, member->pool) == SWITCH_STATUS_SUCCESS) {
|
||||
read_impl.number_of_channels,
|
||||
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, member->pool) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG,
|
||||
"Raw Codec Activation Success L16@%uhz 1 channel %dms\n",
|
||||
read_impl.actual_samples_per_second, read_impl.microseconds_per_packet / 1000);
|
||||
"Raw Codec Activation Success L16@%uhz %d channel %dms\n",
|
||||
read_impl.actual_samples_per_second, read_impl.number_of_channels, read_impl.microseconds_per_packet / 1000);
|
||||
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG, "Raw Codec Activation Failed L16@%uhz 1 channel %dms\n",
|
||||
read_impl.actual_samples_per_second, read_impl.microseconds_per_packet / 1000);
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG, "Raw Codec Activation Failed L16@%uhz %d channel %dms\n",
|
||||
read_impl.actual_samples_per_second, read_impl.number_of_channels, read_impl.microseconds_per_packet / 1000);
|
||||
|
||||
goto done;
|
||||
}
|
||||
@@ -8096,7 +8134,7 @@ static int setup_media(conference_member_t *member, conference_obj_t *conference
|
||||
if (read_impl.actual_samples_per_second != conference->rate) {
|
||||
if (switch_resample_create(&member->read_resampler,
|
||||
read_impl.actual_samples_per_second,
|
||||
conference->rate, member->frame_size, SWITCH_RESAMPLE_QUALITY, 1) != SWITCH_STATUS_SUCCESS) {
|
||||
conference->rate, member->frame_size, SWITCH_RESAMPLE_QUALITY, conference->channels) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_CRIT, "Unable to create resampler!\n");
|
||||
goto done;
|
||||
}
|
||||
@@ -8120,12 +8158,14 @@ static int setup_media(conference_member_t *member, conference_obj_t *conference
|
||||
NULL,
|
||||
conference->rate,
|
||||
read_impl.microseconds_per_packet / 1000,
|
||||
1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, member->pool) == SWITCH_STATUS_SUCCESS) {
|
||||
read_impl.number_of_channels,
|
||||
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, member->pool) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG,
|
||||
"Raw Codec Activation Success L16@%uhz 1 channel %dms\n", conference->rate, read_impl.microseconds_per_packet / 1000);
|
||||
"Raw Codec Activation Success L16@%uhz %d channel %dms\n",
|
||||
conference->rate, conference->channels, read_impl.microseconds_per_packet / 1000);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG, "Raw Codec Activation Failed L16@%uhz 1 channel %dms\n",
|
||||
conference->rate, read_impl.microseconds_per_packet / 1000);
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG, "Raw Codec Activation Failed L16@%uhz %d channel %dms\n",
|
||||
conference->rate, conference->channels, read_impl.microseconds_per_packet / 1000);
|
||||
goto codec_done2;
|
||||
}
|
||||
|
||||
@@ -9027,6 +9067,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
|
||||
uint32_t announce_count = 0;
|
||||
char *maxmember_sound = NULL;
|
||||
uint32_t rate = 8000, interval = 20;
|
||||
uint32_t channels = 1;
|
||||
int broadcast_chat_messages = 0;
|
||||
int comfort_noise_level = 0;
|
||||
int pin_retries = 3;
|
||||
@@ -9044,8 +9085,8 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
|
||||
switch_uuid_t uuid;
|
||||
switch_codec_implementation_t read_impl = { 0 };
|
||||
switch_channel_t *channel = NULL;
|
||||
const char *force_rate = NULL, *force_interval = NULL, *presence_id = NULL;
|
||||
uint32_t force_rate_i = 0, force_interval_i = 0;
|
||||
const char *force_rate = NULL, *force_interval = NULL, *force_channels = NULL, *presence_id = NULL;
|
||||
uint32_t force_rate_i = 0, force_interval_i = 0, force_channels_i = NULL;
|
||||
|
||||
/* Validate the conference name */
|
||||
if (zstr(name)) {
|
||||
@@ -9073,6 +9114,18 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
|
||||
}
|
||||
}
|
||||
|
||||
if ((force_channels = switch_channel_get_variable(channel, "conference_force_channels"))) {
|
||||
if (!strcasecmp(force_channels, "auto")) {
|
||||
force_rate_i = read_impl.number_of_channels;
|
||||
} else {
|
||||
tmp = atoi(force_channels);
|
||||
|
||||
if (tmp == 1 || tmp == 2) {
|
||||
force_channels_i = channels = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((force_interval = switch_channel_get_variable(channel, "conference_force_interval"))) {
|
||||
if (!strcasecmp(force_interval, "auto")) {
|
||||
force_interval_i = read_impl.microseconds_per_packet / 1000;
|
||||
@@ -9117,6 +9170,17 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
|
||||
rate = tmp;
|
||||
}
|
||||
}
|
||||
} else if (!force_channels_i && !strcasecmp(var, "channels") && !zstr(val)) {
|
||||
uint32_t tmp = atoi(val);
|
||||
if (session && tmp == 0) {
|
||||
if (!strcasecmp(val, "auto")) {
|
||||
channels = read_impl.number_of_channels;
|
||||
}
|
||||
} else {
|
||||
if (tmp == 1 || tmp == 2) {
|
||||
channels = tmp;
|
||||
}
|
||||
}
|
||||
} else if (!strcasecmp(var, "domain") && !zstr(val)) {
|
||||
domain = val;
|
||||
} else if (!strcasecmp(var, "description") && !zstr(val)) {
|
||||
@@ -9507,6 +9571,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
|
||||
conference->domain = "cluecon.com";
|
||||
}
|
||||
|
||||
conference->channels = channels;
|
||||
conference->rate = rate;
|
||||
conference->interval = interval;
|
||||
conference->ivr_dtmf_timeout = ivr_dtmf_timeout;
|
||||
|
||||
@@ -118,7 +118,7 @@ static swift_result_t write_audio(swift_event * event, swift_event_t type, void
|
||||
return rv;
|
||||
}
|
||||
|
||||
static switch_status_t cepstral_speech_open(switch_speech_handle_t *sh, const char *voice_name, int rate, switch_speech_flag_t *flags)
|
||||
static switch_status_t cepstral_speech_open(switch_speech_handle_t *sh, const char *voice_name, int rate, int channels, switch_speech_flag_t *flags)
|
||||
{
|
||||
cepstral_t *cepstral = switch_core_alloc(sh->memory_pool, sizeof(*cepstral));
|
||||
char srate[25];
|
||||
@@ -290,7 +290,6 @@ static switch_status_t cepstral_speech_read_tts(switch_speech_handle_t *sh, void
|
||||
|
||||
|
||||
if (!used && cepstral->done_gen) {
|
||||
|
||||
status = SWITCH_STATUS_BREAK;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -143,6 +143,11 @@ static switch_status_t switch_opus_fmtp_parse(const char *fmtp, switch_codec_fmt
|
||||
codec_settings->samplerate = atoi(arg);
|
||||
codec_fmtp->actual_samples_per_second = codec_settings->samplerate;
|
||||
}
|
||||
|
||||
if (!strcasecmp(data, "stereo")) {
|
||||
codec_settings->stereo = atoi(arg);
|
||||
codec_fmtp->stereo = codec_settings->stereo;
|
||||
}
|
||||
|
||||
if (!strcasecmp(data, "maxaveragebitrate")) {
|
||||
codec_settings->maxaveragebitrate = atoi(arg);
|
||||
@@ -202,36 +207,40 @@ static char *gen_fmtp(opus_codec_settings_t *settings, switch_memory_pool_t *poo
|
||||
char buf[256] = "";
|
||||
|
||||
if (settings->useinbandfec) {
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "useinbandfec=1;");
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "useinbandfec=1; ");
|
||||
}
|
||||
|
||||
if (settings->usedtx) {
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "usedtx=1;");
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "usedtx=1; ");
|
||||
}
|
||||
|
||||
if (settings->maxaveragebitrate) {
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "maxaveragebitrate=%d;", settings->maxaveragebitrate);
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "maxaveragebitrate=%d; ", settings->maxaveragebitrate);
|
||||
|
||||
}
|
||||
|
||||
if (settings->ptime) {
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "ptime=%d;", settings->ptime);
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "ptime=%d; ", settings->ptime);
|
||||
}
|
||||
|
||||
if (settings->minptime) {
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "minptime=%d;", settings->minptime);
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "minptime=%d; ", settings->minptime);
|
||||
}
|
||||
|
||||
|
||||
if (settings->maxptime) {
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "maxptime=%d;", settings->maxptime);
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "maxptime=%d; ", settings->maxptime);
|
||||
}
|
||||
|
||||
if (settings->samplerate) {
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "samplerate=%d;", settings->samplerate);
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "samplerate=%d; ", settings->samplerate);
|
||||
}
|
||||
|
||||
if (end_of(buf) == ';') {
|
||||
end_of(buf) = '\0';
|
||||
|
||||
if (settings->stereo) {
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "stereo=%d; ", settings->stereo);
|
||||
}
|
||||
|
||||
if (end_of(buf) == ' ') {
|
||||
*(end_of_p(buf) - 1) = '\0';
|
||||
}
|
||||
|
||||
return switch_core_strdup(pool, buf);
|
||||
@@ -255,9 +264,8 @@ static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag
|
||||
memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
|
||||
codec_fmtp.private_info = &opus_codec_settings;
|
||||
switch_opus_fmtp_parse(codec->fmtp_in, &codec_fmtp);
|
||||
|
||||
codec->fmtp_out = gen_fmtp(&opus_codec_settings, codec->memory_pool);
|
||||
|
||||
|
||||
if (encoding) {
|
||||
/* come up with a way to specify these */
|
||||
int bitrate_bps = OPUS_AUTO;
|
||||
@@ -268,7 +276,7 @@ static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag
|
||||
|
||||
context->encoder_object = opus_encoder_create(samplerate,
|
||||
codec->implementation->number_of_channels,
|
||||
OPUS_APPLICATION_VOIP, &err);
|
||||
codec->implementation->number_of_channels == 1 ? OPUS_APPLICATION_VOIP : OPUS_APPLICATION_AUDIO, &err);
|
||||
|
||||
if (err != OPUS_OK) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot create encoder: %s\n", opus_strerror(err));
|
||||
@@ -358,17 +366,19 @@ static switch_status_t switch_opus_encode(switch_codec_t *codec,
|
||||
if (!context) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (len > 1275) len = 1275;
|
||||
|
||||
bytes = opus_encode(context->encoder_object, (void *) decoded_data, decoded_data_len / 2, (unsigned char *) encoded_data, len);
|
||||
|
||||
|
||||
if (len > 2880) len = 2880;
|
||||
|
||||
bytes = opus_encode(context->encoder_object, (void *) decoded_data,
|
||||
decoded_data_len / 2 / codec->implementation->number_of_channels, (unsigned char *) encoded_data, len);
|
||||
|
||||
if (bytes > 0) {
|
||||
*encoded_data_len = (uint32_t) bytes;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Encoder Error!\n");
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Encoder Error: %s Decoded Datalen %u Codec NumberChans %u Len %u DecodedDate %p EncodedData %p ContextEncoderObject %p!\n", opus_strerror(bytes),decoded_data_len,codec->implementation->number_of_channels,len,(void *) decoded_data,(void *) encoded_data,(void *) context->encoder_object);
|
||||
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
@@ -387,12 +397,13 @@ static switch_status_t switch_opus_decode(switch_codec_t *codec,
|
||||
}
|
||||
|
||||
samples = opus_decode(context->decoder_object, (*flag & SFF_PLC) ? NULL : encoded_data, encoded_data_len, decoded_data, *decoded_data_len, 0);
|
||||
|
||||
|
||||
if (samples < 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Decoder Error: %s!\n", opus_strerror(samples));
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
*decoded_data_len = samples * 2;
|
||||
|
||||
*decoded_data_len = samples * 2 * codec->implementation->number_of_channels;
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
@@ -481,6 +492,27 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load)
|
||||
switch_opus_decode, /* function to decode encoded data into raw data */
|
||||
switch_opus_destroy); /* deinitalize a codec handle using this implementation */
|
||||
|
||||
settings.stereo = 1;
|
||||
dft_fmtp = gen_fmtp(&settings, pool);
|
||||
|
||||
switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
|
||||
116, /* the IANA code number */
|
||||
"opus",/* the IANA code name */
|
||||
dft_fmtp, /* default fmtp to send (can be overridden by the init function) */
|
||||
rate, /* samples transferred per second */
|
||||
rate, /* actual samples transferred per second */
|
||||
bits, /* bits transferred per second */
|
||||
mss, /* number of microseconds per frame */
|
||||
samples, /* number of samples per frame */
|
||||
bytes * 2, /* number of bytes per frame decompressed */
|
||||
0, /* number of bytes per frame compressed */
|
||||
2,/* number of channels represented */
|
||||
1, /* number of frames per network packet */
|
||||
switch_opus_init, /* function to initialize a codec handle using this implementation */
|
||||
switch_opus_encode, /* function to encode raw data into encoded data */
|
||||
switch_opus_decode, /* function to decode encoded data into raw data */
|
||||
switch_opus_destroy); /* deinitalize a codec handle using this implementation */
|
||||
|
||||
bytes *= 2;
|
||||
samples *= 2;
|
||||
mss *= 2;
|
||||
|
||||
@@ -298,7 +298,7 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
||||
}
|
||||
}
|
||||
|
||||
switch_buffer_write(audio_buffer, abuf, olen * 2);
|
||||
switch_buffer_write(audio_buffer, abuf, olen * 2 * source->channels);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,8 +308,8 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
||||
break;
|
||||
}
|
||||
|
||||
if (!is_open || used >= source->prebuf || (source->total && used > source->samples * 2)) {
|
||||
used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2);
|
||||
if (!is_open || used >= source->prebuf || (source->total && used > source->samples * 2 * source->channels)) {
|
||||
used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2 * source->channels);
|
||||
if (source->total) {
|
||||
uint32_t bused = 0;
|
||||
switch_mutex_lock(source->mutex);
|
||||
@@ -548,7 +548,7 @@ static switch_status_t local_stream_file_read(switch_file_handle_t *handle, void
|
||||
{
|
||||
local_stream_context_t *context = handle->private_info;
|
||||
switch_size_t bytes = 0;
|
||||
size_t need = *len * 2;
|
||||
size_t need = *len * 2 * handle->real_channels;
|
||||
|
||||
if (!context->source->ready) {
|
||||
*len = 0;
|
||||
@@ -557,13 +557,13 @@ static switch_status_t local_stream_file_read(switch_file_handle_t *handle, void
|
||||
|
||||
switch_mutex_lock(context->audio_mutex);
|
||||
if ((bytes = switch_buffer_read(context->audio_buffer, data, need))) {
|
||||
*len = bytes / 2;
|
||||
*len = bytes / 2 / handle->real_channels;
|
||||
} else {
|
||||
if (need > 2560) {
|
||||
need = 2560;
|
||||
}
|
||||
memset(data, 255, need);
|
||||
*len = need / 2;
|
||||
*len = need / 2 / handle->real_channels;
|
||||
}
|
||||
switch_mutex_unlock(context->audio_mutex);
|
||||
handle->sample_count += *len;
|
||||
|
||||
@@ -99,6 +99,8 @@ static switch_status_t shell_stream_file_open(switch_file_handle_t *handle, cons
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
handle->channels = 1;
|
||||
|
||||
context = switch_core_alloc(handle->memory_pool, sizeof(*context));
|
||||
|
||||
context->fds[0] = -1;
|
||||
|
||||
@@ -625,6 +625,9 @@ static switch_status_t shout_file_open(switch_file_handle_t *handle, const char
|
||||
char *err = NULL;
|
||||
const char *mpg123err = NULL;
|
||||
int portno = 0;
|
||||
long rate = 0;
|
||||
int channels = 0;
|
||||
int encoding = 0;
|
||||
|
||||
if ((context = switch_core_alloc(handle->memory_pool, sizeof(*context))) == 0) {
|
||||
return SWITCH_STATUS_MEMERR;
|
||||
@@ -659,9 +662,6 @@ static switch_status_t shout_file_open(switch_file_handle_t *handle, const char
|
||||
}
|
||||
|
||||
if (handle->handler) {
|
||||
if (mpg123_param(context->mh, MPG123_FLAGS, MPG123_SEEKBUFFER | MPG123_MONO_MIX, 0) != MPG123_OK) {
|
||||
MPGERROR();
|
||||
}
|
||||
if (mpg123_open_feed(context->mh) != MPG123_OK) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening mpg feed\n");
|
||||
mpg123err = mpg123_strerror(context->mh);
|
||||
@@ -672,9 +672,7 @@ static switch_status_t shout_file_open(switch_file_handle_t *handle, const char
|
||||
launch_read_stream_thread(context);
|
||||
} else {
|
||||
handle->seekable = 1;
|
||||
if (mpg123_param(context->mh, MPG123_FLAGS, MPG123_MONO_MIX, 0) != MPG123_OK) {
|
||||
MPGERROR();
|
||||
}
|
||||
|
||||
if (mpg123_open(context->mh, path) != MPG123_OK) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening %s\n", path);
|
||||
mpg123err = mpg123_strerror(context->mh);
|
||||
@@ -682,6 +680,12 @@ static switch_status_t shout_file_open(switch_file_handle_t *handle, const char
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
mpg123_getformat(context->mh, &rate, &channels, &encoding);
|
||||
handle->channels = channels;
|
||||
handle->samplerate = rate;
|
||||
|
||||
} else if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
|
||||
if (!(context->gfp = lame_init())) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate lame\n");
|
||||
@@ -897,7 +901,7 @@ static switch_status_t shout_file_seek(switch_file_handle_t *handle, unsigned in
|
||||
static switch_status_t shout_file_read(switch_file_handle_t *handle, void *data, size_t *len)
|
||||
{
|
||||
shout_context_t *context = handle->private_info;
|
||||
size_t rb = 0, bytes = *len * sizeof(int16_t), newbytes = 0;
|
||||
size_t rb = 0, bytes = *len * sizeof(int16_t) * handle->channels, newbytes = 0;
|
||||
|
||||
*len = 0;
|
||||
|
||||
@@ -919,7 +923,7 @@ static switch_status_t shout_file_read(switch_file_handle_t *handle, void *data,
|
||||
/* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "rb: %d, bytes: %d\n", (int) rb, (int) bytes); */
|
||||
|
||||
if (rb) {
|
||||
*len = rb / sizeof(int16_t);
|
||||
*len = rb / sizeof(int16_t) / handle->channels;
|
||||
} else {
|
||||
/* no data, so insert 1 second of silence */
|
||||
newbytes = 2 * handle->samplerate;
|
||||
@@ -929,7 +933,7 @@ static switch_status_t shout_file_read(switch_file_handle_t *handle, void *data,
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Padding mp3 stream with 1s of empty audio. (%s)\n", context->stream_url);
|
||||
|
||||
memset(data, 255, bytes);
|
||||
*len = bytes / sizeof(int16_t);
|
||||
*len = bytes / sizeof(int16_t) / handle->channels;
|
||||
}
|
||||
|
||||
handle->sample_count += *len;
|
||||
|
||||
@@ -67,6 +67,7 @@ static switch_status_t silence_stream_file_open(switch_file_handle_t *handle, co
|
||||
}
|
||||
}
|
||||
|
||||
handle->channels = 1;
|
||||
handle->private_info = sh;
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
@@ -153,6 +154,8 @@ static switch_status_t tone_stream_file_open(switch_file_handle_t *handle, const
|
||||
handle->samplerate = 8000;
|
||||
}
|
||||
|
||||
handle->channels = 1;
|
||||
|
||||
teletone_init_session(&ts, 0, teletone_handler, audio_buffer);
|
||||
ts.rate = handle->samplerate;
|
||||
ts.channels = 1;
|
||||
|
||||
@@ -73,6 +73,7 @@ struct vlc_file_context {
|
||||
int samples;
|
||||
int playing;
|
||||
int samplerate;
|
||||
int channels;
|
||||
int err;
|
||||
int pts;
|
||||
libvlc_instance_t *inst_out;
|
||||
@@ -113,7 +114,7 @@ void vlc_auto_play_callback(void *data, const void *samples, unsigned count, int
|
||||
|
||||
switch_mutex_lock(context->audio_mutex);
|
||||
if (context->audio_buffer) {
|
||||
if (!switch_buffer_write(context->audio_buffer, samples, count * 2)) {
|
||||
if (!switch_buffer_write(context->audio_buffer, samples, count * 2 * context->channels)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Buffer error\n");
|
||||
}
|
||||
}
|
||||
@@ -145,7 +146,7 @@ int vlc_imem_get_callback(void *data, const char *cookie, int64_t *dts, int64_t
|
||||
context->samples = 0;
|
||||
|
||||
if ( samples ) {
|
||||
bytes = samples * 2;
|
||||
bytes = samples * 2 * context->channels;
|
||||
*output = malloc(bytes);
|
||||
bytes = switch_buffer_read(context->audio_buffer, *output, bytes);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "VLC imem samples: %d\n", samples);
|
||||
@@ -210,12 +211,14 @@ static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *p
|
||||
|
||||
context->mp = libvlc_media_player_new_from_media(context->m);
|
||||
|
||||
if ( !handle->samplerate)
|
||||
if (!handle->samplerate) {
|
||||
handle->samplerate = 16000;
|
||||
}
|
||||
|
||||
context->samplerate = handle->samplerate;
|
||||
|
||||
libvlc_audio_set_format(context->mp, "S16N", context->samplerate, 1);
|
||||
context->channels = handle->channels;
|
||||
|
||||
libvlc_audio_set_format(context->mp, "S16N", context->samplerate, handle->channels);
|
||||
|
||||
m_event_manager = libvlc_media_event_manager(context->m);
|
||||
libvlc_event_attach(m_event_manager, libvlc_MediaStateChanged, vlc_media_state_callback, (void *) context);
|
||||
@@ -246,7 +249,7 @@ static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *p
|
||||
opts[6] = "--rawaud-fourcc=s16l";
|
||||
opts[7] = switch_mprintf("--rawaud-samplerate=%d", context->samplerate);
|
||||
opts[8] = switch_mprintf("--imem-data=%ld", context);
|
||||
opts[9] = "--rawaud-channels=1";
|
||||
//opts[9] = "--rawaud-channels=1";
|
||||
|
||||
/* Prepare to write to an output stream. */
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "VLC open %s for writing\n", path);
|
||||
@@ -274,7 +277,7 @@ static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *p
|
||||
static switch_status_t vlc_file_read(switch_file_handle_t *handle, void *data, size_t *len)
|
||||
{
|
||||
vlc_file_context_t *context = handle->private_info;
|
||||
size_t bytes = *len * sizeof(int16_t), read;
|
||||
size_t bytes = *len * sizeof(int16_t) * handle->channels, read;
|
||||
libvlc_state_t status;
|
||||
|
||||
if (!context) {
|
||||
@@ -310,7 +313,8 @@ static switch_status_t vlc_file_read(switch_file_handle_t *handle, void *data, s
|
||||
read = switch_buffer_read(context->audio_buffer, data, bytes);
|
||||
switch_mutex_unlock(context->audio_mutex);
|
||||
|
||||
status = libvlc_media_get_state(context->m);
|
||||
status = libvlc_media_get_state(context->m);
|
||||
|
||||
if (!read && (status == libvlc_Stopped || status == libvlc_Ended || status == libvlc_Error)) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
} else if (!read) {
|
||||
@@ -318,8 +322,9 @@ static switch_status_t vlc_file_read(switch_file_handle_t *handle, void *data, s
|
||||
memset(data, 0, read);
|
||||
}
|
||||
|
||||
if (read)
|
||||
*len = read/2;
|
||||
if (read) {
|
||||
*len = read / 2 / handle->channels;
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
@@ -327,7 +332,7 @@ static switch_status_t vlc_file_read(switch_file_handle_t *handle, void *data, s
|
||||
static switch_status_t vlc_file_write(switch_file_handle_t *handle, void *data, size_t *len)
|
||||
{
|
||||
vlc_file_context_t *context = handle->private_info;
|
||||
size_t bytes = *len * sizeof(int16_t);
|
||||
size_t bytes = *len * sizeof(int16_t) * handle->channels;
|
||||
|
||||
switch_mutex_lock(context->audio_mutex);
|
||||
context->samples += *len;
|
||||
|
||||
@@ -982,7 +982,7 @@ switch_status_t FSSession::InitSpeechEngine(const char *engine, const char *voic
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (switch_core_speech_open(&this->_speech->sh, engine, voice, rate, interval,
|
||||
if (switch_core_speech_open(&this->_speech->sh, engine, voice, rate, interval, read_codec->implementation->number_of_channels,
|
||||
&flags, switch_core_session_get_pool(this->_session)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid TTS module!\n");
|
||||
switch_core_codec_destroy(&this->_speech->codec);
|
||||
|
||||
Reference in new issue
Block a user