2 * Asterisk -- A telephony toolkit for Linux.
4 * Convenience Signal Processing routines
6 * Copyright (C) 2002, Digium
8 * Mark Spencer <markster@linux-support.net>
10 * This program is free software, distributed under the terms of
11 * the GNU General Public License.
13 * Goertzel routines are borrowed from Steve Underwood's tremendous work on the
18 /* Some routines from tone_detect.c by Steven Underwood as published under the zapata library */
20 tone_detect.c - General telephony tone detection, and specific
23 Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
25 Despite my general liking of the GPL, I place this code in the
26 public domain for the benefit of all mankind - even the slimy
27 ones who might try to proprietize my work and use it to my
31 #include <sys/types.h>
32 #include <asterisk/frame.h>
33 #include <asterisk/channel.h>
34 #include <asterisk/channel_pvt.h>
35 #include <asterisk/logger.h>
36 #include <asterisk/dsp.h>
37 #include <asterisk/ulaw.h>
38 #include <asterisk/alaw.h>
46 #define DEFAULT_THRESHOLD 1024
48 #define BUSY_PERCENT 10 /* The percentage diffrence between the two last silence periods */
49 #define BUSY_THRESHOLD 100 /* Max number of ms difference between max and min times in busy */
50 #define BUSY_MIN 75 /* Busy must be at least 80 ms in half-cadence */
51 #define BUSY_MAX 1100 /* Busy can't be longer than 1100 ms in half-cadence */
53 /* Remember last 15 units */
54 #define DSP_HISTORY 15
56 /* Number of goertzels for progress detect */
57 #define GSAMP_SIZE 183
67 #define TONE_THRESH 10.0 /* How much louder the tone should be than channel energy */
68 #define TONE_MIN_THRESH 1e8 /* How much tone there should be at least to attempt */
69 #define COUNT_THRESH 3 /* Need at least 50ms of stuff to count it */
71 #define TONE_STATE_SILENCE 0
72 #define TONE_STATE_RINGING 1
73 #define TONE_STATE_DIALTONE 2
74 #define TONE_STATE_TALKING 3
75 #define TONE_STATE_BUSY 4
76 #define TONE_STATE_SPECIAL1 5
77 #define TONE_STATE_SPECIAL2 6
78 #define TONE_STATE_SPECIAL3 7
80 #define MAX_DTMF_DIGITS 128
84 * Minimum tone on = 40ms
85 * Minimum tone off = 50ms
86 * Maximum digit rate = 10 per second
87 * Normal twist <= 8dB accepted
88 * Reverse twist <= 4dB accepted
89 * S/N >= 15dB will detect OK
90 * Attenuation <= 26dB will detect OK
91 * Frequency tolerance +- 1.5% will detect, +-3.5% will reject
94 #define DTMF_THRESHOLD 8.0e7
95 #define FAX_THRESHOLD 8.0e7
96 #define FAX_2ND_HARMONIC 2.0 /* 4dB */
97 #define DTMF_NORMAL_TWIST 6.3 /* 8dB */
98 #define DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 4.0 : 2.5) /* 4dB normal */
99 #define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */
100 #define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */
101 #define DTMF_2ND_HARMONIC_ROW ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 1.7 : 2.5) /* 4dB normal */
102 #define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */
103 #ifndef OLD_DSP_ROUTINES
104 #define DTMF_TO_TOTAL_ENERGY 42.0
107 #ifdef OLD_DSP_ROUTINES
108 #define MF_THRESHOLD 8.0e7
109 #define MF_NORMAL_TWIST 5.3 /* 8dB */
110 #define MF_REVERSE_TWIST 4.0 /* was 2.5 */
111 #define MF_RELATIVE_PEAK 5.3 /* 8dB */
112 #define MF_2ND_HARMONIC 1.7 /* was 2.5 */
114 #define BELL_MF_THRESHOLD 1.6e9
115 #define BELL_MF_TWIST 4.0 /* 6dB */
116 #define BELL_MF_RELATIVE_PEAK 12.6 /* 11dB */
123 #ifndef OLD_DSP_ROUTINES
131 goertzel_state_t row_out[4];
132 goertzel_state_t col_out[4];
133 goertzel_state_t fax_tone;
134 #ifdef OLD_DSP_ROUTINES
135 goertzel_state_t row_out2nd[4];
136 goertzel_state_t col_out2nd[4];
137 goertzel_state_t fax_tone2nd;
149 char digits[MAX_DTMF_DIGITS + 1];
157 } dtmf_detect_state_t;
161 goertzel_state_t tone_out[6];
163 #ifdef OLD_DSP_ROUTINES
168 goertzel_state_t tone_out2nd[6];
175 char digits[MAX_DTMF_DIGITS + 1];
182 static float dtmf_row[] =
184 697.0, 770.0, 852.0, 941.0
186 static float dtmf_col[] =
188 1209.0, 1336.0, 1477.0, 1633.0
191 static float mf_tones[] =
193 700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0
196 static float fax_freq = 1100.0;
198 static char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
200 #ifdef OLD_DSP_ROUTINES
201 static char mf_hit[6][6] = {
202 /* 700 + */ { 0, '1', '2', '4', '7', 'C' },
203 /* 900 + */ { '1', 0, '3', '5', '8', 'A' },
204 /* 1100 + */ { '2', '3', 0, '6', '9', '*' },
205 /* 1300 + */ { '4', '5', '6', 0, '0', 'B' },
206 /* 1500 + */ { '7', '8', '9', '0', 0, '#' },
207 /* 1700 + */ { 'C', 'A', '*', 'B', '#', 0 },
210 static char bell_mf_positions[] = "1247C-358A--69*---0B----#";
213 static inline void goertzel_sample(goertzel_state_t *s, short sample)
216 float fsamp = sample;
219 s->v3 = s->fac * s->v2 - v1 + fsamp;
222 static inline void goertzel_update(goertzel_state_t *s, short *samps, int count)
225 for (i=0;i<count;i++)
226 goertzel_sample(s, samps[i]);
230 static inline float goertzel_result(goertzel_state_t *s)
232 return s->v3 * s->v3 + s->v2 * s->v2 - s->v2 * s->v3 * s->fac;
235 static inline void goertzel_init(goertzel_state_t *s, float freq, int samples)
238 s->fac = 2.0 * cos(2.0 * M_PI * (freq / 8000.0));
239 #ifndef OLD_DSP_ROUTINES
240 s->samples = samples;
244 static inline void goertzel_reset(goertzel_state_t *s)
257 int historicnoise[DSP_HISTORY];
258 int historicsilence[DSP_HISTORY];
259 goertzel_state_t freqs[7];
267 dtmf_detect_state_t dtmf;
268 mf_detect_state_t mf;
272 static void ast_dtmf_detect_init (dtmf_detect_state_t *s)
276 #ifdef OLD_DSP_ROUTINES
283 s->hits[0] = s->hits[1] = s->hits[2] = 0;
285 for (i = 0; i < 4; i++)
288 goertzel_init (&s->row_out[i], dtmf_row[i], 102);
289 goertzel_init (&s->col_out[i], dtmf_col[i], 102);
290 #ifdef OLD_DSP_ROUTINES
291 goertzel_init (&s->row_out2nd[i], dtmf_row[i] * 2.0, 102);
292 goertzel_init (&s->col_out2nd[i], dtmf_col[i] * 2.0, 102);
297 /* Same for the fax dector */
298 goertzel_init (&s->fax_tone, fax_freq, 102);
300 #ifdef OLD_DSP_ROUTINES
301 /* Same for the fax dector 2nd harmonic */
302 goertzel_init (&s->fax_tone2nd, fax_freq * 2.0, 102);
305 s->current_sample = 0;
306 s->detected_digits = 0;
307 s->current_digits = 0;
308 memset(&s->digits, 0, sizeof(s->digits));
313 static void ast_mf_detect_init (mf_detect_state_t *s)
317 #ifdef OLD_DSP_ROUTINES
321 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
323 for (i = 0; i < 6; i++)
326 goertzel_init (&s->tone_out[i], mf_tones[i], 160);
327 #ifdef OLD_DSP_ROUTINES
328 goertzel_init (&s->tone_out2nd[i], mf_tones[i] * 2.0, 160);
334 s->current_digits = 0;
335 memset(&s->digits, 0, sizeof(s->digits));
336 s->current_sample = 0;
337 s->detected_digits = 0;
343 static int dtmf_detect (dtmf_detect_state_t *s,
346 int digitmode, int *writeback)
352 #ifdef OLD_DSP_ROUTINES
353 float fax_energy_2nd;
366 for (sample = 0; sample < samples; sample = limit)
368 /* 102 is optimised to meet the DTMF specs. */
369 if ((samples - sample) >= (102 - s->current_sample))
370 limit = sample + (102 - s->current_sample);
373 #if defined(USE_3DNOW)
374 _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample);
375 _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample);
376 #ifdef OLD_DSP_ROUTINES
377 _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample);
378 _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample);
380 /* XXX Need to fax detect for 3dnow too XXX */
381 #warning "Fax Support Broken"
383 /* The following unrolled loop takes only 35% (rough estimate) of the
384 time of a rolled loop on the machine on which it was developed */
385 for (j = sample; j < limit; j++)
389 s->energy += famp*famp;
391 /* With GCC 2.95, the following unrolled code seems to take about 35%
392 (rough estimate) as long as a neat little 0-3 loop */
393 v1 = s->row_out[0].v2;
394 s->row_out[0].v2 = s->row_out[0].v3;
395 s->row_out[0].v3 = s->row_out[0].fac*s->row_out[0].v2 - v1 + famp;
397 v1 = s->col_out[0].v2;
398 s->col_out[0].v2 = s->col_out[0].v3;
399 s->col_out[0].v3 = s->col_out[0].fac*s->col_out[0].v2 - v1 + famp;
401 v1 = s->row_out[1].v2;
402 s->row_out[1].v2 = s->row_out[1].v3;
403 s->row_out[1].v3 = s->row_out[1].fac*s->row_out[1].v2 - v1 + famp;
405 v1 = s->col_out[1].v2;
406 s->col_out[1].v2 = s->col_out[1].v3;
407 s->col_out[1].v3 = s->col_out[1].fac*s->col_out[1].v2 - v1 + famp;
409 v1 = s->row_out[2].v2;
410 s->row_out[2].v2 = s->row_out[2].v3;
411 s->row_out[2].v3 = s->row_out[2].fac*s->row_out[2].v2 - v1 + famp;
413 v1 = s->col_out[2].v2;
414 s->col_out[2].v2 = s->col_out[2].v3;
415 s->col_out[2].v3 = s->col_out[2].fac*s->col_out[2].v2 - v1 + famp;
417 v1 = s->row_out[3].v2;
418 s->row_out[3].v2 = s->row_out[3].v3;
419 s->row_out[3].v3 = s->row_out[3].fac*s->row_out[3].v2 - v1 + famp;
421 v1 = s->col_out[3].v2;
422 s->col_out[3].v2 = s->col_out[3].v3;
423 s->col_out[3].v3 = s->col_out[3].fac*s->col_out[3].v2 - v1 + famp;
425 /* Update fax tone */
427 s->fax_tone.v2 = s->fax_tone.v3;
428 s->fax_tone.v3 = s->fax_tone.fac*s->fax_tone.v2 - v1 + famp;
430 #ifdef OLD_DSP_ROUTINES
431 v1 = s->col_out2nd[0].v2;
432 s->col_out2nd[0].v2 = s->col_out2nd[0].v3;
433 s->col_out2nd[0].v3 = s->col_out2nd[0].fac*s->col_out2nd[0].v2 - v1 + famp;
435 v1 = s->row_out2nd[0].v2;
436 s->row_out2nd[0].v2 = s->row_out2nd[0].v3;
437 s->row_out2nd[0].v3 = s->row_out2nd[0].fac*s->row_out2nd[0].v2 - v1 + famp;
439 v1 = s->col_out2nd[1].v2;
440 s->col_out2nd[1].v2 = s->col_out2nd[1].v3;
441 s->col_out2nd[1].v3 = s->col_out2nd[1].fac*s->col_out2nd[1].v2 - v1 + famp;
443 v1 = s->row_out2nd[1].v2;
444 s->row_out2nd[1].v2 = s->row_out2nd[1].v3;
445 s->row_out2nd[1].v3 = s->row_out2nd[1].fac*s->row_out2nd[1].v2 - v1 + famp;
447 v1 = s->col_out2nd[2].v2;
448 s->col_out2nd[2].v2 = s->col_out2nd[2].v3;
449 s->col_out2nd[2].v3 = s->col_out2nd[2].fac*s->col_out2nd[2].v2 - v1 + famp;
451 v1 = s->row_out2nd[2].v2;
452 s->row_out2nd[2].v2 = s->row_out2nd[2].v3;
453 s->row_out2nd[2].v3 = s->row_out2nd[2].fac*s->row_out2nd[2].v2 - v1 + famp;
455 v1 = s->col_out2nd[3].v2;
456 s->col_out2nd[3].v2 = s->col_out2nd[3].v3;
457 s->col_out2nd[3].v3 = s->col_out2nd[3].fac*s->col_out2nd[3].v2 - v1 + famp;
459 v1 = s->row_out2nd[3].v2;
460 s->row_out2nd[3].v2 = s->row_out2nd[3].v3;
461 s->row_out2nd[3].v3 = s->row_out2nd[3].fac*s->row_out2nd[3].v2 - v1 + famp;
464 s->fax_tone2nd.v2 = s->fax_tone2nd.v3;
465 s->fax_tone2nd.v3 = s->fax_tone2nd.fac*s->fax_tone2nd.v2 - v1 + famp;
469 s->current_sample += (limit - sample);
470 if (s->current_sample < 102) {
471 if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) {
472 /* If we had a hit last time, go ahead and clear this out since likely it
473 will be another hit */
474 for (i=sample;i<limit;i++)
481 /* Detect the fax energy, too */
482 fax_energy = goertzel_result(&s->fax_tone);
484 /* We are at the end of a DTMF detection block */
485 /* Find the peak row and the peak column */
486 row_energy[0] = goertzel_result (&s->row_out[0]);
487 col_energy[0] = goertzel_result (&s->col_out[0]);
489 for (best_row = best_col = 0, i = 1; i < 4; i++)
491 row_energy[i] = goertzel_result (&s->row_out[i]);
492 if (row_energy[i] > row_energy[best_row])
494 col_energy[i] = goertzel_result (&s->col_out[i]);
495 if (col_energy[i] > col_energy[best_col])
499 /* Basic signal level test and the twist test */
500 if (row_energy[best_row] >= DTMF_THRESHOLD
502 col_energy[best_col] >= DTMF_THRESHOLD
504 col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST
506 col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row])
508 /* Relative peak test */
509 for (i = 0; i < 4; i++)
511 if ((i != best_col && col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col])
513 (i != best_row && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row]))
518 #ifdef OLD_DSP_ROUTINES
519 /* ... and second harmonic test */
522 (row_energy[best_row] + col_energy[best_col]) > 42.0*s->energy
524 goertzel_result (&s->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col]
526 goertzel_result (&s->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row])
528 /* ... and fraction of total energy test */
531 (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->energy)
535 hit = dtmf_positions[(best_row << 2) + best_col];
536 if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) {
537 /* Zero out frame data if this is part DTMF */
538 for (i=sample;i<limit;i++)
542 /* Look for two successive similar results */
543 /* The logic in the next test is:
544 We need two successive identical clean detects, with
545 something different preceeding it. This can work with
546 back to back differing digits. More importantly, it
547 can work with nasty phones that give a very wobbly start
550 #ifdef OLD_DSP_ROUTINES
551 if (hit == s->hit3 && s->hit3 != s->hit2)
554 s->digit_hits[(best_row << 2) + best_col]++;
555 s->detected_digits++;
556 if (s->current_digits < MAX_DTMF_DIGITS)
558 s->digits[s->current_digits++] = hit;
559 s->digits[s->current_digits] = '\0';
567 if (hit == s->hits[2] && hit != s->hits[1] && hit != s->hits[0])
570 s->digit_hits[(best_row << 2) + best_col]++;
571 s->detected_digits++;
572 if (s->current_digits < MAX_DTMF_DIGITS)
574 s->digits[s->current_digits++] = hit;
575 s->digits[s->current_digits] = '\0';
585 #ifdef OLD_DSP_ROUTINES
586 if (!hit && (fax_energy >= FAX_THRESHOLD) && (fax_energy > s->energy * 21.0)) {
587 fax_energy_2nd = goertzel_result(&s->fax_tone2nd);
588 fax_energy_2nd = goertzel_result(&s->fax_tone2nd);
589 if (fax_energy_2nd * FAX_2ND_HARMONIC < fax_energy) {
591 printf("Fax energy/Second Harmonic: %f/%f\n", fax_energy, fax_energy_2nd);
593 /* XXX Probably need better checking than just this the energy XXX */
596 } /* Don't reset fax hits counter */
598 #else /* OLD_DSP_ROUTINES */
599 if (!hit && (fax_energy >= DTMF_TO_TOTAL_ENERGY*s->energy)) {
601 printf("Fax energy/Second Harmonic: %f\n", fax_energy);
603 /* XXX Probably need better checking than just this the energy XXX */
607 #endif /* OLD_DSP_ROUTINES */
609 if (s->fax_hits > 5) {
612 s->detected_digits++;
613 if (s->current_digits < MAX_DTMF_DIGITS)
615 s->digits[s->current_digits++] = hit;
616 s->digits[s->current_digits] = '\0';
625 #ifdef OLD_DSP_ROUTINES
630 s->hits[0] = s->hits[1];
631 s->hits[1] = s->hits[2];
634 /* Reinitialise the detector for the next block */
635 for (i = 0; i < 4; i++)
637 goertzel_reset(&s->row_out[i]);
638 goertzel_reset(&s->col_out[i]);
639 #ifdef OLD_DSP_ROUTINES
640 goertzel_reset(&s->row_out2nd[i]);
641 goertzel_reset(&s->col_out2nd[i]);
644 goertzel_reset (&s->fax_tone);
645 #ifdef OLD_DSP_ROUTINES
646 goertzel_reset (&s->fax_tone2nd);
649 s->current_sample = 0;
651 if ((!s->mhit) || (s->mhit != hit))
659 /* MF goertzel size */
660 #ifdef OLD_DSP_ROUTINES
666 static int mf_detect (mf_detect_state_t *s,
669 int digitmode, int *writeback)
672 #ifdef OLD_DSP_ROUTINES
673 float tone_energy[6];
692 for (sample = 0; sample < samples; sample = limit)
694 /* 80 is optimised to meet the MF specs. */
695 if ((samples - sample) >= (MF_GSIZE - s->current_sample))
696 limit = sample + (MF_GSIZE - s->current_sample);
699 #if defined(USE_3DNOW)
700 _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample);
701 _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample);
702 #ifdef OLD_DSP_ROUTINES
703 _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample);
704 _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample);
706 /* XXX Need to fax detect for 3dnow too XXX */
707 #warning "Fax Support Broken"
709 /* The following unrolled loop takes only 35% (rough estimate) of the
710 time of a rolled loop on the machine on which it was developed */
711 for (j = sample; j < limit; j++)
715 #ifdef OLD_DSP_ROUTINES
716 s->energy += famp*famp;
719 /* With GCC 2.95, the following unrolled code seems to take about 35%
720 (rough estimate) as long as a neat little 0-3 loop */
721 v1 = s->tone_out[0].v2;
722 s->tone_out[0].v2 = s->tone_out[0].v3;
723 s->tone_out[0].v3 = s->tone_out[0].fac*s->tone_out[0].v2 - v1 + famp;
725 v1 = s->tone_out[1].v2;
726 s->tone_out[1].v2 = s->tone_out[1].v3;
727 s->tone_out[1].v3 = s->tone_out[1].fac*s->tone_out[1].v2 - v1 + famp;
729 v1 = s->tone_out[2].v2;
730 s->tone_out[2].v2 = s->tone_out[2].v3;
731 s->tone_out[2].v3 = s->tone_out[2].fac*s->tone_out[2].v2 - v1 + famp;
733 v1 = s->tone_out[3].v2;
734 s->tone_out[3].v2 = s->tone_out[3].v3;
735 s->tone_out[3].v3 = s->tone_out[3].fac*s->tone_out[3].v2 - v1 + famp;
737 v1 = s->tone_out[4].v2;
738 s->tone_out[4].v2 = s->tone_out[4].v3;
739 s->tone_out[4].v3 = s->tone_out[4].fac*s->tone_out[4].v2 - v1 + famp;
741 v1 = s->tone_out[5].v2;
742 s->tone_out[5].v2 = s->tone_out[5].v3;
743 s->tone_out[5].v3 = s->tone_out[5].fac*s->tone_out[5].v2 - v1 + famp;
745 #ifdef OLD_DSP_ROUTINES
746 v1 = s->tone_out2nd[0].v2;
747 s->tone_out2nd[0].v2 = s->tone_out2nd[0].v3;
748 s->tone_out2nd[0].v3 = s->tone_out2nd[0].fac*s->tone_out2nd[0].v2 - v1 + famp;
750 v1 = s->tone_out2nd[1].v2;
751 s->tone_out2nd[1].v2 = s->tone_out2nd[1].v3;
752 s->tone_out2nd[1].v3 = s->tone_out2nd[1].fac*s->tone_out2nd[1].v2 - v1 + famp;
754 v1 = s->tone_out2nd[2].v2;
755 s->tone_out2nd[2].v2 = s->tone_out2nd[2].v3;
756 s->tone_out2nd[2].v3 = s->tone_out2nd[2].fac*s->tone_out2nd[2].v2 - v1 + famp;
758 v1 = s->tone_out2nd[3].v2;
759 s->tone_out2nd[3].v2 = s->tone_out2nd[3].v3;
760 s->tone_out2nd[3].v3 = s->tone_out2nd[3].fac*s->tone_out2nd[3].v2 - v1 + famp;
762 v1 = s->tone_out2nd[4].v2;
763 s->tone_out2nd[4].v2 = s->tone_out2nd[4].v3;
764 s->tone_out2nd[4].v3 = s->tone_out2nd[4].fac*s->tone_out2nd[2].v2 - v1 + famp;
766 v1 = s->tone_out2nd[3].v2;
767 s->tone_out2nd[5].v2 = s->tone_out2nd[6].v3;
768 s->tone_out2nd[5].v3 = s->tone_out2nd[6].fac*s->tone_out2nd[3].v2 - v1 + famp;
772 s->current_sample += (limit - sample);
773 if (s->current_sample < MF_GSIZE) {
774 if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) {
775 /* If we had a hit last time, go ahead and clear this out since likely it
776 will be another hit */
777 for (i=sample;i<limit;i++)
785 #ifdef OLD_DSP_ROUTINES
786 /* We're at the end of an MF detection block. Go ahead and calculate
789 tone_energy[i] = goertzel_result(&s->tone_out[i]);
793 max = tone_energy[0];
795 if (tone_energy[i] > max) {
796 max = tone_energy[i];
801 /* Find 2nd highest */
803 max = tone_energy[0];
806 max = tone_energy[1];
811 if (i == best1) continue;
812 if (tone_energy[i] > max) {
813 max = tone_energy[i];
819 if (best1 != best2) sofarsogood=1;
821 /* Check for relative energies */
823 if (i == best1) continue;
824 if (i == best2) continue;
825 if (tone_energy[best1] < tone_energy[i] * MF_RELATIVE_PEAK) {
829 if (tone_energy[best2] < tone_energy[i] * MF_RELATIVE_PEAK) {
836 /* Check for 2nd harmonic */
837 if (goertzel_result(&s->tone_out2nd[best1]) * MF_2ND_HARMONIC > tone_energy[best1])
839 else if (goertzel_result(&s->tone_out2nd[best2]) * MF_2ND_HARMONIC > tone_energy[best2])
843 hit = mf_hit[best1][best2];
844 if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) {
845 /* Zero out frame data if this is part DTMF */
846 for (i=sample;i<limit;i++)
850 /* Look for two consecutive clean hits */
851 if ((hit == s->hit3) && (s->hit3 != s->hit2)) {
853 s->detected_digits++;
854 if (s->current_digits < MAX_DTMF_DIGITS - 2) {
855 s->digits[s->current_digits++] = hit;
856 s->digits[s->current_digits] = '\0';
866 /* Reinitialise the detector for the next block */
867 for (i = 0; i < 6; i++)
869 goertzel_reset(&s->tone_out[i]);
870 goertzel_reset(&s->tone_out2nd[i]);
873 s->current_sample = 0;
876 /* We're at the end of an MF detection block. */
877 /* Find the two highest energies. The spec says to look for
878 two tones and two tones only. Taking this literally -ie
879 only two tones pass the minimum threshold - doesn't work
880 well. The sinc function mess, due to rectangular windowing
881 ensure that! Find the two highest energies and ensure they
882 are considerably stronger than any of the others. */
883 energy[0] = goertzel_result(&s->tone_out[0]);
884 energy[1] = goertzel_result(&s->tone_out[1]);
885 if (energy[0] > energy[1])
896 for (i = 2; i < 6; i++)
898 energy[i] = goertzel_result(&s->tone_out[i]);
899 if (energy[i] >= energy[best])
904 else if (energy[i] >= energy[second_best])
909 /* Basic signal level and twist tests */
911 if (energy[best] >= BELL_MF_THRESHOLD
913 energy[second_best] >= BELL_MF_THRESHOLD
915 energy[best] < energy[second_best]*BELL_MF_TWIST
917 energy[best]*BELL_MF_TWIST > energy[second_best])
919 /* Relative peak test */
921 for (i = 0; i < 6; i++)
923 if (i != best && i != second_best)
925 if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best])
927 /* The best two are not clearly the best */
936 /* Get the values into ascending order */
937 if (second_best < best)
943 best = best*5 + second_best - 1;
944 hit = bell_mf_positions[best];
945 /* Look for two successive similar results */
946 /* The logic in the next test is:
947 For KP we need 4 successive identical clean detects, with
948 two blocks of something different preceeding it. For anything
949 else we need two successive identical clean detects, with
950 two blocks of something different preceeding it. */
951 if (hit == s->hits[4]
955 ((hit != '*' && hit != s->hits[2] && hit != s->hits[1])
957 (hit == '*' && hit == s->hits[2] && hit != s->hits[1] && hit != s->hits[0])))
959 s->detected_digits++;
960 if (s->current_digits < MAX_DTMF_DIGITS)
962 s->digits[s->current_digits++] = hit;
963 s->digits[s->current_digits] = '\0';
975 s->hits[0] = s->hits[1];
976 s->hits[1] = s->hits[2];
977 s->hits[2] = s->hits[3];
978 s->hits[3] = s->hits[4];
980 /* Reinitialise the detector for the next block */
981 for (i = 0; i < 6; i++)
982 goertzel_reset(&s->tone_out[i]);
983 s->current_sample = 0;
986 if ((!s->mhit) || (s->mhit != hit))
994 static int __ast_dsp_digitdetect(struct ast_dsp *dsp, short *s, int len, int *writeback)
997 if (dsp->digitmode & DSP_DIGITMODE_MF)
998 res = mf_detect(&dsp->td.mf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback);
1000 res = dtmf_detect(&dsp->td.dtmf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback);
1004 int ast_dsp_digitdetect(struct ast_dsp *dsp, struct ast_frame *inf)
1009 if (inf->frametype != AST_FRAME_VOICE) {
1010 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
1013 if (inf->subclass != AST_FORMAT_SLINEAR) {
1014 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
1018 len = inf->datalen / 2;
1019 return __ast_dsp_digitdetect(dsp, s, len, &ign);
1022 static inline int pair_there(float p1, float p2, float i1, float i2, float e)
1024 /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
1025 /* Make sure absolute levels are high enough */
1026 if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH))
1028 /* Amplify ignored stuff */
1032 /* Check first tone */
1033 if ((p1 < i1) || (p1 < i2) || (p1 < e))
1036 if ((p2 < i1) || (p2 < i2) || (p2 < e))
1038 /* Guess it's there... */
1042 int ast_dsp_getdigits (struct ast_dsp *dsp,
1046 if (dsp->digitmode & DSP_DIGITMODE_MF) {
1047 if (max > dsp->td.mf.current_digits)
1048 max = dsp->td.mf.current_digits;
1051 memcpy (buf, dsp->td.mf.digits, max);
1052 memmove (dsp->td.mf.digits, dsp->td.mf.digits + max, dsp->td.mf.current_digits - max);
1053 dsp->td.mf.current_digits -= max;
1058 if (max > dsp->td.dtmf.current_digits)
1059 max = dsp->td.dtmf.current_digits;
1062 memcpy (buf, dsp->td.dtmf.digits, max);
1063 memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max);
1064 dsp->td.dtmf.current_digits -= max;
1071 static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len)
1075 int newstate = TONE_STATE_SILENCE;
1078 /* Take the lesser of the number of samples we need and what we have */
1080 if (pass > GSAMP_SIZE - dsp->gsamps)
1081 pass = GSAMP_SIZE - dsp->gsamps;
1082 for (x=0;x<pass;x++) {
1083 goertzel_sample(&dsp->freqs[HZ_350], s[x]);
1084 goertzel_sample(&dsp->freqs[HZ_440], s[x]);
1085 goertzel_sample(&dsp->freqs[HZ_480], s[x]);
1086 goertzel_sample(&dsp->freqs[HZ_620], s[x]);
1087 goertzel_sample(&dsp->freqs[HZ_950], s[x]);
1088 goertzel_sample(&dsp->freqs[HZ_1400], s[x]);
1089 goertzel_sample(&dsp->freqs[HZ_1800], s[x]);
1090 dsp->genergy += s[x] * s[x];
1093 dsp->gsamps += pass;
1095 if (dsp->gsamps == GSAMP_SIZE) {
1103 hz_350 = goertzel_result(&dsp->freqs[HZ_350]);
1104 hz_440 = goertzel_result(&dsp->freqs[HZ_440]);
1105 hz_480 = goertzel_result(&dsp->freqs[HZ_480]);
1106 hz_620 = goertzel_result(&dsp->freqs[HZ_620]);
1107 hz_950 = goertzel_result(&dsp->freqs[HZ_950]);
1108 hz_1400 = goertzel_result(&dsp->freqs[HZ_1400]);
1109 hz_1800 = goertzel_result(&dsp->freqs[HZ_1800]);
1111 printf("Got whole dsp state: 350: %e, 440: %e, 480: %e, 620: %e, 950: %e, 1400: %e, 1800: %e, Energy: %e\n",
1112 hz_350, hz_440, hz_480, hz_620, hz_950, hz_1400, hz_1800, dsp->genergy);
1114 if (pair_there(hz_480, hz_620, hz_350, hz_440, dsp->genergy)) {
1115 newstate = TONE_STATE_BUSY;
1116 } else if (pair_there(hz_440, hz_480, hz_350, hz_620, dsp->genergy)) {
1117 newstate = TONE_STATE_RINGING;
1118 } else if (pair_there(hz_350, hz_440, hz_480, hz_620, dsp->genergy)) {
1119 newstate = TONE_STATE_DIALTONE;
1120 } else if (hz_950 > TONE_MIN_THRESH * TONE_THRESH) {
1121 newstate = TONE_STATE_SPECIAL1;
1122 } else if (hz_1400 > TONE_MIN_THRESH * TONE_THRESH) {
1123 if (dsp->tstate == TONE_STATE_SPECIAL1)
1124 newstate = TONE_STATE_SPECIAL2;
1125 } else if (hz_1800 > TONE_MIN_THRESH * TONE_THRESH) {
1126 if (dsp->tstate == TONE_STATE_SPECIAL2)
1127 newstate = TONE_STATE_SPECIAL3;
1128 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
1129 newstate = TONE_STATE_TALKING;
1131 newstate = TONE_STATE_SILENCE;
1133 if (newstate == dsp->tstate) {
1135 if (dsp->tcount == COUNT_THRESH) {
1136 if (dsp->tstate == TONE_STATE_BUSY) {
1137 res = AST_CONTROL_BUSY;
1138 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1139 } else if (dsp->tstate == TONE_STATE_TALKING) {
1140 res = AST_CONTROL_ANSWER;
1141 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1142 } else if (dsp->tstate == TONE_STATE_RINGING)
1143 res = AST_CONTROL_RINGING;
1144 else if (dsp->tstate == TONE_STATE_SPECIAL3) {
1145 res = AST_CONTROL_CONGESTION;
1146 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1152 printf("Newstate: %d\n", newstate);
1154 dsp->tstate = newstate;
1158 /* Reset goertzel */
1160 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
1167 printf("Returning %d\n", res);
1172 int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf)
1174 if (inf->frametype != AST_FRAME_VOICE) {
1175 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
1178 if (inf->subclass != AST_FORMAT_SLINEAR) {
1179 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
1182 return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2);
1185 static int __ast_dsp_silence(struct ast_dsp *dsp, short *s, int len, int *totalsilence)
1192 for (x=0;x<len; x++)
1195 if (accum < dsp->threshold) {
1196 dsp->totalsilence += len/8;
1197 if (dsp->totalnoise) {
1198 /* Move and save history */
1199 memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount +1, dsp->busycount*sizeof(dsp->historicnoise[0]));
1200 dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
1201 /* we don't want to check for busydetect that frequently */
1206 dsp->totalnoise = 0;
1209 dsp->totalnoise += len/8;
1210 if (dsp->totalsilence) {
1211 int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
1212 int silence2 = dsp->historicsilence[DSP_HISTORY - 2];
1213 /* Move and save history */
1214 memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount*sizeof(dsp->historicsilence[0]));
1215 dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
1216 /* check if the previous sample differs only by BUSY_PERCENT from the one before it */
1217 if (silence1 < silence2) {
1218 if (silence1 + silence1/BUSY_PERCENT >= silence2)
1223 if (silence1 - silence1/BUSY_PERCENT <= silence2)
1230 dsp->totalsilence = 0;
1233 *totalsilence = dsp->totalsilence;
1236 #ifdef BUSYDETECT_MARTIN
1237 int ast_dsp_busydetect(struct ast_dsp *dsp)
1240 #ifndef BUSYDETECT_TONEONLY
1241 int avgsilence = 0, hitsilence = 0;
1243 int avgtone = 0, hittone = 0;
1244 if (!dsp->busymaybe)
1246 for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
1247 #ifndef BUSYDETECT_TONEONLY
1248 avgsilence += dsp->historicsilence[x];
1250 avgtone += dsp->historicnoise[x];
1252 #ifndef BUSYDETECT_TONEONLY
1253 avgsilence /= dsp->busycount;
1255 avgtone /= dsp->busycount;
1256 for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
1257 #ifndef BUSYDETECT_TONEONLY
1258 if (avgsilence > dsp->historicsilence[x]) {
1259 if (avgsilence - (avgsilence / BUSY_PERCENT) <= dsp->historicsilence[x])
1262 if (avgsilence + (avgsilence / BUSY_PERCENT) >= dsp->historicsilence[x])
1266 if (avgtone > dsp->historicnoise[x]) {
1267 if (avgtone - (avgtone / BUSY_PERCENT) <= dsp->historicsilence[x])
1270 if (avgtone + (avgtone / BUSY_PERCENT) >= dsp->historicsilence[x])
1274 #ifndef BUSYDETECT_TONEONLY
1275 if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) {
1277 if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
1279 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
1280 #ifdef BUSYDETECT_TONEONLY
1281 #error You cant use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE
1283 if (avgtone > avgsilence) {
1284 if (avgtone - avgtone/(BUSY_PERCENT*2) <= avgsilence)
1287 if (avgtone + avgtone/(BUSY_PERCENT*2) >= avgsilence)
1296 ast_log(LOG_NOTICE, "detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
1303 int ast_dsp_busydetect(struct ast_dsp *dsp)
1310 if (dsp->busy_hits > 5);
1313 if (dsp->busymaybe) {
1315 printf("Maybe busy!\n");
1320 for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
1322 printf("Silence: %d, Noise: %d\n", dsp->historicsilence[x], dsp->historicnoise[x]);
1324 if (dsp->historicsilence[x] < min)
1325 min = dsp->historicsilence[x];
1326 if (dsp->historicnoise[x] < min)
1327 min = dsp->historicnoise[x];
1328 if (dsp->historicsilence[x] > max)
1329 max = dsp->historicsilence[x];
1330 if (dsp->historicnoise[x] > max)
1331 max = dsp->historicnoise[x];
1333 if ((max - min < BUSY_THRESHOLD) && (max < BUSY_MAX) && (min > BUSY_MIN)) {
1340 printf("Min: %d, max: %d\n", min, max);
1347 int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
1352 if (f->frametype != AST_FRAME_VOICE) {
1353 ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
1356 if (f->subclass != AST_FORMAT_SLINEAR) {
1357 ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
1362 return __ast_dsp_silence(dsp, s, len, totalsilence);
1365 struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af, int needlock)
1371 unsigned short *shortdata;
1372 unsigned char *odata;
1376 #define FIX_INF(inf) do { \
1378 switch(inf->subclass) { \
1379 case AST_FORMAT_SLINEAR: \
1381 case AST_FORMAT_ULAW: \
1382 for (x=0;x<len;x++) \
1383 odata[x] = AST_LIN2MU(shortdata[x]); \
1385 case AST_FORMAT_ALAW: \
1386 for (x=0;x<len;x++) \
1387 odata[x] = AST_LIN2A(shortdata[x]); \
1395 if (af->frametype != AST_FRAME_VOICE)
1399 /* Make sure we have short data */
1400 switch(af->subclass) {
1401 case AST_FORMAT_SLINEAR:
1402 shortdata = af->data;
1403 len = af->datalen / 2;
1405 case AST_FORMAT_ULAW:
1406 shortdata = alloca(af->datalen * 2);
1408 ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno));
1412 shortdata[x] = AST_MULAW(odata[x]);
1414 case AST_FORMAT_ALAW:
1415 shortdata = alloca(af->datalen * 2);
1417 ast_log(LOG_WARNING, "Unable to allocate stack space for data: %s\n", strerror(errno));
1421 shortdata[x] = AST_ALAW(odata[x]);
1424 ast_log(LOG_WARNING, "Unable to process inband DTMF on %d frames\n", af->subclass);
1427 silence = __ast_dsp_silence(dsp, shortdata, len, NULL);
1428 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
1429 memset(&dsp->f, 0, sizeof(dsp->f));
1430 dsp->f.frametype = AST_FRAME_NULL;
1433 if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
1434 chan->_softhangup |= AST_SOFTHANGUP_DEV;
1435 memset(&dsp->f, 0, sizeof(dsp->f));
1436 dsp->f.frametype = AST_FRAME_CONTROL;
1437 dsp->f.subclass = AST_CONTROL_BUSY;
1438 ast_log(LOG_DEBUG, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name);
1441 if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) {
1442 digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback);
1445 printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode);
1447 if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) {
1448 if (!dsp->thinkdigit) {
1450 /* Looks like we might have something. Request a conference mute for the moment */
1451 memset(&dsp->f, 0, sizeof(dsp->f));
1452 dsp->f.frametype = AST_FRAME_DTMF;
1453 dsp->f.subclass = 'm';
1454 dsp->thinkdigit = 'x';
1457 ast_queue_frame(chan, af, needlock);
1463 /* Thought we saw one last time. Pretty sure we really have now */
1464 if (dsp->thinkdigit) {
1465 if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) {
1466 /* If we found a digit, and we're changing digits, go
1467 ahead and send this one, but DON'T stop confmute because
1468 we're detecting something else, too... */
1469 memset(&dsp->f, 0, sizeof(dsp->f));
1470 dsp->f.frametype = AST_FRAME_DTMF;
1471 dsp->f.subclass = dsp->thinkdigit;
1474 ast_queue_frame(chan, af, needlock);
1477 dsp->thinkdigit = digit;
1480 dsp->thinkdigit = digit;
1482 if (dsp->thinkdigit) {
1483 memset(&dsp->f, 0, sizeof(dsp->f));
1484 if (dsp->thinkdigit != 'x') {
1485 /* If we found a digit, send it now */
1486 dsp->f.frametype = AST_FRAME_DTMF;
1487 dsp->f.subclass = dsp->thinkdigit;
1488 dsp->thinkdigit = 0;
1490 dsp->f.frametype = AST_FRAME_DTMF;
1491 dsp->f.subclass = 'u';
1492 dsp->thinkdigit = 0;
1496 ast_queue_frame(chan, af, needlock);
1502 } else if (!digit) {
1503 /* Only check when there is *not* a hit... */
1504 if (dsp->digitmode & DSP_DIGITMODE_MF) {
1505 if (dsp->td.mf.current_digits) {
1506 memset(&dsp->f, 0, sizeof(dsp->f));
1507 dsp->f.frametype = AST_FRAME_DTMF;
1508 dsp->f.subclass = dsp->td.mf.digits[0];
1509 memmove(dsp->td.mf.digits, dsp->td.mf.digits + 1, dsp->td.mf.current_digits);
1510 dsp->td.mf.current_digits--;
1513 ast_queue_frame(chan, af, needlock);
1518 if (dsp->td.dtmf.current_digits) {
1519 memset(&dsp->f, 0, sizeof(dsp->f));
1520 dsp->f.frametype = AST_FRAME_DTMF;
1521 dsp->f.subclass = dsp->td.dtmf.digits[0];
1522 memmove(dsp->td.dtmf.digits, dsp->td.dtmf.digits + 1, dsp->td.dtmf.current_digits);
1523 dsp->td.dtmf.current_digits--;
1526 ast_queue_frame(chan, af, needlock);
1533 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
1534 res = __ast_dsp_call_progress(dsp, shortdata, len);
1535 memset(&dsp->f, 0, sizeof(dsp->f));
1536 dsp->f.frametype = AST_FRAME_CONTROL;
1539 case AST_CONTROL_ANSWER:
1540 case AST_CONTROL_BUSY:
1541 case AST_CONTROL_RINGING:
1542 case AST_CONTROL_CONGESTION:
1543 dsp->f.subclass = res;
1545 ast_queue_frame(chan, &dsp->f, needlock);
1548 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
1556 struct ast_dsp *ast_dsp_new(void)
1558 struct ast_dsp *dsp;
1559 dsp = malloc(sizeof(struct ast_dsp));
1561 memset(dsp, 0, sizeof(struct ast_dsp));
1562 dsp->threshold = DEFAULT_THRESHOLD;
1563 dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
1564 dsp->busycount = DSP_HISTORY;
1565 /* Initialize goertzels */
1566 goertzel_init(&dsp->freqs[HZ_350], 350.0, GSAMP_SIZE);
1567 goertzel_init(&dsp->freqs[HZ_440], 440.0, GSAMP_SIZE);
1568 goertzel_init(&dsp->freqs[HZ_480], 480.0, GSAMP_SIZE);
1569 goertzel_init(&dsp->freqs[HZ_620], 620.0, GSAMP_SIZE);
1570 goertzel_init(&dsp->freqs[HZ_950], 950.0, GSAMP_SIZE);
1571 goertzel_init(&dsp->freqs[HZ_1400], 1400.0, GSAMP_SIZE);
1572 goertzel_init(&dsp->freqs[HZ_1800], 1800.0, GSAMP_SIZE);
1573 /* Initialize DTMF detector */
1574 ast_dtmf_detect_init(&dsp->td.dtmf);
1579 void ast_dsp_set_features(struct ast_dsp *dsp, int features)
1581 dsp->features = features;
1584 void ast_dsp_free(struct ast_dsp *dsp)
1589 void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
1591 dsp->threshold = threshold;
1594 void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
1598 if (cadences > DSP_HISTORY)
1599 cadences = DSP_HISTORY;
1600 dsp->busycount = cadences;
1603 void ast_dsp_digitreset(struct ast_dsp *dsp)
1606 dsp->thinkdigit = 0;
1607 if (dsp->digitmode & DSP_DIGITMODE_MF) {
1608 memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits));
1609 dsp->td.mf.current_digits = 0;
1610 /* Reinitialise the detector for the next block */
1611 for (i = 0; i < 6; i++) {
1612 goertzel_reset(&dsp->td.mf.tone_out[i]);
1613 #ifdef OLD_DSP_ROUTINES
1614 goertzel_reset(&dsp->td.mf.tone_out2nd[i]);
1617 #ifdef OLD_DSP_ROUTINES
1618 dsp->td.mf.energy = 0.0;
1619 dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0;
1621 dsp->td.mf.hits[4] = dsp->td.mf.hits[3] = dsp->td.mf.hits[2] = dsp->td.mf.hits[1] = dsp->td.mf.hits[0] = dsp->td.mf.mhit = 0;
1623 dsp->td.mf.current_sample = 0;
1625 memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits));
1626 dsp->td.dtmf.current_digits = 0;
1627 /* Reinitialise the detector for the next block */
1628 for (i = 0; i < 4; i++) {
1629 goertzel_reset(&dsp->td.dtmf.row_out[i]);
1630 goertzel_reset(&dsp->td.dtmf.col_out[i]);
1631 #ifdef OLD_DSP_ROUTINES
1632 goertzel_reset(&dsp->td.dtmf.row_out2nd[i]);
1633 goertzel_reset(&dsp->td.dtmf.col_out2nd[i]);
1636 goertzel_reset (&dsp->td.dtmf.fax_tone);
1637 #ifdef OLD_DSP_ROUTINES
1638 goertzel_reset (&dsp->td.dtmf.fax_tone2nd);
1639 dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0;
1641 dsp->td.dtmf.hits[2] = dsp->td.dtmf.hits[1] = dsp->td.dtmf.hits[0] = dsp->td.dtmf.mhit = 0;
1643 dsp->td.dtmf.energy = 0.0;
1644 dsp->td.dtmf.current_sample = 0;
1648 void ast_dsp_reset(struct ast_dsp *dsp)
1651 dsp->totalsilence = 0;
1654 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
1655 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
1656 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
1660 int ast_dsp_digitmode(struct ast_dsp *dsp, int digitmode)
1663 old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
1664 new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
1666 /* Must initialize structures if switching from MF to DTMF or vice-versa */
1667 if (new & DSP_DIGITMODE_MF)
1668 ast_mf_detect_init(&dsp->td.mf);
1670 ast_dtmf_detect_init(&dsp->td.dtmf);
1672 dsp->digitmode = digitmode;