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