root/src/libteletone_detect.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. goertzel_init
  2. TELETONE_API
  3. TELETONE_API
  4. TELETONE_API
  5. TELETONE_API
  6. TELETONE_API
  7. TELETONE_API

   1 /* 
   2  * libteletone
   3  * Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
   4  *
   5  * Much less efficient expansion interface was added to allow for the detection of 
   6  * a single arbitrary tone combination which may also exceed 2 simultaneous tones.
   7  * (controlled by compile time constant TELETONE_MAX_TONES)
   8  *
   9  * Copyright (C) 2006 Anthony Minessale II <anthm@freeswitch.org>
  10  *
  11  * libteletone_detect.c Tone Detection Code
  12  *
  13  * Copyright (c) 2007, Anthony Minessale II
  14  * All rights reserved.
  15  * 
  16  * Redistribution and use in source and binary forms, with or without
  17  * modification, are permitted provided that the following conditions
  18  * are met:
  19  * 
  20  * * Redistributions of source code must retain the above copyright
  21  * notice, this list of conditions and the following disclaimer.
  22  * 
  23  * * Redistributions in binary form must reproduce the above copyright
  24  * notice, this list of conditions and the following disclaimer in the
  25  * documentation and/or other materials provided with the distribution.
  26  * 
  27  * * Neither the name of the original author; nor the names of any contributors
  28  * may be used to endorse or promote products derived from this software
  29  * without specific prior written permission.
  30  * 
  31  * 
  32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  35  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
  36  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  37  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  38  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  39  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  40  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  41  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  42  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  43  *
  44  ********************************************************************************* 
  45  *
  46  * Derived from tone_detect.c - General telephony tone detection, and specific
  47  * detection of DTMF.
  48  *
  49  * Copyright (C) 2001  Steve Underwood <steveu@coppice.org>
  50  *
  51  * Despite my general liking of the GPL, I place this code in the
  52  * public domain for the benefit of all mankind - even the slimy
  53  * ones who might try to proprietize my work and use it to my
  54  * detriment.
  55  *
  56  *
  57  *
  58  */
  59 
  60 #include <libteletone_detect.h>
  61 
  62 #ifndef _MSC_VER
  63 #include <stdint.h>
  64 #endif
  65 #include <string.h>
  66 #include <stdio.h>
  67 #include <time.h>
  68 #include <fcntl.h>
  69 
  70 
  71 static teletone_detection_descriptor_t dtmf_detect_row[GRID_FACTOR];
  72 static teletone_detection_descriptor_t dtmf_detect_col[GRID_FACTOR];
  73 static teletone_detection_descriptor_t dtmf_detect_row_2nd[GRID_FACTOR];
  74 static teletone_detection_descriptor_t dtmf_detect_col_2nd[GRID_FACTOR];
  75 
  76 static float dtmf_row[] = {697.0f,      770.0f,  852.0f,  941.0f};
  77 static float dtmf_col[] = {1209.0f, 1336.0f, 1477.0f, 1633.0f};
  78 
  79 static char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
  80 
  81 static void goertzel_init(teletone_goertzel_state_t *goertzel_state, teletone_detection_descriptor_t *tdesc) {
  82         goertzel_state->v2 = goertzel_state->v3 = 0.0;
  83         goertzel_state->fac = tdesc->fac;
  84 }
  85 
  86 TELETONE_API(void) teletone_goertzel_update(teletone_goertzel_state_t *goertzel_state,
  87                                                           int16_t sample_buffer[],
  88                                                           int samples)
  89 {
  90         int i;
  91         float v1;
  92         
  93         for (i = 0;      i < samples;  i++) {
  94                 v1 = goertzel_state->v2;
  95                 goertzel_state->v2 = goertzel_state->v3;
  96                 goertzel_state->v3 = (float)(goertzel_state->fac*goertzel_state->v2 - v1 + sample_buffer[i]);
  97         }
  98 }
  99 #ifdef _MSC_VER
 100 #pragma warning(disable:4244)
 101 #endif
 102 
 103 #define teletone_goertzel_result(gs) (double)(((gs)->v3 * (gs)->v3 + (gs)->v2 * (gs)->v2 - (gs)->v2 * (gs)->v3 * (gs)->fac))
 104 
 105 TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf_detect_state, int sample_rate)
 106 {
 107         int i;
 108         float theta;
 109 
 110         dtmf_detect_state->hit1 = dtmf_detect_state->hit2 = 0;
 111 
 112         for (i = 0;      i < GRID_FACTOR;  i++) {
 113                 theta = (float)(M_TWO_PI*(dtmf_row[i]/(float)sample_rate));
 114                 dtmf_detect_row[i].fac = (float)(2.0*cos(theta));
 115 
 116                 theta = (float)(M_TWO_PI*(dtmf_col[i]/(float)sample_rate));
 117                 dtmf_detect_col[i].fac = (float)(2.0*cos(theta));
 118         
 119                 theta = (float)(M_TWO_PI*(dtmf_row[i]*2.0/(float)sample_rate));
 120                 dtmf_detect_row_2nd[i].fac = (float)(2.0*cos(theta));
 121 
 122                 theta = (float)(M_TWO_PI*(dtmf_col[i]*2.0/(float)sample_rate));
 123                 dtmf_detect_col_2nd[i].fac = (float)(2.0*cos(theta));
 124         
 125                 goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
 126                 goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
 127                 goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
 128                 goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
 129         
 130                 dtmf_detect_state->energy = 0.0;
 131         }
 132         dtmf_detect_state->current_sample = 0;
 133         dtmf_detect_state->detected_digits = 0;
 134         dtmf_detect_state->lost_digits = 0;
 135         dtmf_detect_state->digits[0] = '\0';
 136         dtmf_detect_state->mhit = 0;
 137 }
 138 
 139 TELETONE_API(void) teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map)
 140 {
 141         float theta = 0;
 142         int x = 0;
 143 
 144         if (!mt->sample_rate) {
 145                 mt->sample_rate = 8000;
 146         }
 147 
 148         if (!mt->min_samples) {
 149                 mt->min_samples = 102;
 150         }
 151 
 152         mt->min_samples *= (mt->sample_rate / 8000);
 153 
 154         if (!mt->positive_factor) {
 155                 mt->positive_factor = 2;
 156         }
 157 
 158         if(!mt->negative_factor) {
 159                 mt->negative_factor = 10;
 160         }
 161 
 162         if (!mt->hit_factor) {
 163                 mt->hit_factor = 2;
 164         }
 165 
 166         for(x = 0; x < TELETONE_MAX_TONES; x++) {
 167                 if ((int) map->freqs[x] == 0) {
 168                         break;
 169                 }
 170                 mt->tone_count++;
 171                 theta = (float)(M_TWO_PI*(map->freqs[x]/(float)mt->sample_rate));
 172                 mt->tdd[x].fac = (float)(2.0 * cos(theta));
 173                 goertzel_init (&mt->gs[x], &mt->tdd[x]);
 174                 goertzel_init (&mt->gs2[x], &mt->tdd[x]);
 175         }
 176 
 177 }
 178 
 179 TELETONE_API(int) teletone_multi_tone_detect (teletone_multi_tone_t *mt,
 180                                                                 int16_t sample_buffer[],
 181                                                                 int samples)
 182 {
 183         int sample, limit = 0, j, x = 0;
 184         float v1, famp;
 185         float eng_sum = 0, eng_all[TELETONE_MAX_TONES] = {0.0};
 186         int gtest = 0, see_hit = 0;
 187 
 188         for (sample = 0;  sample >= 0 && sample < samples; sample = limit) {
 189                 mt->total_samples++;
 190 
 191                 if ((samples - sample) >= (mt->min_samples - mt->current_sample)) {
 192                         limit = sample + (mt->min_samples - mt->current_sample);
 193                 } else {
 194                         limit = samples;
 195                 }
 196                 if (limit < 0 || limit > samples) {
 197                         limit = samples;
 198                 }
 199 
 200                 for (j = sample;  j < limit;  j++) {
 201                         famp = sample_buffer[j];
 202                         
 203                         mt->energy += famp*famp;
 204 
 205                         for(x = 0; x < TELETONE_MAX_TONES && x < mt->tone_count; x++) {
 206                                 v1 = mt->gs[x].v2;
 207                                 mt->gs[x].v2 = mt->gs[x].v3;
 208                                 mt->gs[x].v3 = (float)(mt->gs[x].fac * mt->gs[x].v2 - v1 + famp);
 209         
 210                                 v1 = mt->gs2[x].v2;
 211                                 mt->gs2[x].v2 = mt->gs2[x].v3;
 212                                 mt->gs2[x].v3 = (float)(mt->gs2[x].fac*mt->gs2[x].v2 - v1 + famp);
 213                         }
 214                 }
 215 
 216                 mt->current_sample += (limit - sample);
 217                 if (mt->current_sample < mt->min_samples) {
 218                         continue;
 219                 }
 220 
 221                 eng_sum = 0;
 222                 for(x = 0; x < TELETONE_MAX_TONES && x < mt->tone_count; x++) {
 223                         eng_all[x] = (float)(teletone_goertzel_result (&mt->gs[x]));
 224                         eng_sum += eng_all[x];
 225                 }
 226 
 227                 gtest = 0;
 228                 for(x = 0; x < TELETONE_MAX_TONES && x < mt->tone_count; x++) {
 229                         gtest += teletone_goertzel_result (&mt->gs2[x]) < eng_all[x] ? 1 : 0;
 230                 }
 231 
 232                 if ((gtest >= 2 || gtest == mt->tone_count) && eng_sum > 42.0 * mt->energy) {
 233                         if(mt->negatives) {
 234                                 mt->negatives--;
 235                         }
 236                         mt->positives++;
 237 
 238                         if(mt->positives >= mt->positive_factor) {
 239                                 mt->hits++;
 240                         }
 241                         if (mt->hits >= mt->hit_factor) {
 242                                 see_hit++;
 243                                 mt->positives = mt->negatives = mt->hits = 0;
 244                         }
 245                 } else {
 246                         mt->negatives++;
 247                         if(mt->positives) {
 248                                 mt->positives--;
 249                         }
 250                         if(mt->negatives > mt->negative_factor) {
 251                                 mt->positives = mt->hits = 0;
 252                         }
 253                 }
 254 
 255                 /* Reinitialise the detector for the next block */
 256                 for(x = 0; x < TELETONE_MAX_TONES && x < mt->tone_count; x++) {
 257                         goertzel_init (&mt->gs[x], &mt->tdd[x]);
 258                         goertzel_init (&mt->gs2[x], &mt->tdd[x]);
 259                 }
 260 
 261                 mt->energy = 0.0;
 262                 mt->current_sample = 0;
 263         }
 264 
 265         return see_hit;
 266 }
 267 
 268 
 269 TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
 270                                                   int16_t sample_buffer[],
 271                                                   int samples)
 272 {
 273         float row_energy[GRID_FACTOR];
 274         float col_energy[GRID_FACTOR];
 275         float famp;
 276         float v1;
 277         int i;
 278         int j;
 279         int sample;
 280         int best_row;
 281         int best_col;
 282         char hit;
 283         int limit;
 284 
 285         hit = 0;
 286         for (sample = 0;  sample < samples;      sample = limit) {
 287                 /* BLOCK_LEN is optimised to meet the DTMF specs. */
 288                 if ((samples - sample) >= (BLOCK_LEN - dtmf_detect_state->current_sample)) {
 289                         limit = sample + (BLOCK_LEN - dtmf_detect_state->current_sample);
 290                 } else {
 291                         limit = samples;
 292                 }
 293 
 294                 for (j = sample;  j < limit;  j++) {
 295                         int x = 0;
 296                         famp = sample_buffer[j];
 297                         
 298                         dtmf_detect_state->energy += famp*famp;
 299 
 300                         for(x = 0; x < GRID_FACTOR; x++) {
 301                                 v1 = dtmf_detect_state->row_out[x].v2;
 302                                 dtmf_detect_state->row_out[x].v2 = dtmf_detect_state->row_out[x].v3;
 303                                 dtmf_detect_state->row_out[x].v3 = (float)(dtmf_detect_state->row_out[x].fac*dtmf_detect_state->row_out[x].v2 - v1 + famp);
 304         
 305                                 v1 = dtmf_detect_state->col_out[x].v2;
 306                                 dtmf_detect_state->col_out[x].v2 = dtmf_detect_state->col_out[x].v3;
 307                                 dtmf_detect_state->col_out[x].v3 = (float)(dtmf_detect_state->col_out[x].fac*dtmf_detect_state->col_out[x].v2 - v1 + famp);
 308 
 309                                 v1 = dtmf_detect_state->col_out2nd[x].v2;
 310                                 dtmf_detect_state->col_out2nd[x].v2 = dtmf_detect_state->col_out2nd[x].v3;
 311                                 dtmf_detect_state->col_out2nd[x].v3 = (float)(dtmf_detect_state->col_out2nd[x].fac*dtmf_detect_state->col_out2nd[x].v2 - v1 + famp);
 312                 
 313                                 v1 = dtmf_detect_state->row_out2nd[x].v2;
 314                                 dtmf_detect_state->row_out2nd[x].v2 = dtmf_detect_state->row_out2nd[x].v3;
 315                                 dtmf_detect_state->row_out2nd[x].v3 = (float)(dtmf_detect_state->row_out2nd[x].fac*dtmf_detect_state->row_out2nd[x].v2 - v1 + famp);
 316                         }
 317 
 318                 }
 319 
 320                 dtmf_detect_state->current_sample += (limit - sample);
 321                 if (dtmf_detect_state->current_sample < BLOCK_LEN) {
 322                         continue;
 323                 }
 324                 /* We are at the end of a DTMF detection block */
 325                 /* Find the peak row and the peak column */
 326                 row_energy[0] = teletone_goertzel_result (&dtmf_detect_state->row_out[0]);
 327                 col_energy[0] = teletone_goertzel_result (&dtmf_detect_state->col_out[0]);
 328 
 329                 for (best_row = best_col = 0, i = 1;  i < GRID_FACTOR;  i++) {
 330                         row_energy[i] = teletone_goertzel_result (&dtmf_detect_state->row_out[i]);
 331                         if (row_energy[i] > row_energy[best_row]) {
 332                                 best_row = i;
 333                         }
 334                         col_energy[i] = teletone_goertzel_result (&dtmf_detect_state->col_out[i]);
 335                         if (col_energy[i] > col_energy[best_col]) {
 336                                 best_col = i;
 337                         }
 338                 }
 339                 hit = 0;
 340                 /* Basic signal level test and the twist test */
 341                 if (row_energy[best_row] >= DTMF_THRESHOLD &&
 342                         col_energy[best_col] >= DTMF_THRESHOLD &&
 343                         col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST &&
 344                         col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) {
 345                         /* Relative peak test */
 346                         for (i = 0;      i < GRID_FACTOR;  i++) {
 347                                 if ((i != best_col      &&      col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
 348                                         (i != best_row  &&      row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
 349                                         break;
 350                                 }
 351                         }
 352                         /* ... and second harmonic test */
 353                         if (i >= GRID_FACTOR && (row_energy[best_row] + col_energy[best_col]) > 42.0*dtmf_detect_state->energy &&
 354                                 teletone_goertzel_result (&dtmf_detect_state->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col] &&
 355                                 teletone_goertzel_result (&dtmf_detect_state->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) {
 356                                 hit = dtmf_positions[(best_row << 2) + best_col];
 357                                 /* Look for two successive similar results */
 358                                 /* The logic in the next test is:
 359                                    We need two successive identical clean detects, with
 360                                    something different preceeding it. This can work with
 361                                    back to back differing digits. More importantly, it
 362                                    can work with nasty phones that give a very wobbly start
 363                                    to a digit. */
 364                                 if (hit == dtmf_detect_state->hit3      &&      dtmf_detect_state->hit3 != dtmf_detect_state->hit2) {
 365                                         dtmf_detect_state->mhit = hit;
 366                                         dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++;
 367                                         dtmf_detect_state->detected_digits++;
 368                                         if (dtmf_detect_state->current_digits < TELETONE_MAX_DTMF_DIGITS) {
 369                                                 dtmf_detect_state->digits[dtmf_detect_state->current_digits++] = hit;
 370                                                 dtmf_detect_state->digits[dtmf_detect_state->current_digits] = '\0';
 371                                         }
 372                                         else
 373                                                 {
 374                                                         dtmf_detect_state->lost_digits++;
 375                                                 }
 376                                 }
 377                         }
 378                 }
 379                 dtmf_detect_state->hit1 = dtmf_detect_state->hit2;
 380                 dtmf_detect_state->hit2 = dtmf_detect_state->hit3;
 381                 dtmf_detect_state->hit3 = hit;
 382                 /* Reinitialise the detector for the next block */
 383                 for (i = 0;      i < GRID_FACTOR;  i++) {
 384                         goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
 385                         goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
 386                         goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
 387                         goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
 388                 }
 389                 dtmf_detect_state->energy = 0.0;
 390                 dtmf_detect_state->current_sample = 0;
 391         }
 392         if ((!dtmf_detect_state->mhit) || (dtmf_detect_state->mhit != hit)) {
 393                 dtmf_detect_state->mhit = 0;
 394                 return(0);
 395         }
 396         return (hit);
 397 }
 398 
 399 
 400 TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state,
 401                                            char *buf,
 402                                            int max)
 403 {
 404         teletone_assert(dtmf_detect_state->current_digits <= TELETONE_MAX_DTMF_DIGITS);
 405 
 406         if (max > dtmf_detect_state->current_digits) {
 407                 max = dtmf_detect_state->current_digits;
 408         }
 409         if (max > 0) {
 410                 memcpy (buf, dtmf_detect_state->digits, max);
 411                 memmove (dtmf_detect_state->digits, dtmf_detect_state->digits + max, dtmf_detect_state->current_digits - max);
 412                 dtmf_detect_state->current_digits -= max;
 413         }
 414         buf[max] = '\0';
 415         return  max;
 416 }
 417 
 418 /* For Emacs:
 419  * Local Variables:
 420  * mode:c
 421  * indent-tabs-mode:t
 422  * tab-width:4
 423  * c-basic-offset:4
 424  * End:
 425  * For VIM:
 426  * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
 427  */

/* [<][>][^][v][top][bottom][index][help] */