From 5367b9615330144e86459701d12de07b6c0d9a28 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Thu, 26 Jul 2012 01:05:36 +0200 Subject: [PATCH] ftmod_isdn: Rework teletone buffer offset handling in isdn_tones_run(). Store the offset in the teletone buffer in the b-channel private data. An NT-mode setup with ftmod_misdn showed severe (dial-)tone distortions in a sound editor (330Hz sine wave phase errors), caused by using a global teletone buffer offset. Switching to a per-channel offset, that is advanced by the amount of data actually written to the channel, removes (almost) all distortions. There is still a minimal phase error every ~500ms (audible) that needs more investigating. Signed-off-by: Stefan Knoblich --- .../freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c | 27 ++++++++++++------- .../freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h | 1 + 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c index 153f380cdd..bd00789248 100644 --- a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c @@ -1797,7 +1797,6 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj) teletone_generation_session_t ts = {{{{0}}}};; unsigned char frame[1024]; int x, interval; - int offset = 0; ftdm_log(FTDM_LOG_DEBUG, "ISDN tones thread starting.\n"); ftdm_set_flag(isdn_data, FTDM_ISDN_TONES_RUNNING); @@ -1842,6 +1841,7 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj) for (x = 1; x <= ftdm_span_get_chan_count(span); x++) { ftdm_channel_t *chan = ftdm_span_get_channel(span, x); ftdm_size_t len = sizeof(frame), rlen; + ftdm_isdn_bchan_data_t *data = chan->call_data; if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_DQ921) { continue; @@ -1855,7 +1855,6 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj) switch (ftdm_channel_get_state(chan)) { case FTDM_CHANNEL_STATE_DIALTONE: { - ftdm_isdn_bchan_data_t *data = (ftdm_isdn_bchan_data_t *)chan->call_data; ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan); /* check overlap dial timeout first before generating tone */ @@ -1933,7 +1932,7 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj) } /* seek to current offset */ - ftdm_buffer_seek(dt_buffer, offset); + ftdm_buffer_seek(dt_buffer, data->offset); rlen = ftdm_buffer_read_loop(dt_buffer, frame, len); @@ -1953,7 +1952,22 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj) goto done; } } - ftdm_channel_write(chan, frame, sizeof(frame), &rlen); + + if (ftdm_channel_write(chan, frame, sizeof(frame), &rlen) == FTDM_SUCCESS) { + /* + * Advance offset in teletone buffer by amount + * of data actually written to channel. + */ + if (chan->effective_codec != FTDM_CODEC_SLIN) { + data->offset += rlen << 1; /* teletone buffer is slin (= len * 2) */ + } else { + data->offset += rlen; + } + + if (data->offset >= ts.rate) { + data->offset = 0; + } + } } /* @@ -1962,11 +1976,6 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj) if (!gated) { ftdm_sleep(interval); } - - offset += (ts.rate / (1000 / interval)) << 1; - if (offset >= ts.rate) { - offset = 0; - } } done: diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h index c8788cf9b0..57e1d5386d 100644 --- a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h @@ -79,6 +79,7 @@ typedef struct ftdm_isdn_data ftdm_isdn_data_t; struct ftdm_isdn_bchan_data { int32_t digit_timeout; + int offset; /* offset in teletone buffer */ }; typedef struct ftdm_isdn_bchan_data ftdm_isdn_bchan_data_t;