diff --git a/libs/freetdm/src/detect_dtmf.c b/libs/freetdm/src/detect_dtmf.c index e7d9648192..62af298aef 100644 --- a/libs/freetdm/src/detect_dtmf.c +++ b/libs/freetdm/src/detect_dtmf.c @@ -6,7 +6,6 @@ int main(int argc, char *argv[]) int fd, b; short sln[512] = {0}; teletone_dtmf_detect_state_t dtmf_detect = {0}; - char digit_str[128] = ""; if (argc < 2) { fprintf(stderr, "Arg Error!\n"); @@ -21,10 +20,29 @@ int main(int argc, char *argv[]) } while((b = read(fd, sln, 320)) > 0) { + char digit_char; + unsigned int dur; + teletone_dtmf_detect(&dtmf_detect, sln, b / 2); - teletone_dtmf_get(&dtmf_detect, digit_str, sizeof(digit_str)); - if (*digit_str) { - printf("digit: %s\n", digit_str); + if ((hit = teletone_dtmf_get(&dtmf_detect, &digit_char, &dur))) { + char *hs = NULL; + + + 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); diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 0d0fdb655f..a472ca1694 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -3859,7 +3859,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, v uint8_t sln_buf[1024] = {0}; int16_t *sln; ftdm_size_t slen = 0; - char digit_str[80] = ""; if (ftdmchan->effective_codec == FTDM_CODEC_SLIN) { 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)) { - teletone_dtmf_detect(&ftdmchan->dtmf_detect, sln, (int)slen); - teletone_dtmf_get(&ftdmchan->dtmf_detect, digit_str, sizeof(digit_str)); + teletone_hit_type_t hit; + char digit_char; + uint32_t dur; - if(*digit_str) { - if (ftdmchan->state == FTDM_CHANNEL_STATE_CALLWAITING && (*digit_str == 'D' || *digit_str == 'A')) { + teletone_dtmf_detect(&ftdmchan->dtmf_detect, sln, (int)slen); + + 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]++; } else { + char digit_str[2] = { digit_char, 0}; + if (!ftdmchan->span->sig_dtmf || (ftdmchan->span->sig_dtmf(ftdmchan, (const char*)digit_str) != FTDM_BREAK)) { ftdm_channel_queue_dtmf(ftdmchan, digit_str); } diff --git a/libs/freetdm/src/include/private/libteletone.h b/libs/freetdm/src/include/private/libteletone.h index dc98c8cb6c..61078b4984 100644 --- a/libs/freetdm/src/include/private/libteletone.h +++ b/libs/freetdm/src/include/private/libteletone.h @@ -4,10 +4,10 @@ * * 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 * 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, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License @@ -33,8 +33,8 @@ * 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 freetdm library. Any use or distribution of this - * source code outside the scope of the freetdm library will nullify the + * 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 @@ -136,8 +136,8 @@ typedef __int16 int16_t; #endif #endif -#include "libteletone_generate.h" -#include "libteletone_detect.h" +#include +#include #ifdef HAVE_STRING_H #include diff --git a/libs/freetdm/src/include/private/libteletone_detect.h b/libs/freetdm/src/include/private/libteletone_detect.h index 71bf067514..4da368969c 100644 --- a/libs/freetdm/src/include/private/libteletone_detect.h +++ b/libs/freetdm/src/include/private/libteletone_detect.h @@ -2,13 +2,60 @@ * libteletone * Copyright (C) 2005-2011, Anthony Minessale II * + * 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 + * 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 + * + * * 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 + * + * 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 freetdm library. Any use or distribution of this - * source code outside the scope of the freetdm library will nullify the + * 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 @@ -41,20 +88,6 @@ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * 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 - * - * 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 @@ -63,7 +96,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "libteletone.h" +#include /*! \file libteletone_detect.h \brief Tone Detection Routines @@ -101,6 +134,14 @@ extern "C" { #define BLOCK_LEN 102 #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) */ typedef struct { float v2; @@ -114,16 +155,19 @@ extern "C" { int hit2; int hit3; int hit4; - int mhit; + int dur; + int zc; + teletone_goertzel_state_t row_out[GRID_FACTOR]; teletone_goertzel_state_t col_out[GRID_FACTOR]; teletone_goertzel_state_t row_out2nd[GRID_FACTOR]; teletone_goertzel_state_t col_out2nd[GRID_FACTOR]; float energy; + float lenergy; int current_sample; - char digits[TELETONE_MAX_DTMF_DIGITS + 1]; + char digit; int current_digits; int detected_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 \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[], 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 \return the number of characters written to buf */ -TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, - char *buf, - int max); +TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur); /*! \brief Step through the Goertzel Algorithm for each sample in a buffer diff --git a/libs/freetdm/src/include/private/libteletone_generate.h b/libs/freetdm/src/include/private/libteletone_generate.h index 6d71694761..0ff39e0dfa 100644 --- a/libs/freetdm/src/include/private/libteletone_generate.h +++ b/libs/freetdm/src/include/private/libteletone_generate.h @@ -2,6 +2,41 @@ * libteletone * Copyright (C) 2005-2011, Anthony Minessale II * + * 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 + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * + * + * 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 * All rights reserved. * @@ -81,7 +116,7 @@ extern float powf (float, float); #endif #include #include -#include "libteletone.h" +#include #define TELETONE_VOL_DB_MAX 0 #define TELETONE_VOL_DB_MIN -63 diff --git a/libs/freetdm/src/libteletone_detect.c b/libs/freetdm/src/libteletone_detect.c index 0436c25953..e995f98d0f 100644 --- a/libs/freetdm/src/libteletone_detect.c +++ b/libs/freetdm/src/libteletone_detect.c @@ -2,14 +2,62 @@ * libteletone * Copyright (C) 2005-2011, Anthony Minessale II * + * 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 + * 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 * + * * 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 + * + * 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 * All rights reserved. * @@ -40,21 +88,6 @@ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * 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 - * - * 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 @@ -67,7 +100,8 @@ #include #include - +#define LOW_ENG 10000000 +#define ZC 2 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_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->detected_digits = 0; dtmf_detect_state->lost_digits = 0; - dtmf_detect_state->digits[0] = '\0'; - dtmf_detect_state->mhit = 0; + dtmf_detect_state->digit = 0; + dtmf_detect_state->dur = 0; } 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[], int samples) { @@ -281,6 +315,7 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec int best_col; char hit; int limit; + teletone_hit_type_t r = 0; hit = 0; 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); if (dtmf_detect_state->current_sample < BLOCK_LEN) { 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 can work with nasty phones that give a very wobbly start to a digit. */ - if (hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) { - dtmf_detect_state->mhit = hit; + if (! r && hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) { dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++; dtmf_detect_state->detected_digits++; if (dtmf_detect_state->current_digits < TELETONE_MAX_DTMF_DIGITS) { - dtmf_detect_state->digits[dtmf_detect_state->current_digits++] = hit; - dtmf_detect_state->digits[dtmf_detect_state->current_digits] = '\0'; + dtmf_detect_state->digit = hit; + } else { + dtmf_detect_state->lost_digits++; } - else - { - dtmf_detect_state->lost_digits++; - } + + if (!dtmf_detect_state->zc) { + 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->hit2 = dtmf_detect_state->hit3; 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->current_sample = 0; + } - if ((!dtmf_detect_state->mhit) || (dtmf_detect_state->mhit != hit)) { - dtmf_detect_state->mhit = 0; - return(0); - } - return (hit); + + return r; } -TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, - char *buf, - int max) +TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur) { - 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) { - max = dtmf_detect_state->current_digits; + *buf = dtmf_detect_state->digit; + + *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); - 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; + + return 1; } /* For Emacs: diff --git a/libs/freetdm/src/libteletone_generate.c b/libs/freetdm/src/libteletone_generate.c index c0d6a54349..7448508944 100644 --- a/libs/freetdm/src/libteletone_generate.c +++ b/libs/freetdm/src/libteletone_generate.c @@ -1,5 +1,41 @@ /* - * libteletone_generate.c -- Tone Generator + * libteletone + * Copyright (C) 2005-2011, Anthony Minessale II + * + * 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 + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * + * + * 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 * All rights reserved. @@ -34,7 +70,6 @@ */ #include -#include "private/ftdm_core.h" #define SMAX 32767 #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_factor = 1; 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; } 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) { if (ts->buffer) { - ftdm_safe_free(ts->buffer); + free(ts->buffer); ts->buffer = NULL; ts->samples = 0; } @@ -270,6 +305,19 @@ TELETONE_API(int) teletone_mux_tones(teletone_generation_session_t *ts, teletone 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) { 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 { - if (!(data = ftdm_strdup(cmd))) { + if (!(data = my_strdup(cmd))) { return -1; } @@ -363,6 +411,9 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm *e++ = '\0'; } do { + if (!p) { + break; + } if ((next = strchr(p, ',')) != 0) { *next++ = '\0'; } @@ -427,7 +478,7 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm } } bottom: - ftdm_safe_free(data); + free(data); data = NULL; if (ts->LOOPS > 0) { ts->LOOPS--; diff --git a/libs/libteletone/src/libteletone.h b/libs/libteletone/src/libteletone.h index b54098c8ee..61078b4984 100644 --- a/libs/libteletone/src/libteletone.h +++ b/libs/libteletone/src/libteletone.h @@ -33,8 +33,8 @@ * 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 library. Any use or distribution of this - * source code outside the scope of the openzap library will nullify the + * 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 diff --git a/libs/libteletone/src/libteletone_detect.c b/libs/libteletone/src/libteletone_detect.c index ae959535b5..e995f98d0f 100644 --- a/libs/libteletone/src/libteletone_detect.c +++ b/libs/libteletone/src/libteletone_detect.c @@ -54,8 +54,8 @@ * 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 library. Any use or distribution of this - * source code outside the scope of the openzap library will nullify the + * 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 @@ -100,7 +100,8 @@ #include #include - +#define LOW_ENG 10000000 +#define ZC 2 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_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->detected_digits = 0; dtmf_detect_state->lost_digits = 0; - dtmf_detect_state->digits[0] = '\0'; - dtmf_detect_state->mhit = 0; + dtmf_detect_state->digit = 0; + dtmf_detect_state->dur = 0; } 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[], int samples) { @@ -314,6 +315,7 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec int best_col; char hit; int limit; + teletone_hit_type_t r = 0; hit = 0; 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); if (dtmf_detect_state->current_sample < BLOCK_LEN) { 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 can work with nasty phones that give a very wobbly start to a digit. */ - if (hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) { - dtmf_detect_state->mhit = hit; + if (! r && hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) { dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++; dtmf_detect_state->detected_digits++; if (dtmf_detect_state->current_digits < TELETONE_MAX_DTMF_DIGITS) { - dtmf_detect_state->digits[dtmf_detect_state->current_digits++] = hit; - dtmf_detect_state->digits[dtmf_detect_state->current_digits] = '\0'; + dtmf_detect_state->digit = hit; + } else { + dtmf_detect_state->lost_digits++; } - else - { - dtmf_detect_state->lost_digits++; - } + + if (!dtmf_detect_state->zc) { + 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->hit2 = dtmf_detect_state->hit3; 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->current_sample = 0; + } - if ((!dtmf_detect_state->mhit) || (dtmf_detect_state->mhit != hit)) { - dtmf_detect_state->mhit = 0; - return(0); - } - return (hit); + + return r; } -TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, - char *buf, - int max) +TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur) { - 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) { - max = dtmf_detect_state->current_digits; + *buf = dtmf_detect_state->digit; + + *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); - 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; + + return 1; } /* For Emacs: diff --git a/libs/libteletone/src/libteletone_detect.h b/libs/libteletone/src/libteletone_detect.h index e2a8c20b33..4da368969c 100644 --- a/libs/libteletone/src/libteletone_detect.h +++ b/libs/libteletone/src/libteletone_detect.h @@ -54,8 +54,8 @@ * 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 library. Any use or distribution of this - * source code outside the scope of the openzap library will nullify the + * 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 @@ -134,6 +134,14 @@ extern "C" { #define BLOCK_LEN 102 #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) */ typedef struct { float v2; @@ -147,16 +155,19 @@ extern "C" { int hit2; int hit3; int hit4; - int mhit; + int dur; + int zc; + teletone_goertzel_state_t row_out[GRID_FACTOR]; teletone_goertzel_state_t col_out[GRID_FACTOR]; teletone_goertzel_state_t row_out2nd[GRID_FACTOR]; teletone_goertzel_state_t col_out2nd[GRID_FACTOR]; float energy; + float lenergy; int current_sample; - char digits[TELETONE_MAX_DTMF_DIGITS + 1]; + char digit; int current_digits; int detected_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 \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[], 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 \return the number of characters written to buf */ -TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, - char *buf, - int max); +TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur); /*! \brief Step through the Goertzel Algorithm for each sample in a buffer diff --git a/libs/libteletone/src/libteletone_generate.c b/libs/libteletone/src/libteletone_generate.c index a5cefac98d..7448508944 100644 --- a/libs/libteletone/src/libteletone_generate.c +++ b/libs/libteletone/src/libteletone_generate.c @@ -33,8 +33,8 @@ * 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 library. Any use or distribution of this - * source code outside the scope of the openzap library will nullify the + * 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 diff --git a/libs/libteletone/src/libteletone_generate.h b/libs/libteletone/src/libteletone_generate.h index 5e6444b0c4..0ff39e0dfa 100644 --- a/libs/libteletone/src/libteletone_generate.h +++ b/libs/libteletone/src/libteletone_generate.h @@ -33,8 +33,8 @@ * 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 library. Any use or distribution of this - * source code outside the scope of the openzap library will nullify the + * 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 diff --git a/src/mod/applications/mod_valet_parking/mod_valet_parking.c b/src/mod/applications/mod_valet_parking/mod_valet_parking.c index 0b25a47e94..3ac27b1533 100644 --- a/src/mod/applications/mod_valet_parking/mod_valet_parking.c +++ b/src/mod/applications/mod_valet_parking/mod_valet_parking.c @@ -92,40 +92,49 @@ static void check_timeouts(void) void *val; time_t now; 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); switch_mutex_lock(globals.mutex); - - 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); - lot = (valet_lot_t *) 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_push_match(&matches, (const char *) var); } 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) diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index 6fe6048173..99449082bb 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -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_frame_t *frame = NULL; - char digit_str[80]; switch_channel_t *channel = switch_core_session_get_channel(pvt->session); + teletone_hit_type_t hit; switch (type) { 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; case SWITCH_ABC_TYPE_READ_REPLACE: if ((frame = switch_core_media_bug_get_read_replace_frame(bug))) { - teletone_dtmf_detect(&pvt->dtmf_detect, frame->data, frame->samples); - teletone_dtmf_get(&pvt->dtmf_detect, digit_str, sizeof(digit_str)); - if (digit_str[0]) { - char *p = digit_str; - while (p && *p) { - switch_dtmf_t dtmf = {0}; - dtmf.digit = *p; - dtmf.duration = switch_core_default_dtmf_duration(0); - 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); + if ((hit = teletone_dtmf_detect(&pvt->dtmf_detect, frame->data, frame->samples)) == TT_HIT_END) { + switch_dtmf_t dtmf = {0}; + + teletone_dtmf_get(&pvt->dtmf_detect, &dtmf.digit, &dtmf.duration); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_DEBUG, "DTMF DETECTED: [%c][%d]\n", + dtmf.digit, dtmf.duration); + dtmf.source = SWITCH_DTMF_INBAND_AUDIO; + switch_channel_queue_dtmf(channel, &dtmf); } switch_core_media_bug_set_read_replace_frame(bug, frame); }