use tzafrir's patch to fix this problem properly... i made the previous set of change...
[asterisk-bristuff.git] / main / dsp.c
blob3caf65027e2b990b4fe3052d2cfa67a668eb9b66
1 /*
2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * Goertzel routines are borrowed from Steve Underwood's tremendous work on the
9 * DTMF detector.
11 * See http://www.asterisk.org for more information about
12 * the Asterisk project. Please do not directly contact
13 * any of the maintainers of this project for assistance;
14 * the project provides a web site, mailing lists and IRC
15 * channels for your use.
17 * This program is free software, distributed under the terms of
18 * the GNU General Public License Version 2. See the LICENSE file
19 * at the top of the source tree.
22 /*! \file
24 * \brief Convenience Signal Processing routines
26 * \author Mark Spencer <markster@digium.com>
27 * \author Steve Underwood <steveu@coppice.org>
30 /* Some routines from tone_detect.c by Steven Underwood as published under the zapata library */
32 tone_detect.c - General telephony tone detection, and specific
33 detection of DTMF.
35 Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
37 Despite my general liking of the GPL, I place this code in the
38 public domain for the benefit of all mankind - even the slimy
39 ones who might try to proprietize my work and use it to my
40 detriment.
43 #include "asterisk.h"
45 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
47 #include <sys/types.h>
48 #include <stdlib.h>
49 #include <unistd.h>
50 #include <string.h>
51 #include <math.h>
52 #include <errno.h>
53 #include <stdio.h>
55 #include "asterisk/frame.h"
56 #include "asterisk/channel.h"
57 #include "asterisk/logger.h"
58 #include "asterisk/dsp.h"
59 #include "asterisk/ulaw.h"
60 #include "asterisk/alaw.h"
61 #include "asterisk/utils.h"
63 /*! Number of goertzels for progress detect */
64 enum gsamp_size {
65 GSAMP_SIZE_NA = 183, /*!< North America - 350, 440, 480, 620, 950, 1400, 1800 Hz */
66 GSAMP_SIZE_CR = 188, /*!< Costa Rica, Brazil - Only care about 425 Hz */
67 GSAMP_SIZE_UK = 160 /*!< UK disconnect goertzel feed - should trigger 400hz */
70 enum prog_mode {
71 PROG_MODE_NA = 0,
72 PROG_MODE_CR,
73 PROG_MODE_UK
76 enum freq_index {
77 /*! For US modes { */
78 HZ_350 = 0,
79 HZ_440,
80 HZ_480,
81 HZ_620,
82 HZ_950,
83 HZ_1400,
84 HZ_1800, /*!< } */
86 /*! For CR/BR modes */
87 HZ_425 = 0,
89 /*! For UK mode */
90 HZ_400 = 0
93 static struct progalias {
94 char *name;
95 enum prog_mode mode;
96 } aliases[] = {
97 { "us", PROG_MODE_NA },
98 { "ca", PROG_MODE_NA },
99 { "cr", PROG_MODE_CR },
100 { "br", PROG_MODE_CR },
101 { "uk", PROG_MODE_UK },
104 static struct progress {
105 enum gsamp_size size;
106 int freqs[7];
107 } modes[] = {
108 { GSAMP_SIZE_NA, { 350, 440, 480, 620, 950, 1400, 1800 } }, /*!< North America */
109 { GSAMP_SIZE_CR, { 425 } }, /*!< Costa Rica, Brazil */
110 { GSAMP_SIZE_UK, { 400 } }, /*!< UK */
113 #define DEFAULT_THRESHOLD 512
115 enum busy_detect {
116 BUSY_PERCENT = 10, /*!< The percentage difference between the two last silence periods */
117 BUSY_PAT_PERCENT = 7, /*!< The percentage difference between measured and actual pattern */
118 BUSY_THRESHOLD = 100, /*!< Max number of ms difference between max and min times in busy */
119 BUSY_MIN = 75, /*!< Busy must be at least 80 ms in half-cadence */
120 BUSY_MAX =3100 /*!< Busy can't be longer than 3100 ms in half-cadence */
123 /*! Remember last 15 units */
124 #define DSP_HISTORY 15
126 /*! Define if you want the fax detector -- NOT RECOMMENDED IN -STABLE */
127 #define FAX_DETECT
129 #define TONE_THRESH 10.0 /*!< How much louder the tone should be than channel energy */
130 #define TONE_MIN_THRESH 1e8 /*!< How much tone there should be at least to attempt */
132 /*! All THRESH_XXX values are in GSAMP_SIZE chunks (us = 22ms) */
133 enum gsamp_thresh {
134 THRESH_RING = 8, /*!< Need at least 150ms ring to accept */
135 THRESH_TALK = 2, /*!< Talk detection does not work continuously */
136 THRESH_BUSY = 4, /*!< Need at least 80ms to accept */
137 THRESH_CONGESTION = 4, /*!< Need at least 80ms to accept */
138 THRESH_HANGUP = 60, /*!< Need at least 1300ms to accept hangup */
139 THRESH_RING2ANSWER = 300 /*!< Timeout from start of ring to answer (about 6600 ms) */
142 #define MAX_DTMF_DIGITS 128
144 /* Basic DTMF specs:
146 * Minimum tone on = 40ms
147 * Minimum tone off = 50ms
148 * Maximum digit rate = 10 per second
149 * Normal twist <= 8dB accepted
150 * Reverse twist <= 4dB accepted
151 * S/N >= 15dB will detect OK
152 * Attenuation <= 26dB will detect OK
153 * Frequency tolerance +- 1.5% will detect, +-3.5% will reject
156 #define DTMF_THRESHOLD 8.0e7
157 #define FAX_THRESHOLD 8.0e7
158 #define FAX_2ND_HARMONIC 2.0 /* 4dB */
160 #ifdef RADIO_RELAX
161 #define DTMF_NORMAL_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 11.3 : 6.3) /* 8dB sph 12.3 was 6.3 */
162 #define DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 9.5 : 2.5) /* 4dB normal sph 12.5 : 5.5 was 6.5 : 2.5 */
163 #define DTMF_RELATIVE_PEAK_ROW ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 3.3 : 6.3) /* 8dB sph was 6.3 */
164 #define DTMF_RELATIVE_PEAK_COL ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 3.3 : 6.3) /* 8dB sph was 6.3 */
165 #define DTMF_TO_TOTAL_ENERGY ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 26.0 : 42.0)
166 #else
167 #define DTMF_NORMAL_TWIST 6.3
168 #define DTMF_REVERSE_TWIST ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 4.0 : 2.5) /* 4dB normal */
169 #define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */
170 #define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */
171 #define DTMF_TO_TOTAL_ENERGY 42.0
172 #endif
174 #ifdef OLD_DSP_ROUTINES
175 #define DTMF_2ND_HARMONIC_ROW ((digitmode & DSP_DIGITMODE_RELAXDTMF) ? 1.7 : 2.5) /* 4dB normal */
176 #define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */
178 #define MF_THRESHOLD 8.0e7
179 #define MF_NORMAL_TWIST 5.3 /* 8dB */
180 #define MF_REVERSE_TWIST 4.0 /* was 2.5 */
181 #define MF_RELATIVE_PEAK 5.3 /* 8dB */
182 #define MF_2ND_HARMONIC 1.7 /* was 2.5 */
183 #else
184 #define BELL_MF_THRESHOLD 1.6e9
185 #define BELL_MF_TWIST 4.0 /* 6dB */
186 #define BELL_MF_RELATIVE_PEAK 12.6 /* 11dB */
187 #endif
189 #if !defined(BUSYDETECT_MARTIN) && !defined(BUSYDETECT) && !defined(BUSYDETECT_TONEONLY) && !defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
190 #define BUSYDETECT_MARTIN
191 #endif
193 typedef struct {
194 float v2;
195 float v3;
196 float fac;
197 #ifndef OLD_DSP_ROUTINES
198 int samples;
199 #endif
200 } goertzel_state_t;
202 typedef struct
204 goertzel_state_t row_out[4];
205 goertzel_state_t col_out[4];
206 #ifdef FAX_DETECT
207 goertzel_state_t fax_tone;
208 #endif
209 #ifdef OLD_DSP_ROUTINES
210 goertzel_state_t row_out2nd[4];
211 goertzel_state_t col_out2nd[4];
212 #ifdef FAX_DETECT
213 goertzel_state_t fax_tone2nd;
214 #endif
215 int hit1;
216 int hit2;
217 int hit3;
218 int hit4;
219 #else
220 int lasthit;
221 #endif
222 int mhit;
223 float energy;
224 int current_sample;
226 char digits[MAX_DTMF_DIGITS + 1];
228 int current_digits;
229 int detected_digits;
230 int lost_digits;
231 int digit_hits[16];
232 #ifdef FAX_DETECT
233 int fax_hits;
234 #endif
235 } dtmf_detect_state_t;
237 typedef struct
239 goertzel_state_t tone_out[6];
240 int mhit;
241 #ifdef OLD_DSP_ROUTINES
242 int hit1;
243 int hit2;
244 int hit3;
245 int hit4;
246 goertzel_state_t tone_out2nd[6];
247 float energy;
248 #else
249 int hits[5];
250 #endif
251 int current_sample;
253 char digits[MAX_DTMF_DIGITS + 1];
255 int current_digits;
256 int detected_digits;
257 int lost_digits;
258 #ifdef FAX_DETECT
259 int fax_hits;
260 #endif
261 } mf_detect_state_t;
263 static float dtmf_row[] =
265 697.0, 770.0, 852.0, 941.0
267 static float dtmf_col[] =
269 1209.0, 1336.0, 1477.0, 1633.0
272 static float mf_tones[] =
274 700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0
277 #ifdef FAX_DETECT
278 static float fax_freq = 1100.0;
279 #endif
281 static char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
283 #ifdef OLD_DSP_ROUTINES
284 static char mf_hit[6][6] = {
285 /* 700 + */ { 0, '1', '2', '4', '7', 'C' },
286 /* 900 + */ { '1', 0, '3', '5', '8', 'A' },
287 /* 1100 + */ { '2', '3', 0, '6', '9', '*' },
288 /* 1300 + */ { '4', '5', '6', 0, '0', 'B' },
289 /* 1500 + */ { '7', '8', '9', '0', 0, '#' },
290 /* 1700 + */ { 'C', 'A', '*', 'B', '#', 0 },
292 #else
293 static char bell_mf_positions[] = "1247C-358A--69*---0B----#";
294 #endif
296 static inline void goertzel_sample(goertzel_state_t *s, short sample)
298 float v1;
299 float fsamp = sample;
301 v1 = s->v2;
302 s->v2 = s->v3;
303 s->v3 = s->fac * s->v2 - v1 + fsamp;
306 static inline void goertzel_update(goertzel_state_t *s, short *samps, int count)
308 int i;
310 for (i=0;i<count;i++)
311 goertzel_sample(s, samps[i]);
315 static inline float goertzel_result(goertzel_state_t *s)
317 return s->v3 * s->v3 + s->v2 * s->v2 - s->v2 * s->v3 * s->fac;
320 static inline void goertzel_init(goertzel_state_t *s, float freq, int samples)
322 s->v2 = s->v3 = 0.0;
323 s->fac = 2.0 * cos(2.0 * M_PI * (freq / 8000.0));
324 #ifndef OLD_DSP_ROUTINES
325 s->samples = samples;
326 #endif
329 static inline void goertzel_reset(goertzel_state_t *s)
331 s->v2 = s->v3 = 0.0;
334 struct ast_dsp {
335 struct ast_frame f;
336 int threshold;
337 int totalsilence;
338 int totalnoise;
339 int features;
340 int ringtimeout;
341 int busymaybe;
342 int busycount;
343 int busy_tonelength;
344 int busy_quietlength;
345 int historicnoise[DSP_HISTORY];
346 int historicsilence[DSP_HISTORY];
347 goertzel_state_t freqs[7];
348 int freqcount;
349 int gsamps;
350 enum gsamp_size gsamp_size;
351 enum prog_mode progmode;
352 int tstate;
353 int tcount;
354 int digitmode;
355 int thinkdigit;
356 float genergy;
357 union {
358 dtmf_detect_state_t dtmf;
359 mf_detect_state_t mf;
360 } td;
363 static void ast_dtmf_detect_init (dtmf_detect_state_t *s)
365 int i;
367 #ifdef OLD_DSP_ROUTINES
368 s->hit1 =
369 s->mhit =
370 s->hit3 =
371 s->hit4 =
372 s->hit2 = 0;
373 #else
374 s->lasthit = 0;
375 #endif
376 for (i = 0; i < 4; i++) {
377 goertzel_init (&s->row_out[i], dtmf_row[i], 102);
378 goertzel_init (&s->col_out[i], dtmf_col[i], 102);
379 #ifdef OLD_DSP_ROUTINES
380 goertzel_init (&s->row_out2nd[i], dtmf_row[i] * 2.0, 102);
381 goertzel_init (&s->col_out2nd[i], dtmf_col[i] * 2.0, 102);
382 #endif
383 s->energy = 0.0;
385 #ifdef FAX_DETECT
386 /* Same for the fax dector */
387 goertzel_init (&s->fax_tone, fax_freq, 102);
389 #ifdef OLD_DSP_ROUTINES
390 /* Same for the fax dector 2nd harmonic */
391 goertzel_init (&s->fax_tone2nd, fax_freq * 2.0, 102);
392 #endif
393 #endif /* FAX_DETECT */
394 s->current_sample = 0;
395 s->detected_digits = 0;
396 s->current_digits = 0;
397 memset(&s->digits, 0, sizeof(s->digits));
398 s->lost_digits = 0;
399 s->digits[0] = '\0';
402 static void ast_mf_detect_init (mf_detect_state_t *s)
404 int i;
405 #ifdef OLD_DSP_ROUTINES
406 s->hit1 =
407 s->hit2 = 0;
408 #else
409 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
410 #endif
411 for (i = 0; i < 6; i++) {
412 goertzel_init (&s->tone_out[i], mf_tones[i], 160);
413 #ifdef OLD_DSP_ROUTINES
414 goertzel_init (&s->tone_out2nd[i], mf_tones[i] * 2.0, 160);
415 s->energy = 0.0;
416 #endif
418 s->current_digits = 0;
419 memset(&s->digits, 0, sizeof(s->digits));
420 s->current_sample = 0;
421 s->detected_digits = 0;
422 s->lost_digits = 0;
423 s->digits[0] = '\0';
424 s->mhit = 0;
427 static int dtmf_detect (dtmf_detect_state_t *s, int16_t amp[], int samples,
428 int digitmode, int *writeback, int faxdetect)
430 float row_energy[4];
431 float col_energy[4];
432 #ifdef FAX_DETECT
433 float fax_energy;
434 #ifdef OLD_DSP_ROUTINES
435 float fax_energy_2nd;
436 #endif
437 #endif /* FAX_DETECT */
438 float famp;
439 float v1;
440 int i;
441 int j;
442 int sample;
443 int best_row;
444 int best_col;
445 int hit;
446 int limit;
448 hit = 0;
449 for (sample = 0; sample < samples; sample = limit) {
450 /* 102 is optimised to meet the DTMF specs. */
451 if ((samples - sample) >= (102 - s->current_sample))
452 limit = sample + (102 - s->current_sample);
453 else
454 limit = samples;
455 #if defined(USE_3DNOW)
456 _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample);
457 _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample);
458 #ifdef OLD_DSP_ROUTINES
459 _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample);
460 _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample);
461 #endif
462 /* XXX Need to fax detect for 3dnow too XXX */
463 #warning "Fax Support Broken"
464 #else
465 /* The following unrolled loop takes only 35% (rough estimate) of the
466 time of a rolled loop on the machine on which it was developed */
467 for (j=sample;j<limit;j++) {
468 famp = amp[j];
469 s->energy += famp*famp;
470 /* With GCC 2.95, the following unrolled code seems to take about 35%
471 (rough estimate) as long as a neat little 0-3 loop */
472 v1 = s->row_out[0].v2;
473 s->row_out[0].v2 = s->row_out[0].v3;
474 s->row_out[0].v3 = s->row_out[0].fac*s->row_out[0].v2 - v1 + famp;
475 v1 = s->col_out[0].v2;
476 s->col_out[0].v2 = s->col_out[0].v3;
477 s->col_out[0].v3 = s->col_out[0].fac*s->col_out[0].v2 - v1 + famp;
478 v1 = s->row_out[1].v2;
479 s->row_out[1].v2 = s->row_out[1].v3;
480 s->row_out[1].v3 = s->row_out[1].fac*s->row_out[1].v2 - v1 + famp;
481 v1 = s->col_out[1].v2;
482 s->col_out[1].v2 = s->col_out[1].v3;
483 s->col_out[1].v3 = s->col_out[1].fac*s->col_out[1].v2 - v1 + famp;
484 v1 = s->row_out[2].v2;
485 s->row_out[2].v2 = s->row_out[2].v3;
486 s->row_out[2].v3 = s->row_out[2].fac*s->row_out[2].v2 - v1 + famp;
487 v1 = s->col_out[2].v2;
488 s->col_out[2].v2 = s->col_out[2].v3;
489 s->col_out[2].v3 = s->col_out[2].fac*s->col_out[2].v2 - v1 + famp;
490 v1 = s->row_out[3].v2;
491 s->row_out[3].v2 = s->row_out[3].v3;
492 s->row_out[3].v3 = s->row_out[3].fac*s->row_out[3].v2 - v1 + famp;
493 v1 = s->col_out[3].v2;
494 s->col_out[3].v2 = s->col_out[3].v3;
495 s->col_out[3].v3 = s->col_out[3].fac*s->col_out[3].v2 - v1 + famp;
496 #ifdef FAX_DETECT
497 /* Update fax tone */
498 v1 = s->fax_tone.v2;
499 s->fax_tone.v2 = s->fax_tone.v3;
500 s->fax_tone.v3 = s->fax_tone.fac*s->fax_tone.v2 - v1 + famp;
501 #endif /* FAX_DETECT */
502 #ifdef OLD_DSP_ROUTINES
503 v1 = s->col_out2nd[0].v2;
504 s->col_out2nd[0].v2 = s->col_out2nd[0].v3;
505 s->col_out2nd[0].v3 = s->col_out2nd[0].fac*s->col_out2nd[0].v2 - v1 + famp;
506 v1 = s->row_out2nd[0].v2;
507 s->row_out2nd[0].v2 = s->row_out2nd[0].v3;
508 s->row_out2nd[0].v3 = s->row_out2nd[0].fac*s->row_out2nd[0].v2 - v1 + famp;
509 v1 = s->col_out2nd[1].v2;
510 s->col_out2nd[1].v2 = s->col_out2nd[1].v3;
511 s->col_out2nd[1].v3 = s->col_out2nd[1].fac*s->col_out2nd[1].v2 - v1 + famp;
512 v1 = s->row_out2nd[1].v2;
513 s->row_out2nd[1].v2 = s->row_out2nd[1].v3;
514 s->row_out2nd[1].v3 = s->row_out2nd[1].fac*s->row_out2nd[1].v2 - v1 + famp;
515 v1 = s->col_out2nd[2].v2;
516 s->col_out2nd[2].v2 = s->col_out2nd[2].v3;
517 s->col_out2nd[2].v3 = s->col_out2nd[2].fac*s->col_out2nd[2].v2 - v1 + famp;
518 v1 = s->row_out2nd[2].v2;
519 s->row_out2nd[2].v2 = s->row_out2nd[2].v3;
520 s->row_out2nd[2].v3 = s->row_out2nd[2].fac*s->row_out2nd[2].v2 - v1 + famp;
521 v1 = s->col_out2nd[3].v2;
522 s->col_out2nd[3].v2 = s->col_out2nd[3].v3;
523 s->col_out2nd[3].v3 = s->col_out2nd[3].fac*s->col_out2nd[3].v2 - v1 + famp;
524 v1 = s->row_out2nd[3].v2;
525 s->row_out2nd[3].v2 = s->row_out2nd[3].v3;
526 s->row_out2nd[3].v3 = s->row_out2nd[3].fac*s->row_out2nd[3].v2 - v1 + famp;
527 #ifdef FAX_DETECT
528 /* Update fax tone */
529 v1 = s->fax_tone.v2;
530 s->fax_tone2nd.v2 = s->fax_tone2nd.v3;
531 s->fax_tone2nd.v3 = s->fax_tone2nd.fac*s->fax_tone2nd.v2 - v1 + famp;
532 #endif /* FAX_DETECT */
533 #endif
535 #endif
536 s->current_sample += (limit - sample);
537 if (s->current_sample < 102) {
538 if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) {
539 /* If we had a hit last time, go ahead and clear this out since likely it
540 will be another hit */
541 for (i=sample;i<limit;i++)
542 amp[i] = 0;
543 *writeback = 1;
545 continue;
547 #ifdef FAX_DETECT
548 /* Detect the fax energy, too */
549 fax_energy = goertzel_result(&s->fax_tone);
550 #endif
551 /* We are at the end of a DTMF detection block */
552 /* Find the peak row and the peak column */
553 row_energy[0] = goertzel_result (&s->row_out[0]);
554 col_energy[0] = goertzel_result (&s->col_out[0]);
556 for (best_row = best_col = 0, i = 1; i < 4; i++) {
557 row_energy[i] = goertzel_result (&s->row_out[i]);
558 if (row_energy[i] > row_energy[best_row])
559 best_row = i;
560 col_energy[i] = goertzel_result (&s->col_out[i]);
561 if (col_energy[i] > col_energy[best_col])
562 best_col = i;
564 hit = 0;
565 /* Basic signal level test and the twist test */
566 if (row_energy[best_row] >= DTMF_THRESHOLD &&
567 col_energy[best_col] >= DTMF_THRESHOLD &&
568 col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST &&
569 col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) {
570 /* Relative peak test */
571 for (i = 0; i < 4; i++) {
572 if ((i != best_col &&
573 col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
574 (i != best_row
575 && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
576 break;
579 #ifdef OLD_DSP_ROUTINES
580 /* ... and second harmonic test */
581 if (i >= 4 &&
582 (row_energy[best_row] + col_energy[best_col]) > 42.0*s->energy &&
583 goertzel_result(&s->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col]
584 && goertzel_result(&s->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) {
585 #else
586 /* ... and fraction of total energy test */
587 if (i >= 4 &&
588 (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->energy) {
589 #endif
590 /* Got a hit */
591 hit = dtmf_positions[(best_row << 2) + best_col];
592 if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) {
593 /* Zero out frame data if this is part DTMF */
594 for (i=sample;i<limit;i++)
595 amp[i] = 0;
596 *writeback = 1;
598 #ifdef OLD_DSP_ROUTINES
599 /* Look for two successive similar results */
600 /* The logic in the next test is:
601 We need two successive identical clean detects, with
602 something different preceeding it. This can work with
603 back to back differing digits. More importantly, it
604 can work with nasty phones that give a very wobbly start
605 to a digit */
606 if (hit == s->hit3 && s->hit3 != s->hit2) {
607 s->mhit = hit;
608 s->digit_hits[(best_row << 2) + best_col]++;
609 s->detected_digits++;
610 if (s->current_digits < MAX_DTMF_DIGITS) {
611 s->digits[s->current_digits++] = hit;
612 s->digits[s->current_digits] = '\0';
613 } else {
614 s->lost_digits++;
617 #endif
621 #ifndef OLD_DSP_ROUTINES
622 /* Look for two successive similar results */
623 /* The logic in the next test is:
624 We need two successive identical clean detects, with
625 something different preceeding it. This can work with
626 back to back differing digits. More importantly, it
627 can work with nasty phones that give a very wobbly start
628 to a digit */
629 if (hit == s->lasthit && hit != s->mhit) {
630 if (hit) {
631 s->digit_hits[(best_row << 2) + best_col]++;
632 s->detected_digits++;
633 if (s->current_digits < MAX_DTMF_DIGITS) {
634 s->digits[s->current_digits++] = hit;
635 s->digits[s->current_digits] = '\0';
636 } else {
637 s->lost_digits++;
640 s->mhit = hit;
642 #endif
644 #ifdef FAX_DETECT
645 if (!hit && (fax_energy >= FAX_THRESHOLD) &&
646 (fax_energy >= DTMF_TO_TOTAL_ENERGY*s->energy) &&
647 (faxdetect)) {
648 #if 0
649 printf("Fax energy/Second Harmonic: %f\n", fax_energy);
650 #endif
651 /* XXX Probably need better checking than just this the energy XXX */
652 hit = 'f';
653 s->fax_hits++;
654 } else {
655 if (s->fax_hits > 5) {
656 hit = 'f';
657 s->mhit = 'f';
658 s->detected_digits++;
659 if (s->current_digits < MAX_DTMF_DIGITS) {
660 s->digits[s->current_digits++] = hit;
661 s->digits[s->current_digits] = '\0';
662 } else {
663 s->lost_digits++;
666 s->fax_hits = 0;
668 #endif /* FAX_DETECT */
669 #ifdef OLD_DSP_ROUTINES
670 s->hit1 = s->hit2;
671 s->hit2 = s->hit3;
672 s->hit3 = hit;
673 #else
674 s->lasthit = hit;
675 #endif
676 /* Reinitialise the detector for the next block */
677 for (i = 0; i < 4; i++) {
678 goertzel_reset(&s->row_out[i]);
679 goertzel_reset(&s->col_out[i]);
680 #ifdef OLD_DSP_ROUTINES
681 goertzel_reset(&s->row_out2nd[i]);
682 goertzel_reset(&s->col_out2nd[i]);
683 #endif
685 #ifdef FAX_DETECT
686 goertzel_reset (&s->fax_tone);
687 #ifdef OLD_DSP_ROUTINES
688 goertzel_reset (&s->fax_tone2nd);
689 #endif
690 #endif
691 s->energy = 0.0;
692 s->current_sample = 0;
694 #ifdef OLD_DSP_ROUTINES
695 if ((!s->mhit) || (s->mhit != hit)) {
696 s->mhit = 0;
697 return(0);
699 return (hit);
700 #else
701 return (s->mhit); /* return the debounced hit */
702 #endif
705 /* MF goertzel size */
706 #ifdef OLD_DSP_ROUTINES
707 #define MF_GSIZE 160
708 #else
709 #define MF_GSIZE 120
710 #endif
712 static int mf_detect (mf_detect_state_t *s, int16_t amp[],
713 int samples, int digitmode, int *writeback)
715 #ifdef OLD_DSP_ROUTINES
716 float tone_energy[6];
717 int best1;
718 int best2;
719 float max;
720 int sofarsogood;
721 #else
722 float energy[6];
723 int best;
724 int second_best;
725 #endif
726 float famp;
727 float v1;
728 int i;
729 int j;
730 int sample;
731 int hit;
732 int limit;
734 hit = 0;
735 for (sample = 0; sample < samples; sample = limit) {
736 /* 80 is optimised to meet the MF specs. */
737 if ((samples - sample) >= (MF_GSIZE - s->current_sample))
738 limit = sample + (MF_GSIZE - s->current_sample);
739 else
740 limit = samples;
741 #if defined(USE_3DNOW)
742 _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample);
743 _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample);
744 #ifdef OLD_DSP_ROUTINES
745 _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample);
746 _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample);
747 #endif
748 /* XXX Need to fax detect for 3dnow too XXX */
749 #warning "Fax Support Broken"
750 #else
751 /* The following unrolled loop takes only 35% (rough estimate) of the
752 time of a rolled loop on the machine on which it was developed */
753 for (j = sample; j < limit; j++) {
754 famp = amp[j];
755 #ifdef OLD_DSP_ROUTINES
756 s->energy += famp*famp;
757 #endif
758 /* With GCC 2.95, the following unrolled code seems to take about 35%
759 (rough estimate) as long as a neat little 0-3 loop */
760 v1 = s->tone_out[0].v2;
761 s->tone_out[0].v2 = s->tone_out[0].v3;
762 s->tone_out[0].v3 = s->tone_out[0].fac*s->tone_out[0].v2 - v1 + famp;
763 v1 = s->tone_out[1].v2;
764 s->tone_out[1].v2 = s->tone_out[1].v3;
765 s->tone_out[1].v3 = s->tone_out[1].fac*s->tone_out[1].v2 - v1 + famp;
766 v1 = s->tone_out[2].v2;
767 s->tone_out[2].v2 = s->tone_out[2].v3;
768 s->tone_out[2].v3 = s->tone_out[2].fac*s->tone_out[2].v2 - v1 + famp;
769 v1 = s->tone_out[3].v2;
770 s->tone_out[3].v2 = s->tone_out[3].v3;
771 s->tone_out[3].v3 = s->tone_out[3].fac*s->tone_out[3].v2 - v1 + famp;
772 v1 = s->tone_out[4].v2;
773 s->tone_out[4].v2 = s->tone_out[4].v3;
774 s->tone_out[4].v3 = s->tone_out[4].fac*s->tone_out[4].v2 - v1 + famp;
775 v1 = s->tone_out[5].v2;
776 s->tone_out[5].v2 = s->tone_out[5].v3;
777 s->tone_out[5].v3 = s->tone_out[5].fac*s->tone_out[5].v2 - v1 + famp;
778 #ifdef OLD_DSP_ROUTINES
779 v1 = s->tone_out2nd[0].v2;
780 s->tone_out2nd[0].v2 = s->tone_out2nd[0].v3;
781 s->tone_out2nd[0].v3 = s->tone_out2nd[0].fac*s->tone_out2nd[0].v2 - v1 + famp;
782 v1 = s->tone_out2nd[1].v2;
783 s->tone_out2nd[1].v2 = s->tone_out2nd[1].v3;
784 s->tone_out2nd[1].v3 = s->tone_out2nd[1].fac*s->tone_out2nd[1].v2 - v1 + famp;
785 v1 = s->tone_out2nd[2].v2;
786 s->tone_out2nd[2].v2 = s->tone_out2nd[2].v3;
787 s->tone_out2nd[2].v3 = s->tone_out2nd[2].fac*s->tone_out2nd[2].v2 - v1 + famp;
788 v1 = s->tone_out2nd[3].v2;
789 s->tone_out2nd[3].v2 = s->tone_out2nd[3].v3;
790 s->tone_out2nd[3].v3 = s->tone_out2nd[3].fac*s->tone_out2nd[3].v2 - v1 + famp;
791 v1 = s->tone_out2nd[4].v2;
792 s->tone_out2nd[4].v2 = s->tone_out2nd[4].v3;
793 s->tone_out2nd[4].v3 = s->tone_out2nd[4].fac*s->tone_out2nd[2].v2 - v1 + famp;
794 v1 = s->tone_out2nd[3].v2;
795 s->tone_out2nd[5].v2 = s->tone_out2nd[6].v3;
796 s->tone_out2nd[5].v3 = s->tone_out2nd[6].fac*s->tone_out2nd[3].v2 - v1 + famp;
797 #endif
799 #endif
800 s->current_sample += (limit - sample);
801 if (s->current_sample < MF_GSIZE) {
802 if (hit && !((digitmode & DSP_DIGITMODE_NOQUELCH))) {
803 /* If we had a hit last time, go ahead and clear this out since likely it
804 will be another hit */
805 for (i=sample;i<limit;i++)
806 amp[i] = 0;
807 *writeback = 1;
809 continue;
811 #ifdef OLD_DSP_ROUTINES
812 /* We're at the end of an MF detection block. Go ahead and calculate
813 all the energies. */
814 for (i=0;i<6;i++) {
815 tone_energy[i] = goertzel_result(&s->tone_out[i]);
817 /* Find highest */
818 best1 = 0;
819 max = tone_energy[0];
820 for (i=1;i<6;i++) {
821 if (tone_energy[i] > max) {
822 max = tone_energy[i];
823 best1 = i;
827 /* Find 2nd highest */
828 if (best1) {
829 max = tone_energy[0];
830 best2 = 0;
831 } else {
832 max = tone_energy[1];
833 best2 = 1;
836 for (i=0;i<6;i++) {
837 if (i == best1) continue;
838 if (tone_energy[i] > max) {
839 max = tone_energy[i];
840 best2 = i;
843 hit = 0;
844 if (best1 != best2)
845 sofarsogood=1;
846 else
847 sofarsogood=0;
848 /* Check for relative energies */
849 for (i=0;i<6;i++) {
850 if (i == best1)
851 continue;
852 if (i == best2)
853 continue;
854 if (tone_energy[best1] < tone_energy[i] * MF_RELATIVE_PEAK) {
855 sofarsogood = 0;
856 break;
858 if (tone_energy[best2] < tone_energy[i] * MF_RELATIVE_PEAK) {
859 sofarsogood = 0;
860 break;
864 if (sofarsogood) {
865 /* Check for 2nd harmonic */
866 if (goertzel_result(&s->tone_out2nd[best1]) * MF_2ND_HARMONIC > tone_energy[best1])
867 sofarsogood = 0;
868 else if (goertzel_result(&s->tone_out2nd[best2]) * MF_2ND_HARMONIC > tone_energy[best2])
869 sofarsogood = 0;
871 if (sofarsogood) {
872 hit = mf_hit[best1][best2];
873 if (!(digitmode & DSP_DIGITMODE_NOQUELCH)) {
874 /* Zero out frame data if this is part DTMF */
875 for (i=sample;i<limit;i++)
876 amp[i] = 0;
877 *writeback = 1;
879 /* Look for two consecutive clean hits */
880 if ((hit == s->hit3) && (s->hit3 != s->hit2)) {
881 s->mhit = hit;
882 s->detected_digits++;
883 if (s->current_digits < MAX_DTMF_DIGITS - 2) {
884 s->digits[s->current_digits++] = hit;
885 s->digits[s->current_digits] = '\0';
886 } else {
887 s->lost_digits++;
892 s->hit1 = s->hit2;
893 s->hit2 = s->hit3;
894 s->hit3 = hit;
895 /* Reinitialise the detector for the next block */
896 for (i = 0; i < 6; i++) {
897 goertzel_reset(&s->tone_out[i]);
898 goertzel_reset(&s->tone_out2nd[i]);
900 s->energy = 0.0;
901 s->current_sample = 0;
903 #else
904 /* We're at the end of an MF detection block. */
905 /* Find the two highest energies. The spec says to look for
906 two tones and two tones only. Taking this literally -ie
907 only two tones pass the minimum threshold - doesn't work
908 well. The sinc function mess, due to rectangular windowing
909 ensure that! Find the two highest energies and ensure they
910 are considerably stronger than any of the others. */
911 energy[0] = goertzel_result(&s->tone_out[0]);
912 energy[1] = goertzel_result(&s->tone_out[1]);
913 if (energy[0] > energy[1]) {
914 best = 0;
915 second_best = 1;
916 } else {
917 best = 1;
918 second_best = 0;
920 /*endif*/
921 for (i=2;i<6;i++) {
922 energy[i] = goertzel_result(&s->tone_out[i]);
923 if (energy[i] >= energy[best]) {
924 second_best = best;
925 best = i;
926 } else if (energy[i] >= energy[second_best]) {
927 second_best = i;
930 /* Basic signal level and twist tests */
931 hit = 0;
932 if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD
933 && energy[best] < energy[second_best]*BELL_MF_TWIST
934 && energy[best]*BELL_MF_TWIST > energy[second_best]) {
935 /* Relative peak test */
936 hit = -1;
937 for (i=0;i<6;i++) {
938 if (i != best && i != second_best) {
939 if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) {
940 /* The best two are not clearly the best */
941 hit = 0;
942 break;
947 if (hit) {
948 /* Get the values into ascending order */
949 if (second_best < best) {
950 i = best;
951 best = second_best;
952 second_best = i;
954 best = best*5 + second_best - 1;
955 hit = bell_mf_positions[best];
956 /* Look for two successive similar results */
957 /* The logic in the next test is:
958 For KP we need 4 successive identical clean detects, with
959 two blocks of something different preceeding it. For anything
960 else we need two successive identical clean detects, with
961 two blocks of something different preceeding it. */
962 if (hit == s->hits[4] && hit == s->hits[3] &&
963 ((hit != '*' && hit != s->hits[2] && hit != s->hits[1])||
964 (hit == '*' && hit == s->hits[2] && hit != s->hits[1] &&
965 hit != s->hits[0]))) {
966 s->detected_digits++;
967 if (s->current_digits < MAX_DTMF_DIGITS) {
968 s->digits[s->current_digits++] = hit;
969 s->digits[s->current_digits] = '\0';
970 } else {
971 s->lost_digits++;
974 } else {
975 hit = 0;
977 s->hits[0] = s->hits[1];
978 s->hits[1] = s->hits[2];
979 s->hits[2] = s->hits[3];
980 s->hits[3] = s->hits[4];
981 s->hits[4] = hit;
982 /* Reinitialise the detector for the next block */
983 for (i = 0; i < 6; i++)
984 goertzel_reset(&s->tone_out[i]);
985 s->current_sample = 0;
987 #endif
988 if ((!s->mhit) || (s->mhit != hit)) {
989 s->mhit = 0;
990 return(0);
992 return (hit);
995 static int __ast_dsp_digitdetect(struct ast_dsp *dsp, short *s, int len, int *writeback)
997 int res;
999 if (dsp->digitmode & DSP_DIGITMODE_MF)
1000 res = mf_detect(&dsp->td.mf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback);
1001 else
1002 res = dtmf_detect(&dsp->td.dtmf, s, len, dsp->digitmode & DSP_DIGITMODE_RELAXDTMF, writeback, dsp->features & DSP_FEATURE_FAX_DETECT);
1003 return res;
1006 int ast_dsp_digitdetect(struct ast_dsp *dsp, struct ast_frame *inf)
1008 short *s;
1009 int len;
1010 int ign=0;
1012 if (inf->frametype != AST_FRAME_VOICE) {
1013 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
1014 return 0;
1016 if (inf->subclass != AST_FORMAT_SLINEAR) {
1017 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
1018 return 0;
1020 s = inf->data;
1021 len = inf->datalen / 2;
1022 return __ast_dsp_digitdetect(dsp, s, len, &ign);
1025 static inline int pair_there(float p1, float p2, float i1, float i2, float e)
1027 /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
1028 /* Make sure absolute levels are high enough */
1029 if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH))
1030 return 0;
1031 /* Amplify ignored stuff */
1032 i2 *= TONE_THRESH;
1033 i1 *= TONE_THRESH;
1034 e *= TONE_THRESH;
1035 /* Check first tone */
1036 if ((p1 < i1) || (p1 < i2) || (p1 < e))
1037 return 0;
1038 /* And second */
1039 if ((p2 < i1) || (p2 < i2) || (p2 < e))
1040 return 0;
1041 /* Guess it's there... */
1042 return 1;
1045 int ast_dsp_getdigits (struct ast_dsp *dsp, char *buf, int max)
1047 if (dsp->digitmode & DSP_DIGITMODE_MF) {
1048 if (max > dsp->td.mf.current_digits)
1049 max = dsp->td.mf.current_digits;
1050 if (max > 0) {
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;
1055 buf[max] = '\0';
1056 return max;
1057 } else {
1058 if (max > dsp->td.dtmf.current_digits)
1059 max = dsp->td.dtmf.current_digits;
1060 if (max > 0) {
1061 memcpy (buf, dsp->td.dtmf.digits, max);
1062 memmove (dsp->td.dtmf.digits, dsp->td.dtmf.digits + max, dsp->td.dtmf.current_digits - max);
1063 dsp->td.dtmf.current_digits -= max;
1065 buf[max] = '\0';
1066 return max;
1070 static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len)
1072 int x;
1073 int y;
1074 int pass;
1075 int newstate = DSP_TONE_STATE_SILENCE;
1076 int res = 0;
1077 while(len) {
1078 /* Take the lesser of the number of samples we need and what we have */
1079 pass = len;
1080 if (pass > dsp->gsamp_size - dsp->gsamps)
1081 pass = dsp->gsamp_size - dsp->gsamps;
1082 for (x=0;x<pass;x++) {
1083 for (y=0;y<dsp->freqcount;y++)
1084 goertzel_sample(&dsp->freqs[y], s[x]);
1085 dsp->genergy += s[x] * s[x];
1087 s += pass;
1088 dsp->gsamps += pass;
1089 len -= pass;
1090 if (dsp->gsamps == dsp->gsamp_size) {
1091 float hz[7];
1092 for (y=0;y<7;y++)
1093 hz[y] = goertzel_result(&dsp->freqs[y]);
1094 #if 0
1095 printf("\n350: 425: 440: 480: 620: 950: 1400: 1800: Energy: \n");
1096 printf("%.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e %.2e\n",
1097 hz[HZ_350], hz[HZ_425], hz[HZ_440], hz[HZ_480], hz[HZ_620], hz[HZ_950], hz[HZ_1400], hz[HZ_1800], dsp->genergy);
1098 #endif
1099 switch(dsp->progmode) {
1100 case PROG_MODE_NA:
1101 if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) {
1102 newstate = DSP_TONE_STATE_BUSY;
1103 } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
1104 newstate = DSP_TONE_STATE_RINGING;
1105 } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
1106 newstate = DSP_TONE_STATE_DIALTONE;
1107 } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) {
1108 newstate = DSP_TONE_STATE_SPECIAL1;
1109 } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) {
1110 if (dsp->tstate == DSP_TONE_STATE_SPECIAL1)
1111 newstate = DSP_TONE_STATE_SPECIAL2;
1112 } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) {
1113 if (dsp->tstate == DSP_TONE_STATE_SPECIAL2)
1114 newstate = DSP_TONE_STATE_SPECIAL3;
1115 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
1116 newstate = DSP_TONE_STATE_TALKING;
1117 } else
1118 newstate = DSP_TONE_STATE_SILENCE;
1119 break;
1120 case PROG_MODE_CR:
1121 if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) {
1122 newstate = DSP_TONE_STATE_RINGING;
1123 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
1124 newstate = DSP_TONE_STATE_TALKING;
1125 } else
1126 newstate = DSP_TONE_STATE_SILENCE;
1127 break;
1128 case PROG_MODE_UK:
1129 if (hz[HZ_400] > TONE_MIN_THRESH * TONE_THRESH) {
1130 newstate = DSP_TONE_STATE_HUNGUP;
1132 break;
1133 default:
1134 ast_log(LOG_WARNING, "Can't process in unknown prog mode '%d'\n", dsp->progmode);
1136 if (newstate == dsp->tstate) {
1137 dsp->tcount++;
1138 if (dsp->ringtimeout)
1139 dsp->ringtimeout++;
1140 switch (dsp->tstate) {
1141 case DSP_TONE_STATE_RINGING:
1142 if ((dsp->features & DSP_PROGRESS_RINGING) &&
1143 (dsp->tcount==THRESH_RING)) {
1144 res = AST_CONTROL_RINGING;
1145 dsp->ringtimeout= 1;
1147 break;
1148 case DSP_TONE_STATE_BUSY:
1149 if ((dsp->features & DSP_PROGRESS_BUSY) &&
1150 (dsp->tcount==THRESH_BUSY)) {
1151 res = AST_CONTROL_BUSY;
1152 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1154 break;
1155 case DSP_TONE_STATE_TALKING:
1156 if ((dsp->features & DSP_PROGRESS_TALK) &&
1157 (dsp->tcount==THRESH_TALK)) {
1158 res = AST_CONTROL_ANSWER;
1159 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1161 break;
1162 case DSP_TONE_STATE_SPECIAL3:
1163 if ((dsp->features & DSP_PROGRESS_CONGESTION) &&
1164 (dsp->tcount==THRESH_CONGESTION)) {
1165 res = AST_CONTROL_CONGESTION;
1166 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1168 break;
1169 case DSP_TONE_STATE_HUNGUP:
1170 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
1171 (dsp->tcount==THRESH_HANGUP)) {
1172 res = AST_CONTROL_HANGUP;
1173 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1175 break;
1177 if (dsp->ringtimeout==THRESH_RING2ANSWER) {
1178 #if 0
1179 ast_log(LOG_NOTICE, "Consider call as answered because of timeout after last ring\n");
1180 #endif
1181 res = AST_CONTROL_ANSWER;
1182 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1184 } else {
1185 #if 0
1186 ast_log(LOG_NOTICE, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount);
1187 ast_log(LOG_NOTICE, "Start state %d\n", newstate);
1188 #endif
1189 dsp->tstate = newstate;
1190 dsp->tcount = 1;
1193 /* Reset goertzel */
1194 for (x=0;x<7;x++)
1195 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
1196 dsp->gsamps = 0;
1197 dsp->genergy = 0.0;
1200 #if 0
1201 if (res)
1202 printf("Returning %d\n", res);
1203 #endif
1204 return res;
1207 int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf)
1209 if (inf->frametype != AST_FRAME_VOICE) {
1210 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
1211 return 0;
1213 if (inf->subclass != AST_FORMAT_SLINEAR) {
1214 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames\n");
1215 return 0;
1217 return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2);
1220 static int __ast_dsp_silence(struct ast_dsp *dsp, short *s, int len, int *totalsilence)
1222 int accum;
1223 int x;
1224 int res = 0;
1226 if (!len)
1227 return 0;
1228 accum = 0;
1229 for (x=0;x<len; x++)
1230 accum += abs(s[x]);
1231 accum /= len;
1232 if (accum < dsp->threshold) {
1233 /* Silent */
1234 dsp->totalsilence += len/8;
1235 if (dsp->totalnoise) {
1236 /* Move and save history */
1237 memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount +1, dsp->busycount*sizeof(dsp->historicnoise[0]));
1238 dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
1239 /* we don't want to check for busydetect that frequently */
1240 #if 0
1241 dsp->busymaybe = 1;
1242 #endif
1244 dsp->totalnoise = 0;
1245 res = 1;
1246 } else {
1247 /* Not silent */
1248 dsp->totalnoise += len/8;
1249 if (dsp->totalsilence) {
1250 int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
1251 int silence2 = dsp->historicsilence[DSP_HISTORY - 2];
1252 /* Move and save history */
1253 memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount*sizeof(dsp->historicsilence[0]));
1254 dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
1255 /* check if the previous sample differs only by BUSY_PERCENT from the one before it */
1256 if (silence1 < silence2) {
1257 if (silence1 + silence1*BUSY_PERCENT/100 >= silence2)
1258 dsp->busymaybe = 1;
1259 else
1260 dsp->busymaybe = 0;
1261 } else {
1262 if (silence1 - silence1*BUSY_PERCENT/100 <= silence2)
1263 dsp->busymaybe = 1;
1264 else
1265 dsp->busymaybe = 0;
1268 dsp->totalsilence = 0;
1270 if (totalsilence)
1271 *totalsilence = dsp->totalsilence;
1272 return res;
1275 #ifdef BUSYDETECT_MARTIN
1276 int ast_dsp_busydetect(struct ast_dsp *dsp)
1278 int res = 0, x;
1279 #ifndef BUSYDETECT_TONEONLY
1280 int avgsilence = 0, hitsilence = 0;
1281 #endif
1282 int avgtone = 0, hittone = 0;
1283 if (!dsp->busymaybe)
1284 return res;
1285 for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
1286 #ifndef BUSYDETECT_TONEONLY
1287 avgsilence += dsp->historicsilence[x];
1288 #endif
1289 avgtone += dsp->historicnoise[x];
1291 #ifndef BUSYDETECT_TONEONLY
1292 avgsilence /= dsp->busycount;
1293 #endif
1294 avgtone /= dsp->busycount;
1295 for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
1296 #ifndef BUSYDETECT_TONEONLY
1297 if (avgsilence > dsp->historicsilence[x]) {
1298 if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
1299 hitsilence++;
1300 } else {
1301 if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
1302 hitsilence++;
1304 #endif
1305 if (avgtone > dsp->historicnoise[x]) {
1306 if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x])
1307 hittone++;
1308 } else {
1309 if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x])
1310 hittone++;
1313 #ifndef BUSYDETECT_TONEONLY
1314 if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) &&
1315 (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) &&
1316 (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) {
1317 #else
1318 if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
1319 #endif
1320 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
1321 #ifdef BUSYDETECT_TONEONLY
1322 #error You cant use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE
1323 #endif
1324 if (avgtone > avgsilence) {
1325 if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
1326 res = 1;
1327 } else {
1328 if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
1329 res = 1;
1331 #else
1332 res = 1;
1333 #endif
1335 /* If we know the expected busy tone length, check we are in the range */
1336 if (res && (dsp->busy_tonelength > 0)) {
1337 if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) {
1338 #if 0
1339 ast_log(LOG_NOTICE, "busy detector: avgtone of %d not close enough to desired %d\n",
1340 avgtone, dsp->busy_tonelength);
1341 #endif
1342 res = 0;
1345 #ifndef BUSYDETECT_TONEONLY
1346 /* If we know the expected busy tone silent-period length, check we are in the range */
1347 if (res && (dsp->busy_quietlength > 0)) {
1348 if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) {
1349 #if 0
1350 ast_log(LOG_NOTICE, "busy detector: avgsilence of %d not close enough to desired %d\n",
1351 avgsilence, dsp->busy_quietlength);
1352 #endif
1353 res = 0;
1356 #endif
1357 #ifndef BUSYDETECT_TONEONLY
1358 #if 1
1359 if (res)
1360 ast_log(LOG_DEBUG, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
1361 #endif
1362 #endif
1363 return res;
1365 #endif
1367 #ifdef BUSYDETECT
1368 int ast_dsp_busydetect(struct ast_dsp *dsp)
1370 int x;
1371 int res = 0;
1372 int max, min;
1374 #if 0
1375 if (dsp->busy_hits > 5);
1376 return 0;
1377 #endif
1378 if (dsp->busymaybe) {
1379 #if 0
1380 printf("Maybe busy!\n");
1381 #endif
1382 dsp->busymaybe = 0;
1383 min = 9999;
1384 max = 0;
1385 for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
1386 #if 0
1387 printf("Silence: %d, Noise: %d\n", dsp->historicsilence[x], dsp->historicnoise[x]);
1388 #endif
1389 if (dsp->historicsilence[x] < min)
1390 min = dsp->historicsilence[x];
1391 if (dsp->historicnoise[x] < min)
1392 min = dsp->historicnoise[x];
1393 if (dsp->historicsilence[x] > max)
1394 max = dsp->historicsilence[x];
1395 if (dsp->historicnoise[x] > max)
1396 max = dsp->historicnoise[x];
1398 if ((max - min < BUSY_THRESHOLD) && (max < BUSY_MAX) && (min > BUSY_MIN)) {
1399 #if 0
1400 printf("Busy!\n");
1401 #endif
1402 res = 1;
1404 #if 0
1405 printf("Min: %d, max: %d\n", min, max);
1406 #endif
1408 return res;
1410 #endif
1412 int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
1414 short *s;
1415 int len;
1417 if (f->frametype != AST_FRAME_VOICE) {
1418 ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
1419 return 0;
1421 if (f->subclass != AST_FORMAT_SLINEAR) {
1422 ast_log(LOG_WARNING, "Can only calculate silence on signed-linear frames :(\n");
1423 return 0;
1425 s = f->data;
1426 len = f->datalen/2;
1427 return __ast_dsp_silence(dsp, s, len, totalsilence);
1430 struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af)
1432 int silence;
1433 int res;
1434 int digit;
1435 int x;
1436 short *shortdata;
1437 unsigned char *odata;
1438 int len;
1439 int writeback = 0;
1441 #define FIX_INF(inf) do { \
1442 if (writeback) { \
1443 switch(inf->subclass) { \
1444 case AST_FORMAT_SLINEAR: \
1445 break; \
1446 case AST_FORMAT_ULAW: \
1447 for (x=0;x<len;x++) \
1448 odata[x] = AST_LIN2MU((unsigned short)shortdata[x]); \
1449 break; \
1450 case AST_FORMAT_ALAW: \
1451 for (x=0;x<len;x++) \
1452 odata[x] = AST_LIN2A((unsigned short)shortdata[x]); \
1453 break; \
1456 } while(0)
1458 if (!af)
1459 return NULL;
1460 if (af->frametype != AST_FRAME_VOICE)
1461 return af;
1462 odata = af->data;
1463 len = af->datalen;
1464 /* Make sure we have short data */
1465 switch(af->subclass) {
1466 case AST_FORMAT_SLINEAR:
1467 shortdata = af->data;
1468 len = af->datalen / 2;
1469 break;
1470 case AST_FORMAT_ULAW:
1471 shortdata = alloca(af->datalen * 2);
1472 for (x = 0;x < len; x++)
1473 shortdata[x] = AST_MULAW(odata[x]);
1474 break;
1475 case AST_FORMAT_ALAW:
1476 shortdata = alloca(af->datalen * 2);
1477 for (x = 0; x < len; x++)
1478 shortdata[x] = AST_ALAW(odata[x]);
1479 break;
1480 default:
1481 ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass));
1482 return af;
1484 silence = __ast_dsp_silence(dsp, shortdata, len, NULL);
1485 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
1486 memset(&dsp->f, 0, sizeof(dsp->f));
1487 dsp->f.frametype = AST_FRAME_NULL;
1488 ast_frfree(af);
1489 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
1490 return &dsp->f;
1492 if ((dsp->features & DSP_FEATURE_BUSY_DETECT) && ast_dsp_busydetect(dsp)) {
1493 chan->_softhangup |= AST_SOFTHANGUP_DEV;
1494 memset(&dsp->f, 0, sizeof(dsp->f));
1495 dsp->f.frametype = AST_FRAME_CONTROL;
1496 dsp->f.subclass = AST_CONTROL_BUSY;
1497 ast_frfree(af);
1498 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
1499 return &dsp->f;
1501 if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) {
1502 digit = __ast_dsp_digitdetect(dsp, shortdata, len, &writeback);
1503 #if 0
1504 if (digit)
1505 printf("Performing digit detection returned %d, digitmode is %d\n", digit, dsp->digitmode);
1506 #endif
1507 if (dsp->digitmode & (DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX)) {
1508 if (!dsp->thinkdigit) {
1509 if (digit) {
1510 /* Looks like we might have something.
1511 * Request a conference mute for the moment */
1512 memset(&dsp->f, 0, sizeof(dsp->f));
1513 dsp->f.frametype = AST_FRAME_DTMF;
1514 dsp->f.subclass = 'm';
1515 dsp->thinkdigit = 'x';
1516 FIX_INF(af);
1517 if (chan)
1518 ast_queue_frame(chan, af);
1519 ast_frfree(af);
1520 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
1521 return &dsp->f;
1523 } else {
1524 if (digit) {
1525 /* Thought we saw one last time. Pretty sure we really have now */
1526 if ((dsp->thinkdigit != 'x') && (dsp->thinkdigit != digit)) {
1527 /* If we found a digit, and we're changing digits, go
1528 ahead and send this one, but DON'T stop confmute because
1529 we're detecting something else, too... */
1530 memset(&dsp->f, 0, sizeof(dsp->f));
1531 dsp->f.frametype = AST_FRAME_DTMF_END;
1532 dsp->f.subclass = dsp->thinkdigit;
1533 FIX_INF(af);
1534 if (chan)
1535 ast_queue_frame(chan, af);
1536 ast_frfree(af);
1537 } else {
1538 dsp->thinkdigit = digit;
1539 memset(&dsp->f, 0, sizeof(dsp->f));
1540 dsp->f.frametype = AST_FRAME_DTMF_BEGIN;
1541 dsp->f.subclass = dsp->thinkdigit;
1542 FIX_INF(af);
1543 if (chan)
1544 ast_queue_frame(chan, af);
1545 ast_frfree(af);
1547 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
1548 return &dsp->f;
1549 } else {
1550 memset(&dsp->f, 0, sizeof(dsp->f));
1551 if (dsp->thinkdigit != 'x') {
1552 /* If we found a digit, send it now */
1553 dsp->f.frametype = AST_FRAME_DTMF_END;
1554 dsp->f.subclass = dsp->thinkdigit;
1555 dsp->thinkdigit = 0;
1556 } else {
1557 dsp->f.frametype = AST_FRAME_DTMF;
1558 dsp->f.subclass = 'u';
1559 dsp->thinkdigit = 0;
1561 FIX_INF(af);
1562 if (chan)
1563 ast_queue_frame(chan, af);
1564 ast_frfree(af);
1565 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
1566 return &dsp->f;
1569 } else if (!digit) {
1570 /* Only check when there is *not* a hit... */
1571 if (dsp->digitmode & DSP_DIGITMODE_MF) {
1572 if (dsp->td.mf.current_digits) {
1573 memset(&dsp->f, 0, sizeof(dsp->f));
1574 dsp->f.frametype = AST_FRAME_DTMF;
1575 dsp->f.subclass = dsp->td.mf.digits[0];
1576 memmove(dsp->td.mf.digits, dsp->td.mf.digits + 1, dsp->td.mf.current_digits);
1577 dsp->td.mf.current_digits--;
1578 FIX_INF(af);
1579 if (chan)
1580 ast_queue_frame(chan, af);
1581 ast_frfree(af);
1582 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
1583 return &dsp->f;
1585 } else {
1586 if (dsp->td.dtmf.current_digits) {
1587 memset(&dsp->f, 0, sizeof(dsp->f));
1588 dsp->f.frametype = AST_FRAME_DTMF_END;
1589 dsp->f.subclass = dsp->td.dtmf.digits[0];
1590 memmove(dsp->td.dtmf.digits, dsp->td.dtmf.digits + 1, dsp->td.dtmf.current_digits);
1591 dsp->td.dtmf.current_digits--;
1592 FIX_INF(af);
1593 if (chan)
1594 ast_queue_frame(chan, af);
1595 ast_frfree(af);
1596 ast_set_flag(&dsp->f, AST_FRFLAG_FROM_DSP);
1597 return &dsp->f;
1602 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
1603 res = __ast_dsp_call_progress(dsp, shortdata, len);
1604 if (res) {
1605 switch(res) {
1606 case AST_CONTROL_ANSWER:
1607 case AST_CONTROL_BUSY:
1608 case AST_CONTROL_RINGING:
1609 case AST_CONTROL_CONGESTION:
1610 case AST_CONTROL_HANGUP:
1611 memset(&dsp->f, 0, sizeof(dsp->f));
1612 dsp->f.frametype = AST_FRAME_CONTROL;
1613 dsp->f.subclass = res;
1614 dsp->f.src = "dsp_progress";
1615 if (chan)
1616 ast_queue_frame(chan, &dsp->f);
1617 break;
1618 default:
1619 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
1623 FIX_INF(af);
1624 return af;
1627 static void ast_dsp_prog_reset(struct ast_dsp *dsp)
1629 int max = 0;
1630 int x;
1632 dsp->gsamp_size = modes[dsp->progmode].size;
1633 dsp->gsamps = 0;
1634 for (x=0;x<sizeof(modes[dsp->progmode].freqs) / sizeof(modes[dsp->progmode].freqs[0]);x++) {
1635 if (modes[dsp->progmode].freqs[x]) {
1636 goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);
1637 max = x + 1;
1640 dsp->freqcount = max;
1641 dsp->ringtimeout= 0;
1644 struct ast_dsp *ast_dsp_new(void)
1646 struct ast_dsp *dsp;
1648 if ((dsp = ast_calloc(1, sizeof(*dsp)))) {
1649 dsp->threshold = DEFAULT_THRESHOLD;
1650 dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
1651 dsp->busycount = DSP_HISTORY;
1652 /* Initialize DTMF detector */
1653 ast_dtmf_detect_init(&dsp->td.dtmf);
1654 /* Initialize initial DSP progress detect parameters */
1655 ast_dsp_prog_reset(dsp);
1657 return dsp;
1660 void ast_dsp_set_features(struct ast_dsp *dsp, int features)
1662 dsp->features = features;
1665 void ast_dsp_free(struct ast_dsp *dsp)
1667 if (ast_test_flag(&dsp->f, AST_FRFLAG_FROM_DSP)) {
1668 /* If this flag is still set, that means that the dsp's destruction
1669 * been torn down, while we still have a frame out there being used.
1670 * When ast_frfree() gets called on that frame, this ast_trans_pvt
1671 * will get destroyed, too. */
1673 /* Set the magic hint that this has been requested to be destroyed. */
1674 dsp->freqcount = -1;
1676 return;
1678 free(dsp);
1681 void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
1683 dsp->threshold = threshold;
1686 void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
1688 if (cadences < 4)
1689 cadences = 4;
1690 if (cadences > DSP_HISTORY)
1691 cadences = DSP_HISTORY;
1692 dsp->busycount = cadences;
1695 void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, int tonelength, int quietlength)
1697 dsp->busy_tonelength = tonelength;
1698 dsp->busy_quietlength = quietlength;
1699 ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
1702 void ast_dsp_digitreset(struct ast_dsp *dsp)
1704 int i;
1706 dsp->thinkdigit = 0;
1707 if (dsp->digitmode & DSP_DIGITMODE_MF) {
1708 memset(dsp->td.mf.digits, 0, sizeof(dsp->td.mf.digits));
1709 dsp->td.mf.current_digits = 0;
1710 /* Reinitialise the detector for the next block */
1711 for (i = 0; i < 6; i++) {
1712 goertzel_reset(&dsp->td.mf.tone_out[i]);
1713 #ifdef OLD_DSP_ROUTINES
1714 goertzel_reset(&dsp->td.mf.tone_out2nd[i]);
1715 #endif
1717 #ifdef OLD_DSP_ROUTINES
1718 dsp->td.mf.energy = 0.0;
1719 dsp->td.mf.hit1 = dsp->td.mf.hit2 = dsp->td.mf.hit3 = dsp->td.mf.hit4 = dsp->td.mf.mhit = 0;
1720 #else
1721 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;
1722 #endif
1723 dsp->td.mf.current_sample = 0;
1724 } else {
1725 memset(dsp->td.dtmf.digits, 0, sizeof(dsp->td.dtmf.digits));
1726 dsp->td.dtmf.current_digits = 0;
1727 /* Reinitialise the detector for the next block */
1728 for (i = 0; i < 4; i++) {
1729 goertzel_reset(&dsp->td.dtmf.row_out[i]);
1730 goertzel_reset(&dsp->td.dtmf.col_out[i]);
1731 #ifdef OLD_DSP_ROUTINES
1732 goertzel_reset(&dsp->td.dtmf.row_out2nd[i]);
1733 goertzel_reset(&dsp->td.dtmf.col_out2nd[i]);
1734 #endif
1736 #ifdef FAX_DETECT
1737 goertzel_reset (&dsp->td.dtmf.fax_tone);
1738 #endif
1739 #ifdef OLD_DSP_ROUTINES
1740 #ifdef FAX_DETECT
1741 goertzel_reset (&dsp->td.dtmf.fax_tone2nd);
1742 #endif
1743 dsp->td.dtmf.hit1 = dsp->td.dtmf.hit2 = dsp->td.dtmf.hit3 = dsp->td.dtmf.hit4 = dsp->td.dtmf.mhit = 0;
1744 #else
1745 dsp->td.dtmf.lasthit = dsp->td.dtmf.mhit = 0;
1746 #endif
1747 dsp->td.dtmf.energy = 0.0;
1748 dsp->td.dtmf.current_sample = 0;
1752 void ast_dsp_reset(struct ast_dsp *dsp)
1754 int x;
1756 dsp->totalsilence = 0;
1757 dsp->gsamps = 0;
1758 for (x=0;x<4;x++)
1759 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
1760 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
1761 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
1762 dsp->ringtimeout= 0;
1765 int ast_dsp_digitmode(struct ast_dsp *dsp, int digitmode)
1767 int new;
1768 int old;
1770 old = dsp->digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
1771 new = digitmode & (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX);
1772 if (old != new) {
1773 /* Must initialize structures if switching from MF to DTMF or vice-versa */
1774 if (new & DSP_DIGITMODE_MF)
1775 ast_mf_detect_init(&dsp->td.mf);
1776 else
1777 ast_dtmf_detect_init(&dsp->td.dtmf);
1779 dsp->digitmode = digitmode;
1780 return 0;
1783 int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
1785 int x;
1787 for (x=0;x<sizeof(aliases) / sizeof(aliases[0]);x++) {
1788 if (!strcasecmp(aliases[x].name, zone)) {
1789 dsp->progmode = aliases[x].mode;
1790 ast_dsp_prog_reset(dsp);
1791 return 0;
1794 return -1;
1797 int ast_dsp_get_tstate(struct ast_dsp *dsp)
1799 return dsp->tstate;
1802 int ast_dsp_get_tcount(struct ast_dsp *dsp)
1804 return dsp->tcount;
1807 void ast_dsp_frame_freed(struct ast_frame *fr)
1809 struct ast_dsp *dsp;
1811 ast_clear_flag(fr, AST_FRFLAG_FROM_DSP);
1813 dsp = (struct ast_dsp *) (((char *) fr) - offsetof(struct ast_dsp, f));
1815 if (dsp->freqcount != -1)
1816 return;
1818 ast_dsp_free(dsp);