From 080436b856512843301f9ad11187aef4476bc5a6 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 14 Sep 2009 14:26:31 +0000 Subject: [PATCH] add openzap_pre_buffer_size= to prebuffer audio and cut out residual dtmf tones git-svn-id: http://svn.openzap.org/svn/openzap/trunk@831 a93c3328-9c30-0410-af19-c9cd2b2d52af --- libs/freetdm/mod_openzap/mod_openzap.c | 29 ++++++- libs/freetdm/src/include/openzap.h | 3 + libs/freetdm/src/include/zap_types.h | 1 + .../src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c | 19 +++-- libs/freetdm/src/zap_io.c | 84 +++++++++++++++++-- 5 files changed, 125 insertions(+), 11 deletions(-) diff --git a/libs/freetdm/mod_openzap/mod_openzap.c b/libs/freetdm/mod_openzap/mod_openzap.c index 02c1eebad9..ddefd6e7fd 100644 --- a/libs/freetdm/mod_openzap/mod_openzap.c +++ b/libs/freetdm/mod_openzap/mod_openzap.c @@ -934,10 +934,30 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s { private_t *tech_pvt; switch_status_t status; - + switch_channel_t *channel; + const char *var; + tech_pvt = (private_t *) switch_core_session_get_private(session); assert(tech_pvt != NULL); + channel = switch_core_session_get_channel(session); + + switch (msg->message_id) { + case SWITCH_MESSAGE_INDICATE_PROGRESS: + case SWITCH_MESSAGE_INDICATE_ANSWER: + if (!switch_channel_test_flag(channel, CF_OUTBOUND)) { + if ((var = switch_channel_get_variable(channel, "openzap_pre_buffer_size"))) { + int tmp = atoi(var); + if (tmp > -1) { + zap_channel_command(tech_pvt->zchan, ZAP_COMMAND_SET_PRE_BUFFER_SIZE, &tmp); + } + } + } + break; + default: + break; + } + switch (tech_pvt->zchan->type) { case ZAP_CHAN_TYPE_FXS: case ZAP_CHAN_TYPE_EM: @@ -1119,6 +1139,13 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi return SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION; } + if ((var = switch_event_get_header(var_event, "openzap_pre_buffer_size"))) { + int tmp = atoi(var); + if (tmp > -1) { + zap_channel_command(zchan, ZAP_COMMAND_SET_PRE_BUFFER_SIZE, &tmp); + } + } + zap_channel_clear_vars(zchan); for (h = var_event->headers; h; h = h->next) { if (!strncasecmp(h->name, OPENZAP_VAR_PREFIX, OPENZAP_VAR_PREFIX_LEN)) { diff --git a/libs/freetdm/src/include/openzap.h b/libs/freetdm/src/include/openzap.h index 6b0c703f23..ee09acc2fb 100644 --- a/libs/freetdm/src/include/openzap.h +++ b/libs/freetdm/src/include/openzap.h @@ -503,6 +503,7 @@ struct zap_channel { uint32_t skip_read_frames; zap_buffer_t *dtmf_buffer; zap_buffer_t *gen_dtmf_buffer; + zap_buffer_t *pre_buffer; zap_buffer_t *digit_buffer; zap_buffer_t *fsk_buffer; uint32_t dtmf_on; @@ -529,6 +530,7 @@ struct zap_channel { struct zap_io_interface *zio; zap_hash_t *variable_hash; unsigned char rx_cas_bits; + uint32_t pre_buffer_size; }; @@ -657,6 +659,7 @@ OZ_DECLARE(zap_status_t) zap_channel_use(zap_channel_t *zchan); OZ_DECLARE(zap_status_t) zap_channel_command(zap_channel_t *zchan, zap_command_t command, void *obj); OZ_DECLARE(zap_status_t) zap_channel_wait(zap_channel_t *zchan, zap_wait_flag_t *flags, int32_t to); OZ_DECLARE(zap_status_t) zap_channel_read(zap_channel_t *zchan, void *data, zap_size_t *datalen); +OZ_DECLARE(void) zap_generate_sln_silence(int16_t *data, uint32_t samples, uint32_t divisor); OZ_DECLARE(zap_status_t) zap_channel_write(zap_channel_t *zchan, void *data, zap_size_t datasize, zap_size_t *datalen); OZ_DECLARE(zap_status_t) zap_channel_add_var(zap_channel_t *zchan, const char *var_name, const char *value); OZ_DECLARE(const char *) zap_channel_get_var(zap_channel_t *zchan, const char *var_name); diff --git a/libs/freetdm/src/include/zap_types.h b/libs/freetdm/src/include/zap_types.h index d745a72f46..2db87513a0 100644 --- a/libs/freetdm/src/include/zap_types.h +++ b/libs/freetdm/src/include/zap_types.h @@ -283,6 +283,7 @@ typedef enum { ZAP_COMMAND_FLUSH_TX_BUFFERS, ZAP_COMMAND_FLUSH_RX_BUFFERS, ZAP_COMMAND_FLUSH_BUFFERS, + ZAP_COMMAND_SET_PRE_BUFFER_SIZE, ZAP_COMMAND_COUNT } zap_command_t; diff --git a/libs/freetdm/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c b/libs/freetdm/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c index e6b26852bb..a7f54595f2 100644 --- a/libs/freetdm/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c +++ b/libs/freetdm/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c @@ -323,7 +323,6 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start, zap_copy_string(chan->chan_number, number, sizeof(chan->chan_number)); } configured++; - zap_log(ZAP_LOG_INFO, "configuring device s%dc%d as OpenZAP device %d:%d fd:%d DTMF: %s\n", spanno, x, chan->span_id, chan->chan_id, sockfd, dtmf); @@ -557,6 +556,16 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command) } } break; + case ZAP_COMMAND_ENABLE_ECHOCANCEL: + { + //code me + } + break; + case ZAP_COMMAND_DISABLE_ECHOCANCEL: + { + //code me + } + break; case ZAP_COMMAND_SET_INTERVAL: { err=sangoma_tdm_set_usr_period(zchan->sockfd, &tdm_api, ZAP_COMMAND_OBJ_INT); @@ -984,12 +993,12 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event) event_id = ZAP_OOB_NOOP; //zap_log(ZAP_LOG_DEBUG, "%d:%d queue hardware dtmf %s\n", zchan->span_id, zchan->chan_id, tmp_dtmf); - //if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_PRESENT) { - //zap_set_flag_locked(zchan, ZAP_CHANNEL_MUTE); - //} + if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_PRESENT) { + zap_set_flag_locked(zchan, ZAP_CHANNEL_MUTE); + } if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_STOP) { - //zap_clear_flag_locked(zchan, ZAP_CHANNEL_MUTE); + zap_clear_flag_locked(zchan, ZAP_CHANNEL_MUTE); zap_channel_queue_dtmf(zchan, tmp_dtmf); } } diff --git a/libs/freetdm/src/zap_io.c b/libs/freetdm/src/zap_io.c index 7d2ea3b094..98df71f723 100644 --- a/libs/freetdm/src/zap_io.c +++ b/libs/freetdm/src/zap_io.c @@ -245,6 +245,7 @@ static zap_status_t zap_channel_destroy(zap_channel_t *zchan) zap_sleep(500); } + zap_buffer_destroy(&zchan->pre_buffer); zap_buffer_destroy(&zchan->digit_buffer); zap_buffer_destroy(&zchan->gen_dtmf_buffer); zap_buffer_destroy(&zchan->dtmf_buffer); @@ -986,7 +987,10 @@ OZ_DECLARE(zap_status_t) zap_channel_open_any(uint32_t span_id, zap_direction_t if (zap_test_flag(check, ZAP_CHANNEL_READY) && !zap_test_flag(check, ZAP_CHANNEL_INUSE) && !zap_test_flag(check, ZAP_CHANNEL_SUSPENDED) && - check->state == ZAP_CHANNEL_STATE_DOWN + check->state == ZAP_CHANNEL_STATE_DOWN && + check->type != ZAP_CHAN_TYPE_DQ921 && + check->type != ZAP_CHAN_TYPE_DQ931 + ) { if (span && span->channel_request) { @@ -1195,6 +1199,8 @@ OZ_DECLARE(zap_status_t) zap_channel_done(zap_channel_t *zchan) zap_clear_flag_locked(zchan, ZAP_CHANNEL_PROGRESS); zap_clear_flag_locked(zchan, ZAP_CHANNEL_MEDIA); zap_clear_flag_locked(zchan, ZAP_CHANNEL_ANSWERED); + zap_buffer_destroy(&zchan->pre_buffer); + zchan->init_state = ZAP_CHANNEL_STATE_DOWN; zchan->state = ZAP_CHANNEL_STATE_DOWN; zap_log(ZAP_LOG_DEBUG, "channel done %u:%u\n", zchan->span_id, zchan->chan_id); @@ -1457,6 +1463,27 @@ OZ_DECLARE(zap_status_t) zap_channel_command(zap_channel_t *zchan, zap_command_t } } } + + case ZAP_COMMAND_SET_PRE_BUFFER_SIZE: + { + int val = ZAP_COMMAND_OBJ_INT; + + if (val < 0) { + val = 0; + } + + zchan->pre_buffer_size = val * 8; + + if (!zchan->pre_buffer_size) { + zap_buffer_destroy(&zchan->pre_buffer); + } else if (!zchan->pre_buffer) { + zap_buffer_create(&zchan->pre_buffer, 1024, zchan->pre_buffer_size, 0); + } + + GOTO_STATUS(done, ZAP_SUCCESS); + + } + break; case ZAP_COMMAND_GET_DTMF_ON_PERIOD: { if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_DTMF_GENERATE)) { @@ -1516,6 +1543,13 @@ OZ_DECLARE(zap_status_t) zap_channel_command(zap_channel_t *zchan, zap_command_t } } break; + + case ZAP_COMMAND_DISABLE_ECHOCANCEL: + { + zap_buffer_destroy(&zchan->pre_buffer); + zchan->pre_buffer_size = 0; + } + break; default: break; } @@ -1737,6 +1771,10 @@ OZ_DECLARE(zap_status_t) zap_channel_queue_dtmf(zap_channel_t *zchan, const char assert(zchan != NULL); + if (zchan->pre_buffer) { + zap_buffer_zero(zchan->pre_buffer); + } + zap_mutex_lock(zchan->mutex); inuse = zap_buffer_inuse(zchan->digit_buffer); @@ -1779,6 +1817,7 @@ static zap_status_t handle_dtmf(zap_channel_t *zchan, zap_size_t datalen) { zap_buffer_t *buffer = NULL; zap_size_t dblen = 0; + int wrote = 0; if (zchan->gen_dtmf_buffer && (dblen = zap_buffer_inuse(zchan->gen_dtmf_buffer))) { char digits[128] = ""; @@ -1800,7 +1839,6 @@ static zap_status_t handle_dtmf(zap_channel_t *zchan, zap_size_t datalen) } for (; *cur; cur++) { - int wrote = 0; if ((wrote = teletone_mux_tones(&zchan->tone_session, &zchan->tone_session.TONES[(int)*cur]))) { zap_buffer_write(zchan->dtmf_buffer, zchan->tone_session.buffer, wrote * 2); x++; @@ -1810,7 +1848,7 @@ static zap_status_t handle_dtmf(zap_channel_t *zchan, zap_size_t datalen) } } - zchan->skip_read_frames = 200 * x; + zchan->skip_read_frames = wrote / (1000 / zchan->effective_interval); } } @@ -1855,6 +1893,28 @@ static zap_status_t handle_dtmf(zap_channel_t *zchan, zap_size_t datalen) } +OZ_DECLARE(void) zap_generate_sln_silence(int16_t *data, uint32_t samples, uint32_t divisor) +{ + int16_t x; + uint32_t i; + int sum_rnd = 0; + int16_t rnd2 = (int16_t) zap_current_time_in_ms * (int16_t) (intptr_t) data; + + assert(divisor); + + for (i = 0; i < samples; i++, sum_rnd = 0) { + 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); + + data++; + } +} + + OZ_DECLARE(zap_status_t) zap_channel_read(zap_channel_t *zchan, void *data, zap_size_t *datalen) { @@ -2048,11 +2108,25 @@ OZ_DECLARE(zap_status_t) zap_channel_read(zap_channel_t *zchan, void *data, zap_ } if (zchan->skip_read_frames > 0 || zap_test_flag(zchan, ZAP_CHANNEL_MUTE)) { - memset(data, 0, *datalen); + + if (zchan->pre_buffer && zap_buffer_inuse(zchan->pre_buffer)) { + zap_buffer_zero(zchan->pre_buffer); + } + + memset(data, 255, *datalen); + if (zchan->skip_read_frames > 0) { zchan->skip_read_frames--; } - } + } else if (zchan->pre_buffer_size) { + zap_buffer_write(zchan->pre_buffer, data, *datalen); + if (zap_buffer_inuse(zchan->pre_buffer) >= zchan->pre_buffer_size) { + zap_buffer_read(zchan->pre_buffer, data, *datalen); + } else { + memset(data, 255, *datalen); + } + } + return status; }