1 /* 2 * libteletone 3 * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org> 4 * 5 * Version: MPL 1.1 6 * 7 * The contents of this file are subject to the Mozilla Public License Version 8 * 1.1 (the "License"); you may not use this file except in compliance with 9 * the License. You may obtain a copy of the License at 10 * http://www.mozilla.org/MPL/ 11 * 12 * Software distributed under the License is distributed on an "AS IS" basis, 13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 14 * for the specific language governing rights and limitations under the 15 * License. 16 * 17 * The Original Code is tone_detect.c - General telephony tone detection, and specific detection of DTMF. 18 * 19 * 20 * The Initial Developer of the Original Code is 21 * Stephen Underwood <steveu@coppice.org> 22 * Portions created by the Initial Developer are Copyright (C) 23 * the Initial Developer. All Rights Reserved. 24 * 25 * Contributor(s): 26 * 27 * The the original interface designed by Steve Underwood was preserved to retain 28 *the optimizations when considering DTMF tones though the names were changed in the interest 29 * of namespace. 30 * 31 * Much less efficient expansion interface was added to allow for the detection of 32 * a single arbitrary tone combination which may also exceed 2 simultaneous tones. 33 * (controlled by compile time constant TELETONE_MAX_TONES) 34 * 35 * Copyright (C) 2006 Anthony Minessale II <anthm@freeswitch.org> 36 * 37 * 38 * libteletone_detect.c Tone Detection Code 39 * 40 * 41 ********************************************************************************* 42 * 43 * Derived from tone_detect.h - General telephony tone detection, and specific 44 * detection of DTMF. 45 * 46 * Copyright (C) 2001 Steve Underwood <steveu@coppice.org> 47 * 48 * Despite my general liking of the GPL, I place this code in the 49 * public domain for the benefit of all mankind - even the slimy 50 * ones who might try to proprietize my work and use it to my 51 * detriment. 52 * 53 * 54 * Exception: 55 * The author hereby grants the use of this source code under the 56 * following license if and only if the source code is distributed 57 * as part of the OpenZAP or FreeTDM library. Any use or distribution of this 58 * source code outside the scope of the OpenZAP or FreeTDM library will nullify the 59 * following license and reinact the MPL 1.1 as stated above. 60 * 61 * Copyright (c) 2007, Anthony Minessale II 62 * All rights reserved. 63 * 64 * Redistribution and use in source and binary forms, with or without 65 * modification, are permitted provided that the following conditions 66 * are met: 67 * 68 * * Redistributions of source code must retain the above copyright 69 * notice, this list of conditions and the following disclaimer. 70 * 71 * * Redistributions in binary form must reproduce the above copyright 72 * notice, this list of conditions and the following disclaimer in the 73 * documentation and/or other materials provided with the distribution. 74 * 75 * * Neither the name of the original author; nor the names of any contributors 76 * may be used to endorse or promote products derived from this software 77 * without specific prior written permission. 78 * 79 * 80 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 81 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 82 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 83 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 84 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 85 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 86 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 87 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 88 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 89 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 90 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 91 */ 92 93 #ifndef LIBTELETONE_DETECT_H 94 #define LIBTELETONE_DETECT_H 95 96 #ifdef __cplusplus 97 extern "C" { 98 #endif 99 #include <libteletone.h> 100 101 /*! \file libteletone_detect.h 102 \brief Tone Detection Routines 103 104 This module is responsible for tone detection specifics 105 */ 106 107 #ifndef FALSE 108 #define FALSE 0 109 #ifndef TRUE 110 #define TRUE (!FALSE) 111 #endif 112 #endif 113 114 /* Basic DTMF specs: 115 * 116 * Minimum tone on = 40ms 117 * Minimum tone off = 50ms 118 * Maximum digit rate = 10 per second 119 * Normal twist <= 8dB accepted 120 * Reverse twist <= 4dB accepted 121 * S/N >= 15dB will detect OK 122 * Attenuation <= 26dB will detect OK 123 * Frequency tolerance +- 1.5% will detect, +-3.5% will reject 124 */ 125 126 #define DTMF_THRESHOLD 8.0e7 127 #define DTMF_NORMAL_TWIST 6.3 /* 8dB */ 128 #define DTMF_REVERSE_TWIST 2.5 /* 4dB */ 129 #define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */ 130 #define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */ 131 #define DTMF_2ND_HARMONIC_ROW 2.5 /* 4dB */ 132 #define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */ 133 #define GRID_FACTOR 4 134 #define BLOCK_LEN 102 135 #define M_TWO_PI 2.0*M_PI 136 137 typedef enum { 138 TT_HIT_NONE = 0, 139 TT_HIT_BEGIN = 1, 140 TT_HIT_MIDDLE = 2, 141 TT_HIT_END = 3 142 } teletone_hit_type_t; 143 144 145 /*! \brief A continer for the elements of a Goertzel Algorithm (The names are from his formula) */ 146 typedef struct { 147 float v2; 148 float v3; 149 double fac; 150 } teletone_goertzel_state_t; 151 152 /*! \brief A container for a DTMF detection state.*/ 153 typedef struct { 154 int hit1; 155 int hit2; 156 int hit3; 157 int hit4; 158 int dur; 159 int zc; 160 161 162 teletone_goertzel_state_t row_out[GRID_FACTOR]; 163 teletone_goertzel_state_t col_out[GRID_FACTOR]; 164 teletone_goertzel_state_t row_out2nd[GRID_FACTOR]; 165 teletone_goertzel_state_t col_out2nd[GRID_FACTOR]; 166 float energy; 167 float lenergy; 168 169 int current_sample; 170 char digit; 171 int current_digits; 172 int detected_digits; 173 int lost_digits; 174 int digit_hits[16]; 175 } teletone_dtmf_detect_state_t; 176 177 /*! \brief An abstraction to store the coefficient of a tone frequency */ 178 typedef struct { 179 float fac; 180 } teletone_detection_descriptor_t; 181 182 /*! \brief A container for a single multi-tone detection 183 TELETONE_MAX_TONES dictates the maximum simultaneous tones that can be present 184 in a multi-tone representation. 185 */ 186 typedef struct { 187 int sample_rate; 188 189 teletone_detection_descriptor_t tdd[TELETONE_MAX_TONES]; 190 teletone_goertzel_state_t gs[TELETONE_MAX_TONES]; 191 teletone_goertzel_state_t gs2[TELETONE_MAX_TONES]; 192 int tone_count; 193 194 float energy; 195 int current_sample; 196 197 int min_samples; 198 int total_samples; 199 200 int positives; 201 int negatives; 202 int hits; 203 204 int positive_factor; 205 int negative_factor; 206 int hit_factor; 207 208 } teletone_multi_tone_t; 209 210 211 /*! 212 \brief Initilize a multi-frequency tone detector 213 \param mt the multi-frequency tone descriptor 214 \param map a representation of the multi-frequency tone 215 */ 216 TELETONE_API(void) teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map); 217 218 /*! 219 \brief Check a sample buffer for the presence of the mulit-frequency tone described by mt 220 \param mt the multi-frequency tone descriptor 221 \param sample_buffer an array aof 16 bit signed linear samples 222 \param samples the number of samples present in sample_buffer 223 \return true when the tone was detected or false when it is not 224 */ 225 TELETONE_API(int) teletone_multi_tone_detect (teletone_multi_tone_t *mt, 226 int16_t sample_buffer[], 227 int samples); 228 229 /*! 230 \brief Initilize a DTMF detection state object 231 \param dtmf_detect_state the DTMF detection state to initilize 232 \param sample_rate the desired sample rate 233 */ 234 TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf_detect_state, int sample_rate); 235 236 /*! 237 \brief Check a sample buffer for the presence of DTMF digits 238 \param dtmf_detect_state the detection state object to check 239 \param sample_buffer an array aof 16 bit signed linear samples 240 \param samples the number of samples present in sample_buffer 241 \return true when DTMF was detected or false when it is not 242 */ 243 TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state, 244 int16_t sample_buffer[], 245 int samples); 246 /*! 247 \brief retrieve any collected digits into a string buffer 248 \param dtmf_detect_state the detection state object to check 249 \param buf the string buffer to write to 250 \param max the maximum length of buf 251 \return the number of characters written to buf 252 */ 253 TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur); 254 255 /*! 256 \brief Step through the Goertzel Algorithm for each sample in a buffer 257 \param goertzel_state the goertzel state to step the samples through 258 \param sample_buffer an array aof 16 bit signed linear samples 259 \param samples the number of samples present in sample_buffer 260 */ 261 TELETONE_API(void) teletone_goertzel_update(teletone_goertzel_state_t *goertzel_state, 262 int16_t sample_buffer[], 263 int samples); 264 265 266 267 #ifdef __cplusplus 268 } 269 #endif 270 271 #endif 272 273 /* For Emacs: 274 * Local Variables: 275 * mode:c 276 * indent-tabs-mode:t 277 * tab-width:4 278 * c-basic-offset:4 279 * End: 280 * For VIM: 281 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 282 */ 283