a whole bunch of stuff just to avoid a sonus issue silence_when_idle=400 chanvar to send generated silence duing sleeps etc

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@10664 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2008-12-09 00:32:51 +00:00
parent 2ac1b96b29
commit 1136fcec4a
5 changed files with 178 additions and 20 deletions

View File

@ -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"

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}