FS-3570 receive side, update libteletone to track duration so it is less likely to double detect and push api changes down to freetdm

This commit is contained in:
Anthony Minessale 2011-09-16 10:05:43 -05:00
parent d9ce90d7b9
commit a65794fb5e
14 changed files with 434 additions and 191 deletions

View File

@ -6,7 +6,6 @@ int main(int argc, char *argv[])
int fd, b; int fd, b;
short sln[512] = {0}; short sln[512] = {0};
teletone_dtmf_detect_state_t dtmf_detect = {0}; teletone_dtmf_detect_state_t dtmf_detect = {0};
char digit_str[128] = "";
if (argc < 2) { if (argc < 2) {
fprintf(stderr, "Arg Error!\n"); fprintf(stderr, "Arg Error!\n");
@ -21,10 +20,29 @@ int main(int argc, char *argv[])
} }
while((b = read(fd, sln, 320)) > 0) { while((b = read(fd, sln, 320)) > 0) {
char digit_char;
unsigned int dur;
teletone_dtmf_detect(&dtmf_detect, sln, b / 2); teletone_dtmf_detect(&dtmf_detect, sln, b / 2);
teletone_dtmf_get(&dtmf_detect, digit_str, sizeof(digit_str)); if ((hit = teletone_dtmf_get(&dtmf_detect, &digit_char, &dur))) {
if (*digit_str) { char *hs = NULL;
printf("digit: %s\n", digit_str);
switch(hit) {
case TT_HIT_BEGIN:
hs = "begin";
break;
case TT_HIT_MIDDLE:
hs = "middle";
break;
case TT_HIT_END:
hs = "end";
break;
}
printf("%s digit: %s\n", hs, digit_str);
} }
} }
close(fd); close(fd);

View File

@ -3859,7 +3859,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, v
uint8_t sln_buf[1024] = {0}; uint8_t sln_buf[1024] = {0};
int16_t *sln; int16_t *sln;
ftdm_size_t slen = 0; ftdm_size_t slen = 0;
char digit_str[80] = "";
if (ftdmchan->effective_codec == FTDM_CODEC_SLIN) { if (ftdmchan->effective_codec == FTDM_CODEC_SLIN) {
sln = data; sln = data;
@ -3960,13 +3959,18 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, v
} }
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT) && !ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) { if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT) && !ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
teletone_dtmf_detect(&ftdmchan->dtmf_detect, sln, (int)slen); teletone_hit_type_t hit;
teletone_dtmf_get(&ftdmchan->dtmf_detect, digit_str, sizeof(digit_str)); char digit_char;
uint32_t dur;
if(*digit_str) { teletone_dtmf_detect(&ftdmchan->dtmf_detect, sln, (int)slen);
if (ftdmchan->state == FTDM_CHANNEL_STATE_CALLWAITING && (*digit_str == 'D' || *digit_str == 'A')) {
if ((hit = teletone_dtmf_get(&ftdmchan->dtmf_detect, &digit_char, &dur)) == TT_HIT_BEGIN) {
if (ftdmchan->state == FTDM_CHANNEL_STATE_CALLWAITING && (digit_char == 'D' || digit_char == 'A')) {
ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK]++; ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK]++;
} else { } else {
char digit_str[2] = { digit_char, 0};
if (!ftdmchan->span->sig_dtmf || (ftdmchan->span->sig_dtmf(ftdmchan, (const char*)digit_str) != FTDM_BREAK)) { if (!ftdmchan->span->sig_dtmf || (ftdmchan->span->sig_dtmf(ftdmchan, (const char*)digit_str) != FTDM_BREAK)) {
ftdm_channel_queue_dtmf(ftdmchan, digit_str); ftdm_channel_queue_dtmf(ftdmchan, digit_str);
} }

View File

@ -4,10 +4,10 @@
* *
* Version: MPL 1.1 * Version: MPL 1.1
* *
* The contents of this file are subject to the Mftilla Public License Version * The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with * 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at * the License. You may obtain a copy of the License at
* http://www.mftilla.org/MPL/ * http://www.mozilla.org/MPL/
* *
* Software distributed under the License is distributed on an "AS IS" basis, * Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
@ -33,8 +33,8 @@
* Exception: * Exception:
* The author hereby grants the use of this source code under the * The author hereby grants the use of this source code under the
* following license if and only if the source code is distributed * following license if and only if the source code is distributed
* as part of the freetdm library. Any use or distribution of this * as part of the OpenZAP or FreeTDM library. Any use or distribution of this
* source code outside the scope of the freetdm library will nullify the * source code outside the scope of the OpenZAP or FreeTDM library will nullify the
* following license and reinact the MPL 1.1 as stated above. * following license and reinact the MPL 1.1 as stated above.
* *
* Copyright (c) 2007, Anthony Minessale II * Copyright (c) 2007, Anthony Minessale II
@ -136,8 +136,8 @@ typedef __int16 int16_t;
#endif #endif
#endif #endif
#include "libteletone_generate.h" #include <libteletone_generate.h>
#include "libteletone_detect.h" #include <libteletone_detect.h>
#ifdef HAVE_STRING_H #ifdef HAVE_STRING_H
#include <string.h> #include <string.h>

View File

@ -2,13 +2,60 @@
* libteletone * libteletone
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org> * Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
* *
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is tone_detect.c - General telephony tone detection, and specific detection of DTMF.
*
*
* The Initial Developer of the Original Code is
* Stephen Underwood <steveu@coppice.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* The the original interface designed by Steve Underwood was preserved to retain
*the optimizations when considering DTMF tones though the names were changed in the interest
* of namespace.
*
* Much less efficient expansion interface was added to allow for the detection of
* a single arbitrary tone combination which may also exceed 2 simultaneous tones.
* (controlled by compile time constant TELETONE_MAX_TONES)
*
* Copyright (C) 2006 Anthony Minessale II <anthm@freeswitch.org>
*
*
* libteletone_detect.c Tone Detection Code * libteletone_detect.c Tone Detection Code
* *
*
*********************************************************************************
*
* Derived from tone_detect.h - General telephony tone detection, and specific
* detection of DTMF.
*
* Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
*
* Despite my general liking of the GPL, I place this code in the
* public domain for the benefit of all mankind - even the slimy
* ones who might try to proprietize my work and use it to my
* detriment.
*
*
* Exception: * Exception:
* The author hereby grants the use of this source code under the * The author hereby grants the use of this source code under the
* following license if and only if the source code is distributed * following license if and only if the source code is distributed
* as part of the freetdm library. Any use or distribution of this * as part of the OpenZAP or FreeTDM library. Any use or distribution of this
* source code outside the scope of the freetdm library will nullify the * source code outside the scope of the OpenZAP or FreeTDM library will nullify the
* following license and reinact the MPL 1.1 as stated above. * following license and reinact the MPL 1.1 as stated above.
* *
* Copyright (c) 2007, Anthony Minessale II * Copyright (c) 2007, Anthony Minessale II
@ -41,20 +88,6 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*********************************************************************************
*
* Derived from tone_detect.h - General telephony tone detection, and specific
* detection of DTMF.
*
* Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
*
* Despite my general liking of the GPL, I place this code in the
* public domain for the benefit of all mankind - even the slimy
* ones who might try to proprietize my work and use it to my
* detriment.
*
*
*/ */
#ifndef LIBTELETONE_DETECT_H #ifndef LIBTELETONE_DETECT_H
@ -63,7 +96,7 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include "libteletone.h" #include <libteletone.h>
/*! \file libteletone_detect.h /*! \file libteletone_detect.h
\brief Tone Detection Routines \brief Tone Detection Routines
@ -101,6 +134,14 @@ extern "C" {
#define BLOCK_LEN 102 #define BLOCK_LEN 102
#define M_TWO_PI 2.0*M_PI #define M_TWO_PI 2.0*M_PI
typedef enum {
TT_HIT_NONE = 0,
TT_HIT_BEGIN = 1,
TT_HIT_MIDDLE = 2,
TT_HIT_END = 3
} teletone_hit_type_t;
/*! \brief A continer for the elements of a Goertzel Algorithm (The names are from his formula) */ /*! \brief A continer for the elements of a Goertzel Algorithm (The names are from his formula) */
typedef struct { typedef struct {
float v2; float v2;
@ -114,16 +155,19 @@ extern "C" {
int hit2; int hit2;
int hit3; int hit3;
int hit4; int hit4;
int mhit; int dur;
int zc;
teletone_goertzel_state_t row_out[GRID_FACTOR]; teletone_goertzel_state_t row_out[GRID_FACTOR];
teletone_goertzel_state_t col_out[GRID_FACTOR]; teletone_goertzel_state_t col_out[GRID_FACTOR];
teletone_goertzel_state_t row_out2nd[GRID_FACTOR]; teletone_goertzel_state_t row_out2nd[GRID_FACTOR];
teletone_goertzel_state_t col_out2nd[GRID_FACTOR]; teletone_goertzel_state_t col_out2nd[GRID_FACTOR];
float energy; float energy;
float lenergy;
int current_sample; int current_sample;
char digits[TELETONE_MAX_DTMF_DIGITS + 1]; char digit;
int current_digits; int current_digits;
int detected_digits; int detected_digits;
int lost_digits; int lost_digits;
@ -196,7 +240,7 @@ TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf
\param samples the number of samples present in sample_buffer \param samples the number of samples present in sample_buffer
\return true when DTMF was detected or false when it is not \return true when DTMF was detected or false when it is not
*/ */
TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state, TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
int16_t sample_buffer[], int16_t sample_buffer[],
int samples); int samples);
/*! /*!
@ -206,9 +250,7 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
\param max the maximum length of buf \param max the maximum length of buf
\return the number of characters written to buf \return the number of characters written to buf
*/ */
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur);
char *buf,
int max);
/*! /*!
\brief Step through the Goertzel Algorithm for each sample in a buffer \brief Step through the Goertzel Algorithm for each sample in a buffer

View File

@ -2,6 +2,41 @@
* libteletone * libteletone
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org> * Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
* *
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is libteletone
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
*
*
* libteletone.h -- Tone Generator
*
*
*
* Exception:
* The author hereby grants the use of this source code under the
* following license if and only if the source code is distributed
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
* following license and reinact the MPL 1.1 as stated above.
*
* Copyright (c) 2007, Anthony Minessale II * Copyright (c) 2007, Anthony Minessale II
* All rights reserved. * All rights reserved.
* *
@ -81,7 +116,7 @@ extern float powf (float, float);
#endif #endif
#include <assert.h> #include <assert.h>
#include <stdarg.h> #include <stdarg.h>
#include "libteletone.h" #include <libteletone.h>
#define TELETONE_VOL_DB_MAX 0 #define TELETONE_VOL_DB_MAX 0
#define TELETONE_VOL_DB_MIN -63 #define TELETONE_VOL_DB_MIN -63

View File

@ -2,14 +2,62 @@
* libteletone * libteletone
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org> * Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
* *
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is tone_detect.c - General telephony tone detection, and specific detection of DTMF.
*
*
* The Initial Developer of the Original Code is
* Stephen Underwood <steveu@coppice.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* The the original interface designed by Steve Underwood was preserved to retain
*the optimizations when considering DTMF tones though the names were changed in the interest
* of namespace.
*
* Much less efficient expansion interface was added to allow for the detection of * Much less efficient expansion interface was added to allow for the detection of
* a single arbitrary tone combination which may also exceed 2 simultaneous tones. * a single arbitrary tone combination which may also exceed 2 simultaneous tones.
* (controlled by compile time constant TELETONE_MAX_TONES) * (controlled by compile time constant TELETONE_MAX_TONES)
* *
* Copyright (C) 2006 Anthony Minessale II <anthm@freeswitch.org> * Copyright (C) 2006 Anthony Minessale II <anthm@freeswitch.org>
* *
*
* libteletone_detect.c Tone Detection Code * libteletone_detect.c Tone Detection Code
* *
*
*********************************************************************************
*
* Derived from tone_detect.c - General telephony tone detection, and specific
* detection of DTMF.
*
* Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
*
* Despite my general liking of the GPL, I place this code in the
* public domain for the benefit of all mankind - even the slimy
* ones who might try to proprietize my work and use it to my
* detriment.
*
*
* Exception:
* The author hereby grants the use of this source code under the
* following license if and only if the source code is distributed
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
* following license and reinact the MPL 1.1 as stated above.
*
* Copyright (c) 2007, Anthony Minessale II * Copyright (c) 2007, Anthony Minessale II
* All rights reserved. * All rights reserved.
* *
@ -40,21 +88,6 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*********************************************************************************
*
* Derived from tone_detect.c - General telephony tone detection, and specific
* detection of DTMF.
*
* Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
*
* Despite my general liking of the GPL, I place this code in the
* public domain for the benefit of all mankind - even the slimy
* ones who might try to proprietize my work and use it to my
* detriment.
*
*
*
*/ */
#include <libteletone_detect.h> #include <libteletone_detect.h>
@ -67,7 +100,8 @@
#include <time.h> #include <time.h>
#include <fcntl.h> #include <fcntl.h>
#define LOW_ENG 10000000
#define ZC 2
static teletone_detection_descriptor_t dtmf_detect_row[GRID_FACTOR]; static teletone_detection_descriptor_t dtmf_detect_row[GRID_FACTOR];
static teletone_detection_descriptor_t dtmf_detect_col[GRID_FACTOR]; static teletone_detection_descriptor_t dtmf_detect_col[GRID_FACTOR];
static teletone_detection_descriptor_t dtmf_detect_row_2nd[GRID_FACTOR]; static teletone_detection_descriptor_t dtmf_detect_row_2nd[GRID_FACTOR];
@ -132,8 +166,8 @@ TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf
dtmf_detect_state->current_sample = 0; dtmf_detect_state->current_sample = 0;
dtmf_detect_state->detected_digits = 0; dtmf_detect_state->detected_digits = 0;
dtmf_detect_state->lost_digits = 0; dtmf_detect_state->lost_digits = 0;
dtmf_detect_state->digits[0] = '\0'; dtmf_detect_state->digit = 0;
dtmf_detect_state->mhit = 0; dtmf_detect_state->dur = 0;
} }
TELETONE_API(void) teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map) TELETONE_API(void) teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map)
@ -266,7 +300,7 @@ TELETONE_API(int) teletone_multi_tone_detect (teletone_multi_tone_t *mt,
} }
TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state, TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
int16_t sample_buffer[], int16_t sample_buffer[],
int samples) int samples)
{ {
@ -281,6 +315,7 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
int best_col; int best_col;
char hit; char hit;
int limit; int limit;
teletone_hit_type_t r = 0;
hit = 0; hit = 0;
for (sample = 0; sample < samples; sample = limit) { for (sample = 0; sample < samples; sample = limit) {
@ -317,6 +352,32 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
} }
if (dtmf_detect_state->zc > 0) {
if (dtmf_detect_state->energy < LOW_ENG && dtmf_detect_state->lenergy < LOW_ENG) {
if (!--dtmf_detect_state->zc) {
/* Reinitialise the detector for the next block */
dtmf_detect_state->hit1 = dtmf_detect_state->hit2 = 0;
for (i = 0; i < GRID_FACTOR; i++) {
goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
}
dtmf_detect_state->dur -= samples;
return TT_HIT_END;
}
}
dtmf_detect_state->dur += samples;
dtmf_detect_state->lenergy = dtmf_detect_state->energy;
dtmf_detect_state->energy = 0.0;
dtmf_detect_state->current_sample = 0;
return TT_HIT_MIDDLE;
} else if (dtmf_detect_state->digit) {
return TT_HIT_END;
}
dtmf_detect_state->current_sample += (limit - sample); dtmf_detect_state->current_sample += (limit - sample);
if (dtmf_detect_state->current_sample < BLOCK_LEN) { if (dtmf_detect_state->current_sample < BLOCK_LEN) {
continue; continue;
@ -361,58 +422,54 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
back to back differing digits. More importantly, it back to back differing digits. More importantly, it
can work with nasty phones that give a very wobbly start can work with nasty phones that give a very wobbly start
to a digit. */ to a digit. */
if (hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) { if (! r && hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) {
dtmf_detect_state->mhit = hit;
dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++; dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++;
dtmf_detect_state->detected_digits++; dtmf_detect_state->detected_digits++;
if (dtmf_detect_state->current_digits < TELETONE_MAX_DTMF_DIGITS) { if (dtmf_detect_state->current_digits < TELETONE_MAX_DTMF_DIGITS) {
dtmf_detect_state->digits[dtmf_detect_state->current_digits++] = hit; dtmf_detect_state->digit = hit;
dtmf_detect_state->digits[dtmf_detect_state->current_digits] = '\0'; } else {
dtmf_detect_state->lost_digits++;
} }
else
{ if (!dtmf_detect_state->zc) {
dtmf_detect_state->lost_digits++; dtmf_detect_state->zc = ZC;
} dtmf_detect_state->dur = 0;
r = TT_HIT_BEGIN;
}
} }
} }
} }
dtmf_detect_state->hit1 = dtmf_detect_state->hit2; dtmf_detect_state->hit1 = dtmf_detect_state->hit2;
dtmf_detect_state->hit2 = dtmf_detect_state->hit3; dtmf_detect_state->hit2 = dtmf_detect_state->hit3;
dtmf_detect_state->hit3 = hit; dtmf_detect_state->hit3 = hit;
/* Reinitialise the detector for the next block */
for (i = 0; i < GRID_FACTOR; i++) {
goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
}
dtmf_detect_state->energy = 0.0; dtmf_detect_state->energy = 0.0;
dtmf_detect_state->current_sample = 0; dtmf_detect_state->current_sample = 0;
} }
if ((!dtmf_detect_state->mhit) || (dtmf_detect_state->mhit != hit)) {
dtmf_detect_state->mhit = 0; return r;
return(0);
}
return (hit);
} }
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur)
char *buf,
int max)
{ {
teletone_assert(dtmf_detect_state->current_digits <= TELETONE_MAX_DTMF_DIGITS); if (!dtmf_detect_state->digit) {
return 0;
}
if (max > dtmf_detect_state->current_digits) { *buf = dtmf_detect_state->digit;
max = dtmf_detect_state->current_digits;
*dur = dtmf_detect_state->dur;
if (!dtmf_detect_state->zc) {
dtmf_detect_state->dur = 0;
dtmf_detect_state->digit = 0;
} }
if (max > 0) {
memcpy (buf, dtmf_detect_state->digits, max); return 1;
memmove (dtmf_detect_state->digits, dtmf_detect_state->digits + max, dtmf_detect_state->current_digits - max);
dtmf_detect_state->current_digits -= max;
}
buf[max] = '\0';
return max;
} }
/* For Emacs: /* For Emacs:

View File

@ -1,5 +1,41 @@
/* /*
* libteletone_generate.c -- Tone Generator * libteletone
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is libteletone
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
*
*
* libteletone.c -- Tone Generator
*
*
*
* Exception:
* The author hereby grants the use of this source code under the
* following license if and only if the source code is distributed
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
* following license and reinact the MPL 1.1 as stated above.
* *
* Copyright (c) 2007, Anthony Minessale II * Copyright (c) 2007, Anthony Minessale II
* All rights reserved. * All rights reserved.
@ -34,7 +70,6 @@
*/ */
#include <libteletone.h> #include <libteletone.h>
#include "private/ftdm_core.h"
#define SMAX 32767 #define SMAX 32767
#define SMIN -32768 #define SMIN -32768
@ -111,7 +146,7 @@ TELETONE_API(int) teletone_init_session(teletone_generation_session_t *ts, int b
ts->decay_step = 0; ts->decay_step = 0;
ts->decay_factor = 1; ts->decay_factor = 1;
if (buflen) { if (buflen) {
if ((ts->buffer = ftdm_calloc(buflen, sizeof(teletone_audio_t))) == 0) { if ((ts->buffer = calloc(buflen, sizeof(teletone_audio_t))) == 0) {
return -1; return -1;
} }
ts->datalen = buflen; ts->datalen = buflen;
@ -142,7 +177,7 @@ TELETONE_API(int) teletone_init_session(teletone_generation_session_t *ts, int b
TELETONE_API(int) teletone_destroy_session(teletone_generation_session_t *ts) TELETONE_API(int) teletone_destroy_session(teletone_generation_session_t *ts)
{ {
if (ts->buffer) { if (ts->buffer) {
ftdm_safe_free(ts->buffer); free(ts->buffer);
ts->buffer = NULL; ts->buffer = NULL;
ts->samples = 0; ts->samples = 0;
} }
@ -270,6 +305,19 @@ TELETONE_API(int) teletone_mux_tones(teletone_generation_session_t *ts, teletone
return ts->samples / ts->channels; return ts->samples / ts->channels;
} }
/* don't ask */
static char *my_strdup (const char *s)
{
size_t len = strlen (s) + 1;
void *new = malloc (len);
if (new == NULL) {
return NULL;
}
return (char *) memcpy (new, s, len);
}
TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cmd) TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cmd)
{ {
char *data = NULL, *cur = NULL, *end = NULL; char *data = NULL, *cur = NULL, *end = NULL;
@ -280,7 +328,7 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm
} }
do { do {
if (!(data = ftdm_strdup(cmd))) { if (!(data = my_strdup(cmd))) {
return -1; return -1;
} }
@ -363,6 +411,9 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm
*e++ = '\0'; *e++ = '\0';
} }
do { do {
if (!p) {
break;
}
if ((next = strchr(p, ',')) != 0) { if ((next = strchr(p, ',')) != 0) {
*next++ = '\0'; *next++ = '\0';
} }
@ -427,7 +478,7 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm
} }
} }
bottom: bottom:
ftdm_safe_free(data); free(data);
data = NULL; data = NULL;
if (ts->LOOPS > 0) { if (ts->LOOPS > 0) {
ts->LOOPS--; ts->LOOPS--;

View File

@ -33,8 +33,8 @@
* Exception: * Exception:
* The author hereby grants the use of this source code under the * The author hereby grants the use of this source code under the
* following license if and only if the source code is distributed * following license if and only if the source code is distributed
* as part of the openzap library. Any use or distribution of this * as part of the OpenZAP or FreeTDM library. Any use or distribution of this
* source code outside the scope of the openzap library will nullify the * source code outside the scope of the OpenZAP or FreeTDM library will nullify the
* following license and reinact the MPL 1.1 as stated above. * following license and reinact the MPL 1.1 as stated above.
* *
* Copyright (c) 2007, Anthony Minessale II * Copyright (c) 2007, Anthony Minessale II

View File

@ -54,8 +54,8 @@
* Exception: * Exception:
* The author hereby grants the use of this source code under the * The author hereby grants the use of this source code under the
* following license if and only if the source code is distributed * following license if and only if the source code is distributed
* as part of the openzap library. Any use or distribution of this * as part of the OpenZAP or FreeTDM library. Any use or distribution of this
* source code outside the scope of the openzap library will nullify the * source code outside the scope of the OpenZAP or FreeTDM library will nullify the
* following license and reinact the MPL 1.1 as stated above. * following license and reinact the MPL 1.1 as stated above.
* *
* Copyright (c) 2007, Anthony Minessale II * Copyright (c) 2007, Anthony Minessale II
@ -100,7 +100,8 @@
#include <time.h> #include <time.h>
#include <fcntl.h> #include <fcntl.h>
#define LOW_ENG 10000000
#define ZC 2
static teletone_detection_descriptor_t dtmf_detect_row[GRID_FACTOR]; static teletone_detection_descriptor_t dtmf_detect_row[GRID_FACTOR];
static teletone_detection_descriptor_t dtmf_detect_col[GRID_FACTOR]; static teletone_detection_descriptor_t dtmf_detect_col[GRID_FACTOR];
static teletone_detection_descriptor_t dtmf_detect_row_2nd[GRID_FACTOR]; static teletone_detection_descriptor_t dtmf_detect_row_2nd[GRID_FACTOR];
@ -165,8 +166,8 @@ TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf
dtmf_detect_state->current_sample = 0; dtmf_detect_state->current_sample = 0;
dtmf_detect_state->detected_digits = 0; dtmf_detect_state->detected_digits = 0;
dtmf_detect_state->lost_digits = 0; dtmf_detect_state->lost_digits = 0;
dtmf_detect_state->digits[0] = '\0'; dtmf_detect_state->digit = 0;
dtmf_detect_state->mhit = 0; dtmf_detect_state->dur = 0;
} }
TELETONE_API(void) teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map) TELETONE_API(void) teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map)
@ -299,7 +300,7 @@ TELETONE_API(int) teletone_multi_tone_detect (teletone_multi_tone_t *mt,
} }
TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state, TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
int16_t sample_buffer[], int16_t sample_buffer[],
int samples) int samples)
{ {
@ -314,6 +315,7 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
int best_col; int best_col;
char hit; char hit;
int limit; int limit;
teletone_hit_type_t r = 0;
hit = 0; hit = 0;
for (sample = 0; sample < samples; sample = limit) { for (sample = 0; sample < samples; sample = limit) {
@ -350,6 +352,32 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
} }
if (dtmf_detect_state->zc > 0) {
if (dtmf_detect_state->energy < LOW_ENG && dtmf_detect_state->lenergy < LOW_ENG) {
if (!--dtmf_detect_state->zc) {
/* Reinitialise the detector for the next block */
dtmf_detect_state->hit1 = dtmf_detect_state->hit2 = 0;
for (i = 0; i < GRID_FACTOR; i++) {
goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
}
dtmf_detect_state->dur -= samples;
return TT_HIT_END;
}
}
dtmf_detect_state->dur += samples;
dtmf_detect_state->lenergy = dtmf_detect_state->energy;
dtmf_detect_state->energy = 0.0;
dtmf_detect_state->current_sample = 0;
return TT_HIT_MIDDLE;
} else if (dtmf_detect_state->digit) {
return TT_HIT_END;
}
dtmf_detect_state->current_sample += (limit - sample); dtmf_detect_state->current_sample += (limit - sample);
if (dtmf_detect_state->current_sample < BLOCK_LEN) { if (dtmf_detect_state->current_sample < BLOCK_LEN) {
continue; continue;
@ -394,58 +422,54 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
back to back differing digits. More importantly, it back to back differing digits. More importantly, it
can work with nasty phones that give a very wobbly start can work with nasty phones that give a very wobbly start
to a digit. */ to a digit. */
if (hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) { if (! r && hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) {
dtmf_detect_state->mhit = hit;
dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++; dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++;
dtmf_detect_state->detected_digits++; dtmf_detect_state->detected_digits++;
if (dtmf_detect_state->current_digits < TELETONE_MAX_DTMF_DIGITS) { if (dtmf_detect_state->current_digits < TELETONE_MAX_DTMF_DIGITS) {
dtmf_detect_state->digits[dtmf_detect_state->current_digits++] = hit; dtmf_detect_state->digit = hit;
dtmf_detect_state->digits[dtmf_detect_state->current_digits] = '\0'; } else {
dtmf_detect_state->lost_digits++;
} }
else
{ if (!dtmf_detect_state->zc) {
dtmf_detect_state->lost_digits++; dtmf_detect_state->zc = ZC;
} dtmf_detect_state->dur = 0;
r = TT_HIT_BEGIN;
}
} }
} }
} }
dtmf_detect_state->hit1 = dtmf_detect_state->hit2; dtmf_detect_state->hit1 = dtmf_detect_state->hit2;
dtmf_detect_state->hit2 = dtmf_detect_state->hit3; dtmf_detect_state->hit2 = dtmf_detect_state->hit3;
dtmf_detect_state->hit3 = hit; dtmf_detect_state->hit3 = hit;
/* Reinitialise the detector for the next block */
for (i = 0; i < GRID_FACTOR; i++) {
goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
}
dtmf_detect_state->energy = 0.0; dtmf_detect_state->energy = 0.0;
dtmf_detect_state->current_sample = 0; dtmf_detect_state->current_sample = 0;
} }
if ((!dtmf_detect_state->mhit) || (dtmf_detect_state->mhit != hit)) {
dtmf_detect_state->mhit = 0; return r;
return(0);
}
return (hit);
} }
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur)
char *buf,
int max)
{ {
teletone_assert(dtmf_detect_state->current_digits <= TELETONE_MAX_DTMF_DIGITS); if (!dtmf_detect_state->digit) {
return 0;
}
if (max > dtmf_detect_state->current_digits) { *buf = dtmf_detect_state->digit;
max = dtmf_detect_state->current_digits;
*dur = dtmf_detect_state->dur;
if (!dtmf_detect_state->zc) {
dtmf_detect_state->dur = 0;
dtmf_detect_state->digit = 0;
} }
if (max > 0) {
memcpy (buf, dtmf_detect_state->digits, max); return 1;
memmove (dtmf_detect_state->digits, dtmf_detect_state->digits + max, dtmf_detect_state->current_digits - max);
dtmf_detect_state->current_digits -= max;
}
buf[max] = '\0';
return max;
} }
/* For Emacs: /* For Emacs:

View File

@ -54,8 +54,8 @@
* Exception: * Exception:
* The author hereby grants the use of this source code under the * The author hereby grants the use of this source code under the
* following license if and only if the source code is distributed * following license if and only if the source code is distributed
* as part of the openzap library. Any use or distribution of this * as part of the OpenZAP or FreeTDM library. Any use or distribution of this
* source code outside the scope of the openzap library will nullify the * source code outside the scope of the OpenZAP or FreeTDM library will nullify the
* following license and reinact the MPL 1.1 as stated above. * following license and reinact the MPL 1.1 as stated above.
* *
* Copyright (c) 2007, Anthony Minessale II * Copyright (c) 2007, Anthony Minessale II
@ -134,6 +134,14 @@ extern "C" {
#define BLOCK_LEN 102 #define BLOCK_LEN 102
#define M_TWO_PI 2.0*M_PI #define M_TWO_PI 2.0*M_PI
typedef enum {
TT_HIT_NONE = 0,
TT_HIT_BEGIN = 1,
TT_HIT_MIDDLE = 2,
TT_HIT_END = 3
} teletone_hit_type_t;
/*! \brief A continer for the elements of a Goertzel Algorithm (The names are from his formula) */ /*! \brief A continer for the elements of a Goertzel Algorithm (The names are from his formula) */
typedef struct { typedef struct {
float v2; float v2;
@ -147,16 +155,19 @@ extern "C" {
int hit2; int hit2;
int hit3; int hit3;
int hit4; int hit4;
int mhit; int dur;
int zc;
teletone_goertzel_state_t row_out[GRID_FACTOR]; teletone_goertzel_state_t row_out[GRID_FACTOR];
teletone_goertzel_state_t col_out[GRID_FACTOR]; teletone_goertzel_state_t col_out[GRID_FACTOR];
teletone_goertzel_state_t row_out2nd[GRID_FACTOR]; teletone_goertzel_state_t row_out2nd[GRID_FACTOR];
teletone_goertzel_state_t col_out2nd[GRID_FACTOR]; teletone_goertzel_state_t col_out2nd[GRID_FACTOR];
float energy; float energy;
float lenergy;
int current_sample; int current_sample;
char digits[TELETONE_MAX_DTMF_DIGITS + 1]; char digit;
int current_digits; int current_digits;
int detected_digits; int detected_digits;
int lost_digits; int lost_digits;
@ -229,7 +240,7 @@ TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf
\param samples the number of samples present in sample_buffer \param samples the number of samples present in sample_buffer
\return true when DTMF was detected or false when it is not \return true when DTMF was detected or false when it is not
*/ */
TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state, TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
int16_t sample_buffer[], int16_t sample_buffer[],
int samples); int samples);
/*! /*!
@ -239,9 +250,7 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
\param max the maximum length of buf \param max the maximum length of buf
\return the number of characters written to buf \return the number of characters written to buf
*/ */
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur);
char *buf,
int max);
/*! /*!
\brief Step through the Goertzel Algorithm for each sample in a buffer \brief Step through the Goertzel Algorithm for each sample in a buffer

View File

@ -33,8 +33,8 @@
* Exception: * Exception:
* The author hereby grants the use of this source code under the * The author hereby grants the use of this source code under the
* following license if and only if the source code is distributed * following license if and only if the source code is distributed
* as part of the openzap library. Any use or distribution of this * as part of the OpenZAP or FreeTDM library. Any use or distribution of this
* source code outside the scope of the openzap library will nullify the * source code outside the scope of the OpenZAP or FreeTDM library will nullify the
* following license and reinact the MPL 1.1 as stated above. * following license and reinact the MPL 1.1 as stated above.
* *
* Copyright (c) 2007, Anthony Minessale II * Copyright (c) 2007, Anthony Minessale II

View File

@ -33,8 +33,8 @@
* Exception: * Exception:
* The author hereby grants the use of this source code under the * The author hereby grants the use of this source code under the
* following license if and only if the source code is distributed * following license if and only if the source code is distributed
* as part of the openzap library. Any use or distribution of this * as part of the OpenZAP or FreeTDM library. Any use or distribution of this
* source code outside the scope of the openzap library will nullify the * source code outside the scope of the OpenZAP or FreeTDM library will nullify the
* following license and reinact the MPL 1.1 as stated above. * following license and reinact the MPL 1.1 as stated above.
* *
* Copyright (c) 2007, Anthony Minessale II * Copyright (c) 2007, Anthony Minessale II

View File

@ -92,40 +92,49 @@ static void check_timeouts(void)
void *val; void *val;
time_t now; time_t now;
valet_lot_t *lot; valet_lot_t *lot;
switch_console_callback_match_t *matches = NULL;
switch_console_callback_match_node_t *m;
switch_hash_index_t *i_hi;
const void *i_var;
void *i_val;
char *i_ext;
valet_token_t *token;
now = switch_epoch_time_now(NULL); now = switch_epoch_time_now(NULL);
switch_mutex_lock(globals.mutex); switch_mutex_lock(globals.mutex);
for (hi = switch_hash_first(NULL, globals.hash); hi; hi = switch_hash_next(hi)) { for (hi = switch_hash_first(NULL, globals.hash); hi; hi = switch_hash_next(hi)) {
switch_hash_index_t *i_hi;
const void *i_var;
void *i_val;
char *i_ext;
valet_token_t *token;
switch_hash_this(hi, &var, NULL, &val); switch_hash_this(hi, &var, NULL, &val);
lot = (valet_lot_t *) val; switch_console_push_match(&matches, (const char *) var);
switch_mutex_lock(lot->mutex);
top:
for (i_hi = switch_hash_first(NULL, lot->hash); i_hi; i_hi = switch_hash_next(i_hi)) {
switch_hash_this(i_hi, &i_var, NULL, &i_val);
i_ext = (char *) i_var;
token = (valet_token_t *) i_val;
if (token->timeout > 0 && (token->timeout < now || token->timeout == 1)) {
switch_core_hash_delete(lot->hash, i_ext);
switch_safe_free(token);
goto top;
}
}
switch_mutex_unlock(lot->mutex);
} }
switch_mutex_unlock(globals.mutex); switch_mutex_unlock(globals.mutex);
if (matches) {
for (m = matches->head; m; m = m->next) {
lot = valet_find_lot(m->val);
switch_mutex_lock(lot->mutex);
top:
for (i_hi = switch_hash_first(NULL, lot->hash); i_hi; i_hi = switch_hash_next(i_hi)) {
switch_hash_this(i_hi, &i_var, NULL, &i_val);
i_ext = (char *) i_var;
token = (valet_token_t *) i_val;
if (token->timeout > 0 && (token->timeout < now || token->timeout == 1)) {
switch_core_hash_delete(lot->hash, i_ext);
switch_safe_free(token);
goto top;
}
}
switch_mutex_unlock(lot->mutex);
}
switch_console_free_matches(&matches);
}
} }
static int next_id(valet_lot_t *lot, int min, int max, int in) static int next_id(valet_lot_t *lot, int min, int max, int in)

View File

@ -2139,8 +2139,8 @@ static switch_bool_t inband_dtmf_callback(switch_media_bug_t *bug, void *user_da
{ {
switch_inband_dtmf_t *pvt = (switch_inband_dtmf_t *) user_data; switch_inband_dtmf_t *pvt = (switch_inband_dtmf_t *) user_data;
switch_frame_t *frame = NULL; switch_frame_t *frame = NULL;
char digit_str[80];
switch_channel_t *channel = switch_core_session_get_channel(pvt->session); switch_channel_t *channel = switch_core_session_get_channel(pvt->session);
teletone_hit_type_t hit;
switch (type) { switch (type) {
case SWITCH_ABC_TYPE_INIT: case SWITCH_ABC_TYPE_INIT:
@ -2149,20 +2149,14 @@ static switch_bool_t inband_dtmf_callback(switch_media_bug_t *bug, void *user_da
break; break;
case SWITCH_ABC_TYPE_READ_REPLACE: case SWITCH_ABC_TYPE_READ_REPLACE:
if ((frame = switch_core_media_bug_get_read_replace_frame(bug))) { if ((frame = switch_core_media_bug_get_read_replace_frame(bug))) {
teletone_dtmf_detect(&pvt->dtmf_detect, frame->data, frame->samples); if ((hit = teletone_dtmf_detect(&pvt->dtmf_detect, frame->data, frame->samples)) == TT_HIT_END) {
teletone_dtmf_get(&pvt->dtmf_detect, digit_str, sizeof(digit_str)); switch_dtmf_t dtmf = {0};
if (digit_str[0]) {
char *p = digit_str; teletone_dtmf_get(&pvt->dtmf_detect, &dtmf.digit, &dtmf.duration);
while (p && *p) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_DEBUG, "DTMF DETECTED: [%c][%d]\n",
switch_dtmf_t dtmf = {0}; dtmf.digit, dtmf.duration);
dtmf.digit = *p; dtmf.source = SWITCH_DTMF_INBAND_AUDIO;
dtmf.duration = switch_core_default_dtmf_duration(0); switch_channel_queue_dtmf(channel, &dtmf);
dtmf.source = SWITCH_DTMF_INBAND_AUDIO;
switch_channel_queue_dtmf(channel, &dtmf);
p++;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_DEBUG, "DTMF DETECTED: [%s]\n",
digit_str);
} }
switch_core_media_bug_set_read_replace_frame(bug, frame); switch_core_media_bug_set_read_replace_frame(bug, frame);
} }