/* * libteletone * Copyright (C) 2005-2014, Anthony Minessale II * * libteletone_detect.c Tone Detection Code * * 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 * following license and reinact the MPL 1.1 as stated above. * * Copyright (c) 2007, Anthony Minessale II * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of the original author; nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * 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 #define LIBTELETONE_DETECT_H #ifdef __cplusplus extern "C" { #endif #include /*! \file libteletone_detect.h \brief Tone Detection Routines This module is responsible for tone detection specifics */ #ifndef FALSE #define FALSE 0 #ifndef TRUE #define TRUE (!FALSE) #endif #endif /* Basic DTMF specs: * * Minimum tone on = 40ms * Minimum tone off = 50ms * Maximum digit rate = 10 per second * Normal twist <= 8dB accepted * Reverse twist <= 4dB accepted * S/N >= 15dB will detect OK * Attenuation <= 26dB will detect OK * Frequency tolerance +- 1.5% will detect, +-3.5% will reject */ #define DTMF_THRESHOLD 8.0e7 #define DTMF_NORMAL_TWIST 6.3 /* 8dB */ #define DTMF_REVERSE_TWIST 2.5 /* 4dB */ #define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */ #define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */ #define DTMF_2ND_HARMONIC_ROW 2.5 /* 4dB */ #define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */ #define GRID_FACTOR 4 #define BLOCK_LEN 102 #define M_TWO_PI 2.0*M_PI /*! \brief A continer for the elements of a Goertzel Algorithm (The names are from his formula) */ typedef struct { float v2; float v3; double fac; } teletone_goertzel_state_t; /*! \brief A container for a DTMF detection state.*/ typedef struct { int hit1; int hit2; int hit3; int hit4; int mhit; 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; int current_sample; char digits[TELETONE_MAX_DTMF_DIGITS + 1]; int current_digits; int detected_digits; int lost_digits; int digit_hits[16]; } teletone_dtmf_detect_state_t; /*! \brief An abstraction to store the coefficient of a tone frequency */ typedef struct { float fac; } teletone_detection_descriptor_t; /*! \brief A container for a single multi-tone detection TELETONE_MAX_TONES dictates the maximum simultaneous tones that can be present in a multi-tone representation. */ typedef struct { int sample_rate; teletone_detection_descriptor_t tdd[TELETONE_MAX_TONES]; teletone_goertzel_state_t gs[TELETONE_MAX_TONES]; teletone_goertzel_state_t gs2[TELETONE_MAX_TONES]; int tone_count; float energy; int current_sample; int min_samples; int total_samples; int positives; int negatives; int hits; int positive_factor; int negative_factor; int hit_factor; } teletone_multi_tone_t; /*! \brief Initilize a multi-frequency tone detector \param mt the multi-frequency tone descriptor \param map a representation of the multi-frequency tone */ TELETONE_API(void) teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map); /*! \brief Check a sample buffer for the presence of the mulit-frequency tone described by mt \param mt the multi-frequency tone descriptor \param sample_buffer an array aof 16 bit signed linear samples \param samples the number of samples present in sample_buffer \return true when the tone was detected or false when it is not */ TELETONE_API(int) teletone_multi_tone_detect (teletone_multi_tone_t *mt, int16_t sample_buffer[], int samples); /*! \brief Initilize a DTMF detection state object \param dtmf_detect_state the DTMF detection state to initilize \param sample_rate the desired sample rate */ TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf_detect_state, int sample_rate); /*! \brief Check a sample buffer for the presence of DTMF digits \param dtmf_detect_state the detection state object to check \param sample_buffer an array aof 16 bit signed linear samples \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, int16_t sample_buffer[], int samples); /*! \brief retrieve any collected digits into a string buffer \param dtmf_detect_state the detection state object to check \param buf the string buffer to write to \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); /*! \brief Step through the Goertzel Algorithm for each sample in a buffer \param goertzel_state the goertzel state to step the samples through \param sample_buffer an array aof 16 bit signed linear samples \param samples the number of samples present in sample_buffer */ TELETONE_API(void) teletone_goertzel_update(teletone_goertzel_state_t *goertzel_state, int16_t sample_buffer[], int samples); #ifdef __cplusplus } #endif #endif /* For Emacs: * Local Variables: * mode:c * indent-tabs-mode:t * tab-width:4 * c-basic-offset:4 * End: * For VIM: * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: */