diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 20eb491b5f..c8fd6cba8e 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -110,6 +110,7 @@ SWITCH_BEGIN_EXTERN_C #define SWITCH_PATH_SEPARATOR "/" #endif #define SWITCH_URL_SEPARATOR "://" +#define SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE "send_silence_when_idle" #define SWITCH_CURRENT_APPLICATION_VARIABLE "current_application" #define SWITCH_CURRENT_APPLICATION_DATA_VARIABLE "current_application_data" #define SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE "current_application_response" diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 6c5432870b..90dfac2bf7 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -47,6 +47,41 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session, int32_t left, elapsed; char data[2] = ""; + switch_frame_t write_frame = { 0 }; + unsigned char *abuf = NULL; + switch_codec_implementation_t imp = {0}; + switch_codec_t codec = { 0 }; + int sval = 0; + const char *var; + + if ((var = switch_channel_get_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE)) && (sval = atoi(var))) { + switch_core_session_get_read_impl(session, &imp); + + if (switch_core_codec_init(&codec, + "L16", + NULL, + imp.samples_per_second, + imp.microseconds_per_packet / 1000, + imp.number_of_channels, + SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, + switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec Error L16@%uhz %u channels %dms\n", + imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000); + return SWITCH_STATUS_FALSE; + } + + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Codec Activated L16@%uhz %u channels %dms\n", + imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000); + + write_frame.codec = &codec; + switch_zmalloc(abuf, SWITCH_RECOMMENDED_BUFFER_SIZE); + write_frame.data = abuf; + write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE; + write_frame.datalen = imp.decoded_bytes_per_packet; + write_frame.samples = write_frame.datalen / sizeof(int16_t); + } + cng_frame.data = data; cng_frame.datalen = 2; cng_frame.buflen = 2; @@ -134,10 +169,20 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session, } } - switch_core_session_write_frame(session, &cng_frame, SWITCH_IO_FLAG_NONE, 0); - + if (sval) { + switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.samples, sval); + switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0); + } else { + switch_core_session_write_frame(session, &cng_frame, SWITCH_IO_FLAG_NONE, 0); + } } + if (write_frame.codec) { + switch_core_codec_destroy(&codec); + } + + switch_safe_free(abuf); + return status; } @@ -749,9 +794,44 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_count(switch_core_sess switch_time_t started = 0, digit_started = 0; uint32_t abs_elapsed = 0, digit_elapsed = 0; uint32_t eff_timeout = 0; + switch_frame_t write_frame = { 0 }; + unsigned char *abuf = NULL; + switch_codec_implementation_t imp = {0}; + switch_codec_t codec = { 0 }; + int sval = 0; + const char *var; - if (terminator != NULL) + if ((var = switch_channel_get_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE)) && (sval = atoi(var))) { + switch_core_session_get_read_impl(session, &imp); + + if (switch_core_codec_init(&codec, + "L16", + NULL, + imp.samples_per_second, + imp.microseconds_per_packet / 1000, + imp.number_of_channels, + SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, + switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec Error L16@%uhz %u channels %dms\n", + imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000); + return SWITCH_STATUS_FALSE; + } + + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Codec Activated L16@%uhz %u channels %dms\n", + imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000); + + write_frame.codec = &codec; + switch_zmalloc(abuf, SWITCH_RECOMMENDED_BUFFER_SIZE); + write_frame.data = abuf; + write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE; + write_frame.datalen = imp.decoded_bytes_per_packet; + write_frame.samples = write_frame.datalen / sizeof(int16_t); + } + + if (terminator != NULL) { *terminator = '\0'; + } if (!switch_strlen_zero(terminators)) { for (i = 0; i < x; i++) { @@ -838,9 +918,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_count(switch_core_sess if (!SWITCH_READ_ACCEPTABLE(status)) { break; } + + if (write_frame.data) { + switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.samples, sval); + switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0); + } + } } + if (write_frame.codec) { + switch_core_codec_destroy(&codec); + } + + switch_safe_free(abuf); + return status; } diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index 7dddd462c6..2c36fb5de7 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -279,6 +279,7 @@ struct ringback { teletone_generation_session_t ts; switch_file_handle_t fhb; switch_file_handle_t *fh; + int silence; uint8_t asis; }; @@ -348,9 +349,16 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_wait_for_answer(switch_core_session_t ringback_data = switch_channel_get_variable(caller_channel, "ringback"); } - if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE) || switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA)) { ringback_data = NULL; + } else { + if ((var = switch_channel_get_variable(caller_channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE))) { + int sval = atoi(var); + + if (sval) { + ringback_data = switch_core_session_sprintf(session, "ringback:%d", sval); + } + } } } @@ -409,14 +417,27 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_wait_for_answer(switch_core_session_t } ringback.fh = &ringback.fhb; } else { - teletone_init_session(&ringback.ts, 0, teletone_handler, &ringback); - ringback.ts.rate = read_codec->implementation->actual_samples_per_second; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Play Ringback Tone [%s]\n", ringback_data); - if (teletone_run(&ringback.ts, ringback_data)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Playing Tone\n"); - teletone_destroy_session(&ringback.ts); - switch_buffer_destroy(&ringback.audio_buffer); - ringback_data = NULL; + if (!strncasecmp(ringback_data, "silence", 7)) { + const char *p = ringback_data + 7; + if (*p == ':') { + p++; + if (p) { + ringback.silence = atoi(p); + } + } + if (ringback.silence <= 0) { + ringback.silence = 400; + } + } else { + teletone_init_session(&ringback.ts, 0, teletone_handler, &ringback); + ringback.ts.rate = read_codec->implementation->actual_samples_per_second; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Play Ringback Tone [%s]\n", ringback_data); + if (teletone_run(&ringback.ts, ringback_data)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Playing Tone\n"); + teletone_destroy_session(&ringback.ts); + switch_buffer_destroy(&ringback.audio_buffer); + ringback_data = NULL; + } } } switch_safe_free(tmp_data); @@ -491,9 +512,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_wait_for_answer(switch_core_session_t write_frame.codec->implementation->decoded_bytes_per_packet)) <= 0) { break; } + } else if (ringback.silence) { + write_frame.datalen = write_frame.codec->implementation->decoded_bytes_per_packet; + switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.datalen / 2, ringback.silence); } - if ((ringback.fh || ringback.audio_buffer) && write_frame.codec && write_frame.datalen) { + if ((ringback.fh || ringback.silence || ringback.audio_buffer) && write_frame.codec && write_frame.datalen) { if (switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) { break; } @@ -769,6 +793,17 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE) || switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA)) { ringback_data = NULL; + } else { + const char *vvar; + + if ((vvar = switch_channel_get_variable(caller_channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE))) { + int sval = atoi(vvar); + + if (sval) { + ringback_data = switch_core_session_sprintf(session, "ringback:%d", sval); + } + + } } } @@ -1292,7 +1327,17 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess } ringback.fh = &ringback.fhb; - + } else if (!strncasecmp(ringback_data, "silence", 7)) { + const char *p = ringback_data + 7; + if (*p == ':') { + p++; + if (p) { + ringback.silence = atoi(p); + } + } + if (ringback.silence <= 0) { + ringback.silence = 400; + } } else { teletone_init_session(&ringback.ts, 0, teletone_handler, &ringback); ringback.ts.rate = read_codec->implementation->actual_samples_per_second; @@ -1436,9 +1481,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess write_frame.codec->implementation->decoded_bytes_per_packet)) <= 0) { break; } + } else if (ringback.silence) { + write_frame.datalen = write_frame.codec->implementation->decoded_bytes_per_packet; + switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.datalen / 2, ringback.silence); } - if ((ringback.fh || ringback.audio_buffer) && write_frame.codec && write_frame.datalen) { + if ((ringback.fh || ringback.silence || ringback.audio_buffer) && write_frame.codec && write_frame.datalen) { if (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 8aac96d86b..0abb3ec63c 100644 --- a/src/switch_resample.c +++ b/src/switch_resample.c @@ -203,18 +203,19 @@ SWITCH_DECLARE(void) switch_swap_linear(int16_t *buf, int len) SWITCH_DECLARE(void) switch_generate_sln_silence(int16_t *data, uint32_t samples, uint32_t divisor) { - int16_t rnd = 0, rnd2, x; + int16_t x; uint32_t i; int sum_rnd = 0; + int16_t rnd2 = (int16_t) switch_timestamp_now(); assert(divisor); - rnd2 = (int16_t) (intptr_t) &data + (int16_t)switch_timestamp(NULL); + for (i = 0; i < samples; i++, sum_rnd = 0) { - for (x = 0; x < 10; x++) { - rnd += (int16_t)((x + i) * rnd2); - sum_rnd += rnd; + for (x = 0; x < 6; x++) { + rnd2 = rnd2 * 31821U + 13849U; + sum_rnd += rnd2; } switch_normalize_to_16bit(sum_rnd); *data = (int16_t) ((int16_t) sum_rnd / (int) divisor); diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 041937ee8c..74fe5bcd63 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -158,6 +158,7 @@ struct switch_rtp { uint32_t last_write_ts; uint32_t last_write_samplecount; uint32_t next_write_samplecount; + switch_time_t last_write_timestamp; uint32_t flags; switch_memory_pool_t *pool; switch_sockaddr_t *from_addr; @@ -1885,15 +1886,27 @@ static int rtp_common_write(switch_rtp_t *rtp_session, rtp_session->send_msg.header.ts = htonl(rtp_session->ts); + if ((rtp_session->ts > (rtp_session->last_write_ts + (rtp_session->samples_per_interval * 10))) || rtp_session->ts == rtp_session->samples_per_interval) { m++; } + if (rtp_session->timer.interval && + (rtp_session->timer.samplecount - rtp_session->last_write_samplecount) > rtp_session->samples_per_interval * 2) { + m++; + } + + if (!rtp_session->timer.interval && + ((unsigned)((switch_timestamp_now() - rtp_session->last_write_timestamp))) > (rtp_session->ms_per_packet *2)) { + m++; + } + if (rtp_session->cn && payload != rtp_session->cng_pt) { rtp_session->cn = 0; m++; } + send_msg->header.m = m ? 1 : 0; memcpy(send_msg->body, data, datalen); @@ -2049,7 +2062,10 @@ static int rtp_common_write(switch_rtp_t *rtp_session, if (rtp_session->timer.interval) { rtp_session->last_write_samplecount = rtp_session->timer.samplecount; + } else { + rtp_session->last_write_timestamp = (uint32_t) switch_timestamp_now(); } + rtp_session->last_write_ts = this_ts; }