Asterisk - The Open Source Telephony Project GIT-master-80b953f
Loading...
Searching...
No Matches
dsp.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 1999 - 2005, Digium, Inc.
5 *
6 * Mark Spencer <markster@digium.com>
7 *
8 * Goertzel routines are borrowed from Steve Underwood's tremendous work on the
9 * DTMF detector.
10 *
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.
16 *
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.
20 */
21
22/*! \file
23 *
24 * \brief Convenience Signal Processing routines
25 *
26 * \author Mark Spencer <markster@digium.com>
27 * \author Steve Underwood <steveu@coppice.org>
28 */
29
30/*! \li \ref dsp.c uses the configuration file \ref dsp.conf
31 * \addtogroup configuration_file Configuration Files
32 */
33
34/*!
35 * \page dsp.conf dsp.conf
36 * \verbinclude dsp.conf.sample
37 */
38
39/* Some routines from tone_detect.c by Steven Underwood as published under the zapata library */
40/*
41 tone_detect.c - General telephony tone detection, and specific
42 detection of DTMF.
43
44 Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
45
46 Despite my general liking of the GPL, I place this code in the
47 public domain for the benefit of all mankind - even the slimy
48 ones who might try to proprietize my work and use it to my
49 detriment.
50*/
51
52/*** MODULEINFO
53 <support_level>core</support_level>
54 ***/
55
56#include "asterisk.h"
57
58#include <math.h>
59
60#include "asterisk/module.h"
61#include "asterisk/frame.h"
63#include "asterisk/channel.h"
64#include "asterisk/dsp.h"
65#include "asterisk/ulaw.h"
66#include "asterisk/alaw.h"
67#include "asterisk/utils.h"
68#include "asterisk/options.h"
69#include "asterisk/config.h"
70#include "asterisk/test.h"
71
72/*! Number of goertzels for progress detect */
74 GSAMP_SIZE_NA = 183, /*!< North America - 350, 440, 480, 620, 950, 1400, 1800 Hz */
75 GSAMP_SIZE_CR = 188, /*!< Costa Rica, Brazil - Only care about 425 Hz */
76 GSAMP_SIZE_UK = 160 /*!< UK disconnect goertzel feed - should trigger 400hz */
77};
78
84
86 /*! For US modes { */
87 HZ_350 = 0,
93 HZ_1800, /*!< } */
94
95 /*! For CR/BR modes */
96 HZ_425 = 0,
97
98 /*! For UK mode */
103
104static struct progalias {
105 char *name;
107} aliases[] = {
108 { "us", PROG_MODE_NA },
109 { "ca", PROG_MODE_NA },
110 { "cr", PROG_MODE_CR },
111 { "br", PROG_MODE_CR },
112 { "uk", PROG_MODE_UK },
114
115#define FREQ_ARRAY_SIZE 7
116
117static struct progress {
120} modes[] = {
121 { GSAMP_SIZE_NA, { 350, 440, 480, 620, 950, 1400, 1800 } }, /*!< North America */
122 { GSAMP_SIZE_CR, { 425 } }, /*!< Costa Rica, Brazil */
123 { GSAMP_SIZE_UK, { 350, 400, 440 } }, /*!< UK */
125
126/*!
127 * \brief Default minimum average magnitude threshold to determine talking/noise by the DSP.
128 *
129 * \details
130 * The magnitude calculated for this threshold is determined by
131 * averaging the absolute value of all samples within a frame.
132 *
133 * This value is the threshold for which a frame's average magnitude
134 * is determined to either be silence (below the threshold) or
135 * noise/talking (at or above the threshold). Please note that while
136 * the default threshold is an even exponent of 2, there is no
137 * requirement that it be so. The threshold will work for any value
138 * between 1 and 2^15.
139 */
140#define DEFAULT_THRESHOLD 512
141
143 BUSY_PERCENT = 10, /*!< The percentage difference between the two last silence periods */
144 BUSY_PAT_PERCENT = 7, /*!< The percentage difference between measured and actual pattern */
145 BUSY_THRESHOLD = 100, /*!< Max number of ms difference between max and min times in busy */
146 BUSY_MIN = 75, /*!< Busy must be at least 80 ms in half-cadence */
147 BUSY_MAX = 3100 /*!< Busy can't be longer than 3100 ms in half-cadence */
149
150/*! Remember last 15 units */
151#define DSP_HISTORY 15
152
153#define TONE_THRESH 10.0 /*!< How much louder the tone should be than channel energy */
154#define TONE_MIN_THRESH 1e8 /*!< How much tone there should be at least to attempt */
155
156/*! All THRESH_XXX values are in GSAMP_SIZE chunks (us = 22ms) */
158 THRESH_RING = 8, /*!< Need at least 150ms ring to accept */
159 THRESH_TALK = 2, /*!< Talk detection does not work continuously */
160 THRESH_BUSY = 4, /*!< Need at least 80ms to accept */
161 THRESH_CONGESTION = 4, /*!< Need at least 80ms to accept */
162 THRESH_HANGUP = 60, /*!< Need at least 1300ms to accept hangup */
163 THRESH_RING2ANSWER = 300 /*!< Timeout from start of ring to answer (about 6600 ms) */
165
166#define MAX_DTMF_DIGITS 128
167
168#define DTMF_MATRIX_SIZE 4
169
170/* Basic DTMF (AT&T) specs:
171 *
172 * Minimum tone on = 40ms
173 * Minimum tone off = 50ms
174 * Maximum digit rate = 10 per second
175 * Normal twist <= 8dB accepted
176 * Reverse twist <= 4dB accepted
177 * S/N >= 15dB will detect OK
178 * Attenuation <= 26dB will detect OK
179 * Frequency tolerance +- 1.5% will detect, +-3.5% will reject
180 */
181
182#define DTMF_THRESHOLD 8.0e7
183#define TONE_THRESHOLD 7.8e7
184
185#define DEF_DTMF_NORMAL_TWIST 6.31 /* 8.0dB */
186#define DEF_RELAX_DTMF_NORMAL_TWIST 6.31 /* 8.0dB */
187
188#ifdef RADIO_RELAX
189#define DEF_DTMF_REVERSE_TWIST 2.51 /* 4.01dB */
190#define DEF_RELAX_DTMF_REVERSE_TWIST 6.61 /* 8.2dB */
191#else
192#define DEF_DTMF_REVERSE_TWIST 2.51 /* 4.01dB */
193#define DEF_RELAX_DTMF_REVERSE_TWIST 3.98 /* 6.0dB */
194#endif
195
196#define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */
197#define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */
198#define DTMF_TO_TOTAL_ENERGY 42.0
199
200#define BELL_MF_THRESHOLD 1.6e9
201#define BELL_MF_TWIST 4.0 /* 6dB */
202#define BELL_MF_RELATIVE_PEAK 12.6 /* 11dB */
203
204#define R2_MF_THRESHOLD 5.0e8f
205#define R2_MF_TWIST 5.0f /* 7dB */
206#define R2_MF_RELATIVE_PEAK 12.6f /* 11dB */
207
208#if defined(BUSYDETECT_TONEONLY) && defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
209#error You cant use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE
210#endif
211
212/* The CNG signal consists of the transmission of 1100 Hz for 1/2 second,
213 * followed by a 3 second silent (2100 Hz OFF) period.
214 */
215#define FAX_TONE_CNG_FREQ 1100
216#define FAX_TONE_CNG_DURATION 500 /* ms */
217#define FAX_TONE_CNG_DB 16
218
219/* This signal may be sent by the Terminating FAX machine anywhere between
220 * 1.8 to 2.5 seconds AFTER answering the call. The CED signal consists
221 * of a 2100 Hz tone that is from 2.6 to 4 seconds in duration.
222*/
223#define FAX_TONE_CED_FREQ 2100
224#define FAX_TONE_CED_DURATION 2600 /* ms */
225#define FAX_TONE_CED_DB 16
226
227#define DEFAULT_SAMPLE_RATE 8000
228
229/* MF goertzel size */
230#define MF_GSIZE 120
231
232/* DTMF goertzel size */
233#define DTMF_GSIZE 102
234
235/* R2 goertzel size */
236#define R2_GSIZE 133
237
238/* How many successive hits needed to consider begin of a digit
239 * IE. Override with dtmf_hits_to_begin=4 in dsp.conf
240 */
241#define DEF_DTMF_HITS_TO_BEGIN 2
242
243/* How many successive misses needed to consider end of a digit
244 * IE. Override with dtmf_misses_to_end=4 in dsp.conf
245 */
246#define DEF_DTMF_MISSES_TO_END 3
247
248/*!
249 * \brief The default silence threshold we will use if an alternate
250 * configured value is not present or is invalid.
251 */
252static const int DEFAULT_SILENCE_THRESHOLD = 256;
253
254#define CONFIG_FILE_NAME "dsp.conf"
255
256typedef struct {
257 /*! The previous previous sample calculation (No binary point just plain int) */
258 int v2;
259 /*! The previous sample calculation (No binary point just plain int) */
260 int v3;
261 /*! v2 and v3 power of two exponent to keep value in int range */
263 /*! 15 bit fixed point goertzel coefficient = 2 * cos(2 * pi * freq / sample_rate) */
264 int fac;
266
267typedef struct {
268 int value;
269 int power;
271
272typedef struct
273{
274 int freq;
276 int squelch; /* Remove (squelch) tone */
278 float energy; /* Accumulated energy of the current block */
279 int samples_pending; /* Samples remain to complete the current block */
280 int mute_samples; /* How many additional samples needs to be muted to suppress already detected tone */
281
282 int hits_required; /* How many successive blocks with tone we are looking for */
283 float threshold; /* Energy of the tone relative to energy from all other signals to consider a hit */
284
285 int hit_count; /* How many successive blocks we consider tone present */
286 int last_hit; /* Indicates if the last processed block was a hit */
287
289
290typedef struct
291{
294 int hits; /* How many successive hits we have seen already */
295 int misses; /* How many successive misses we have seen already */
298 float energy;
302
303typedef struct
304{
305 goertzel_state_t tone_out[6];
307 int hits[5];
311
312typedef struct
313{
314 char digits[MAX_DTMF_DIGITS + 1];
315 int digitlen[MAX_DTMF_DIGITS + 1];
319
320 union {
323 } td;
325
326static const float dtmf_row[] = {
327 697.0, 770.0, 852.0, 941.0
328};
329static const float dtmf_col[] = {
330 1209.0, 1336.0, 1477.0, 1633.0
331};
332static const float mf_tones[] = {
333 700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0
334};
335static const float r2_forward_tones[] = {
336 1380.0, 1500.0, 1620.0, 1740.0, 1860.0, 1980.0
337};
338static const float r2_backward_tones[] = {
339 1140.0, 1020.0, 900.0, 780.0, 660.0, 540.0
340};
341static const char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
342static const char bell_mf_positions[] = "1247C-358A--69*---0B----#";
343static const char r2_mf_positions[] = "1247B-358C--69D---0E----F"; /* Use codes '1' to 'F' for the R2 signals 1 to 15, except for signal 'A'. Use '0' for this, so the codes match the digits 0-9. */
345static float dtmf_normal_twist; /* AT&T = 8dB */
346static float dtmf_reverse_twist; /* AT&T = 4dB */
347static float relax_dtmf_normal_twist; /* AT&T = 8dB */
348static float relax_dtmf_reverse_twist; /* AT&T = 6dB */
349static int dtmf_hits_to_begin; /* How many successive hits needed to consider begin of a digit */
350static int dtmf_misses_to_end; /* How many successive misses needed to consider end of a digit */
351
352static inline void goertzel_sample(goertzel_state_t *s, short sample)
353{
354 int v1;
355
356 /*
357 * Shift previous values so
358 * v1 is previous previous value
359 * v2 is previous value
360 * until the new v3 is calculated.
361 */
362 v1 = s->v2;
363 s->v2 = s->v3;
364
365 /* Discard the binary fraction introduced by s->fac */
366 s->v3 = (s->fac * s->v2) >> 15;
367 /* Scale sample to match previous values */
368 s->v3 = s->v3 - v1 + (sample >> s->chunky);
369
370 if (abs(s->v3) > (1 << 15)) {
371 /* The result is now too large so increase the chunky power. */
372 s->chunky++;
373 s->v3 = s->v3 >> 1;
374 s->v2 = s->v2 >> 1;
375 }
376}
377
378static inline float goertzel_result(goertzel_state_t *s)
379{
381
382 r.value = (s->v3 * s->v3) + (s->v2 * s->v2);
383 r.value -= ((s->v2 * s->v3) >> 15) * s->fac;
384 /*
385 * We have to double the exponent because we multiplied the
386 * previous sample calculation values together.
387 */
388 r.power = s->chunky * 2;
389 return (float)r.value * (float)(1 << r.power);
390}
391
392static inline void goertzel_init(goertzel_state_t *s, float freq, unsigned int sample_rate)
393{
394 s->v2 = s->v3 = s->chunky = 0;
395 s->fac = (int)(32768.0 * 2.0 * cos(2.0 * M_PI * freq / sample_rate));
396}
397
398static inline void goertzel_reset(goertzel_state_t *s)
399{
400 s->v2 = s->v3 = s->chunky = 0;
401}
402
403typedef struct {
404 int start;
405 int end;
406} fragment_t;
407
408/* Note on tone suppression (squelching). Individual detectors (DTMF/MF/generic tone)
409 * report fragments of the frame in which detected tone resides and which needs
410 * to be "muted" in order to suppress the tone. To mark fragment for muting,
411 * detectors call mute_fragment passing fragment_t there. Multiple fragments
412 * can be marked and ast_dsp_process later will mute all of them.
413 *
414 * Note: When tone starts in the middle of a Goertzel block, it won't be properly
415 * detected in that block, only in the next. If we only mute the next block
416 * where tone is actually detected, the user will still hear beginning
417 * of the tone in preceeding block. This is why we usually want to mute some amount
418 * of samples preceeding and following the block where tone was detected.
419*/
420
421struct ast_dsp {
422 struct ast_frame f;
424 /*! Accumulated total silence in ms since last talking/noise. */
426 /*! Accumulated total talking/noise in ms since last silence. */
430 int busymaybe; /* Boolean, could be a bitfield */
445 int dtmf_began; /* Boolean, could be a bitfield */
446 int display_inband_dtmf_warning; /* Boolean, could be a bitfield */
447 float genergy;
449 unsigned int sample_rate;
454};
455
456static void mute_fragment(struct ast_dsp *dsp, fragment_t *fragment)
457{
458 if (dsp->mute_fragments >= ARRAY_LEN(dsp->mute_data)) {
459 ast_log(LOG_ERROR, "Too many fragments to mute. Ignoring\n");
460 return;
461 }
462
463 dsp->mute_data[dsp->mute_fragments++] = *fragment;
464}
465
466static void ast_tone_detect_init(tone_detect_state_t *s, int freq, int duration, int amp, unsigned int sample_rate)
467{
468 int duration_samples;
469 float x;
470 int periods_in_block;
471
472 s->freq = freq;
473
474 /* Desired tone duration in samples */
475 duration_samples = duration * sample_rate / 1000;
476 /* We want to allow 10% deviation of tone duration */
477 duration_samples = duration_samples * 9 / 10;
478
479 /* If we want to remove tone, it is important to have block size not
480 to exceed frame size. Otherwise by the moment tone is detected it is too late
481 to squelch it from previous frames. Block size is 20ms at the given sample rate.*/
482 s->block_size = (20 * sample_rate) / 1000;
483
484 periods_in_block = s->block_size * freq / sample_rate;
485
486 /* Make sure we will have at least 5 periods at target frequency for analysis.
487 This may make block larger than expected packet and will make squelching impossible
488 but at least we will be detecting the tone */
489 if (periods_in_block < 5) {
490 periods_in_block = 5;
491 }
492
493 /* Now calculate final block size. It will contain integer number of periods */
494 s->block_size = periods_in_block * sample_rate / freq;
495
496 /* tone_detect is generally only used to detect fax tones and we
497 do not need squelching the fax tones */
498 s->squelch = 0;
499
500 /* Account for the first and the last block to be incomplete
501 and thus no tone will be detected in them */
502 s->hits_required = (duration_samples - (s->block_size - 1)) / s->block_size;
503
504 goertzel_init(&s->tone, freq, sample_rate);
505
507 s->hit_count = 0;
508 s->last_hit = 0;
509 s->energy = 0.0;
510
511 /* We want tone energy to be amp decibels above the rest of the signal (the noise).
512 According to Parseval's theorem the energy computed in time domain equals to energy
513 computed in frequency domain. So subtracting energy in the frequency domain (Goertzel result)
514 from the energy in the time domain we will get energy of the remaining signal (without the tone
515 we are detecting). We will be checking that
516 10*log(Ew / (Et - Ew)) > amp
517 Calculate threshold so that we will be actually checking
518 Ew > Et * threshold
519 */
520
521 x = pow(10.0, amp / 10.0);
522 s->threshold = x / (x + 1);
523
524 ast_debug(1, "Setup tone %d Hz, %d ms, block_size=%d, hits_required=%d\n", freq, duration, s->block_size, s->hits_required);
525}
526
537
538static void ast_freq_detect_init(struct ast_dsp *s, int freq, int dur, int db, int squelch)
539{
540 /* we can conveniently just use one of the two fax tone states */
541 ast_tone_detect_init(&s->cng_tone_state, freq, dur, db, s->sample_rate);
542 if (s->freqmode & squelch) {
543 s->cng_tone_state.squelch = 1;
544 }
545}
546
547static void ast_dtmf_detect_init(dtmf_detect_state_t *s, unsigned int sample_rate)
548{
549 int i;
550
551 for (i = 0; i < DTMF_MATRIX_SIZE; i++) {
552 goertzel_init(&s->row_out[i], dtmf_row[i], sample_rate);
553 goertzel_init(&s->col_out[i], dtmf_col[i], sample_rate);
554 }
555 s->lasthit = 0;
556 s->current_hit = 0;
557 s->energy = 0.0;
558 s->current_sample = 0;
559 s->hits = 0;
560 s->misses = 0;
561}
562
563static void ast_mf_detect_init(mf_detect_state_t *s, unsigned int sample_rate)
564{
565 int i;
566
567 for (i = 0; i < 6; i++) {
568 goertzel_init(&s->tone_out[i], mf_tones[i], sample_rate);
569 }
570 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
571 s->current_sample = 0;
572 s->current_hit = 0;
573}
574
575static void ast_r2_detect_init(mf_detect_state_t *s, unsigned int sample_rate, int backward)
576{
577 int i;
578
579 for (i = 0; i < 6; i++) {
580 goertzel_init(&s->tone_out[i], backward ? r2_backward_tones[i] : r2_forward_tones[i], sample_rate);
581 }
582 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
583 s->current_sample = 0;
584 s->current_hit = 0;
585}
586
587static void ast_digit_detect_init(digit_detect_state_t *s, int digitmode, unsigned int sample_rate)
588{
589 s->current_digits = 0;
590 s->detected_digits = 0;
591 s->lost_digits = 0;
592 s->digits[0] = '\0';
593
594 if (digitmode & DSP_DIGITMODE_R2_FORWARD) {
595 ast_r2_detect_init(&s->td.mf, sample_rate, 0);
596 } else if (digitmode & DSP_DIGITMODE_R2_BACKWARD) {
597 ast_r2_detect_init(&s->td.mf, sample_rate, 1);
598 } else if (digitmode & DSP_DIGITMODE_MF) {
599 ast_mf_detect_init(&s->td.mf, sample_rate);
600 } else {
601 ast_dtmf_detect_init(&s->td.dtmf, sample_rate);
602 }
603}
604
605static int tone_detect(struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp, int samples)
606{
607 float tone_energy;
608 int i;
609 int hit = 0;
610 int limit;
611 int res = 0;
612 int16_t *ptr;
613 short samp;
614 int start, end;
615 fragment_t mute = {0, 0};
616
617 if (s->squelch && s->mute_samples > 0) {
618 mute.end = (s->mute_samples < samples) ? s->mute_samples : samples;
619 s->mute_samples -= mute.end;
620 }
621
622 for (start = 0; start < samples; start = end) {
623 /* Process in blocks. */
624 limit = samples - start;
625 if (limit > s->samples_pending) {
626 limit = s->samples_pending;
627 }
628 end = start + limit;
629
630 for (i = limit, ptr = amp ; i > 0; i--, ptr++) {
631 samp = *ptr;
632 /* signed 32 bit int should be enough to square any possible signed 16 bit value */
633 s->energy += (int32_t) samp * (int32_t) samp;
634
635 goertzel_sample(&s->tone, samp);
636 }
637
638 s->samples_pending -= limit;
639
640 if (s->samples_pending) {
641 /* Finished incomplete (last) block */
642 break;
643 }
644
645 tone_energy = goertzel_result(&s->tone);
646
647 /* Scale to make comparable */
648 tone_energy *= 2.0;
649 s->energy *= s->block_size;
650
651 /* Add 1 to hit_count when logging, since it doesn't get incremented until later in the loop. */
652 if (TONE_THRESHOLD <= tone_energy
653 && tone_energy > s->energy * s->threshold) {
654 ast_debug(9, "%d Hz tone Hit! [%d/%d] Ew=%.4E, Et=%.4E, s/n=%10.2f\n", s->freq, s->hit_count + 1, s->hits_required, tone_energy, s->energy, tone_energy / (s->energy - tone_energy));
655 hit = 1;
656 } else {
657 ast_debug(10, "%d Hz tone [%d/%d] Ew=%.4E, Et=%.4E, s/n=%10.2f\n", s->freq, s->hit_count, s->hits_required, tone_energy, s->energy, tone_energy / (s->energy - tone_energy));
658 hit = 0;
659 }
660
661 if (s->hit_count) {
662 s->hit_count++;
663 }
664
665 if (hit == s->last_hit) {
666 if (!hit) {
667 /* Two successive misses. Tone ended */
668 if (s->hit_count) {
669 ast_debug(9, "Partial detect expired after %d/%d hits\n", s->hit_count, s->hits_required);
670 }
671 s->hit_count = 0;
672 } else if (!s->hit_count) {
673 s->hit_count++;
674 }
675 }
676
677 if (s->hit_count == s->hits_required) {
678 ast_debug(1, "%d Hz tone detected\n", s->freq);
679 res = 1;
680 }
681
682 s->last_hit = hit;
683
684 /* If we had a hit in this block, include it into mute fragment */
685 if (s->squelch && hit) {
686 if (mute.end < start - s->block_size) {
687 /* There is a gap between fragments */
688 mute_fragment(dsp, &mute);
689 mute.start = (start > s->block_size) ? (start - s->block_size) : 0;
690 }
691 mute.end = end + s->block_size;
692 }
693
694 /* Reinitialise the detector for the next block */
695 /* Reset for the next block */
696 goertzel_reset(&s->tone);
697
698 /* Advance to the next block */
699 s->energy = 0.0;
701
702 amp += limit;
703 }
704
705 if (s->squelch && mute.end) {
706 if (mute.end > samples) {
707 s->mute_samples = mute.end - samples;
708 mute.end = samples;
709 }
710 mute_fragment(dsp, &mute);
711 }
712
713 return res;
714}
715
717{
718 s->detected_digits++;
720 s->digitlen[s->current_digits] = 0;
721 s->digits[s->current_digits++] = digit;
722 s->digits[s->current_digits] = '\0';
723 } else {
724 ast_log(LOG_WARNING, "Digit lost due to full buffer\n");
725 s->lost_digits++;
726 }
727}
728
729static int dtmf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax)
730{
731 float row_energy[DTMF_MATRIX_SIZE];
732 float col_energy[DTMF_MATRIX_SIZE];
733 int i;
734 int j;
735 int sample;
736 short samp;
737 int best_row;
738 int best_col;
739 int hit;
740 int limit;
741 fragment_t mute = {0, 0};
742
743 if (squelch && s->td.dtmf.mute_samples > 0) {
744 mute.end = (s->td.dtmf.mute_samples < samples) ? s->td.dtmf.mute_samples : samples;
745 s->td.dtmf.mute_samples -= mute.end;
746 }
747
748 hit = 0;
749 for (sample = 0; sample < samples; sample = limit) {
750 /* DTMF_GSIZE is optimised to meet the DTMF specs. */
751 if ((samples - sample) >= (DTMF_GSIZE - s->td.dtmf.current_sample)) {
752 limit = sample + (DTMF_GSIZE - s->td.dtmf.current_sample);
753 } else {
754 limit = samples;
755 }
756 /* The following unrolled loop takes only 35% (rough estimate) of the
757 time of a rolled loop on the machine on which it was developed */
758 for (j = sample; j < limit; j++) {
759 samp = amp[j];
760 s->td.dtmf.energy += (int32_t) samp * (int32_t) samp;
761 /* With GCC 2.95, the following unrolled code seems to take about 35%
762 (rough estimate) as long as a neat little 0-3 loop */
763 goertzel_sample(s->td.dtmf.row_out, samp);
764 goertzel_sample(s->td.dtmf.col_out, samp);
765 goertzel_sample(s->td.dtmf.row_out + 1, samp);
766 goertzel_sample(s->td.dtmf.col_out + 1, samp);
767 goertzel_sample(s->td.dtmf.row_out + 2, samp);
768 goertzel_sample(s->td.dtmf.col_out + 2, samp);
769 goertzel_sample(s->td.dtmf.row_out + 3, samp);
770 goertzel_sample(s->td.dtmf.col_out + 3, samp);
771 /* go up to DTMF_MATRIX_SIZE - 1 */
772 }
773 s->td.dtmf.current_sample += (limit - sample);
774 if (s->td.dtmf.current_sample < DTMF_GSIZE) {
775 continue;
776 }
777 /* We are at the end of a DTMF detection block */
778 /* Find the peak row and the peak column */
779 row_energy[0] = goertzel_result(&s->td.dtmf.row_out[0]);
780 col_energy[0] = goertzel_result(&s->td.dtmf.col_out[0]);
781
782 for (best_row = best_col = 0, i = 1; i < DTMF_MATRIX_SIZE; i++) {
783 row_energy[i] = goertzel_result(&s->td.dtmf.row_out[i]);
784 if (row_energy[i] > row_energy[best_row]) {
785 best_row = i;
786 }
787 col_energy[i] = goertzel_result(&s->td.dtmf.col_out[i]);
788 if (col_energy[i] > col_energy[best_col]) {
789 best_col = i;
790 }
791 }
792 ast_debug(10, "DTMF best '%c' Erow=%.4E Ecol=%.4E Erc=%.4E Et=%.4E\n",
793 dtmf_positions[(best_row << 2) + best_col],
794 row_energy[best_row], col_energy[best_col],
795 row_energy[best_row] + col_energy[best_col], s->td.dtmf.energy);
796 hit = 0;
797 /* Basic signal level test and the twist test */
798 if (row_energy[best_row] >= DTMF_THRESHOLD &&
799 col_energy[best_col] >= DTMF_THRESHOLD &&
800 col_energy[best_col] < row_energy[best_row] * (relax ? relax_dtmf_reverse_twist : dtmf_reverse_twist) &&
801 row_energy[best_row] < col_energy[best_col] * (relax ? relax_dtmf_normal_twist : dtmf_normal_twist)) {
802 /* Relative peak test */
803 for (i = 0; i < DTMF_MATRIX_SIZE; i++) {
804 if ((i != best_col &&
805 col_energy[i] * DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
806 (i != best_row
807 && row_energy[i] * DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
808 break;
809 }
810 }
811 /* ... and fraction of total energy test */
812 if (i >= DTMF_MATRIX_SIZE &&
813 (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY * s->td.dtmf.energy) {
814 /* Got a hit */
815 hit = dtmf_positions[(best_row << 2) + best_col];
816 ast_debug(10, "DTMF hit '%c'\n", hit);
817 }
818 }
819
820/*
821 * Adapted from ETSI ES 201 235-3 V1.3.1 (2006-03)
822 * (40ms reference is tunable with hits_to_begin and misses_to_end)
823 * each hit/miss is 12.75ms with DTMF_GSIZE at 102
824 *
825 * Character recognition: When not DRC *(1) and then
826 * Shall exist VSC > 40 ms (hits_to_begin)
827 * May exist 20 ms <= VSC <= 40 ms
828 * Shall not exist VSC < 20 ms
829 *
830 * Character recognition: When DRC and then
831 * Shall cease Not VSC > 40 ms (misses_to_end)
832 * May cease 20 ms >= Not VSC >= 40 ms
833 * Shall not cease Not VSC < 20 ms
834 *
835 * *(1) or optionally a different digit recognition condition
836 *
837 * Legend: VSC The continuous existence of a valid signal condition.
838 * Not VSC The continuous non-existence of valid signal condition.
839 * DRC The existence of digit recognition condition.
840 * Not DRC The non-existence of digit recognition condition.
841 */
842
843/*
844 * Example: hits_to_begin=2 misses_to_end=3
845 * -------A last_hit=A hits=0&1
846 * ------AA hits=2 current_hit=A misses=0 BEGIN A
847 * -----AA- misses=1 last_hit=' ' hits=0
848 * ----AA-- misses=2
849 * ---AA--- misses=3 current_hit=' ' END A
850 * --AA---B last_hit=B hits=0&1
851 * -AA---BC last_hit=C hits=0&1
852 * AA---BCC hits=2 current_hit=C misses=0 BEGIN C
853 * A---BCC- misses=1 last_hit=' ' hits=0
854 * ---BCC-C misses=0 last_hit=C hits=0&1
855 * --BCC-CC misses=0
856 *
857 * Example: hits_to_begin=3 misses_to_end=2
858 * -------A last_hit=A hits=0&1
859 * ------AA hits=2
860 * -----AAA hits=3 current_hit=A misses=0 BEGIN A
861 * ----AAAB misses=1 last_hit=B hits=0&1
862 * ---AAABB misses=2 current_hit=' ' hits=2 END A
863 * --AAABBB hits=3 current_hit=B misses=0 BEGIN B
864 * -AAABBBB misses=0
865 *
866 * Example: hits_to_begin=2 misses_to_end=2
867 * -------A last_hit=A hits=0&1
868 * ------AA hits=2 current_hit=A misses=0 BEGIN A
869 * -----AAB misses=1 hits=0&1
870 * ----AABB misses=2 current_hit=' ' hits=2 current_hit=B misses=0 BEGIN B
871 * ---AABBB misses=0
872 */
873
874 if (s->td.dtmf.current_hit) {
875 /* We are in the middle of a digit already */
876 if (hit != s->td.dtmf.current_hit) {
877 s->td.dtmf.misses++;
878 if (s->td.dtmf.misses == dtmf_misses_to_end) {
879 /* There were enough misses to consider digit ended */
880 s->td.dtmf.current_hit = 0;
881 }
882 } else {
883 s->td.dtmf.misses = 0;
884 /* Current hit was same as last, so increment digit duration (of last digit) */
885 s->digitlen[s->current_digits - 1] += DTMF_GSIZE;
886 }
887 }
888
889 /* Look for a start of a new digit no matter if we are already in the middle of some
890 digit or not. This is because hits_to_begin may be smaller than misses_to_end
891 and we may find begin of new digit before we consider last one ended. */
892
893 if (hit != s->td.dtmf.lasthit) {
894 s->td.dtmf.lasthit = hit;
895 s->td.dtmf.hits = 0;
896 }
897 if (hit && hit != s->td.dtmf.current_hit) {
898 s->td.dtmf.hits++;
899 if (s->td.dtmf.hits == dtmf_hits_to_begin) {
900 store_digit(s, hit);
902 s->td.dtmf.current_hit = hit;
903 s->td.dtmf.misses = 0;
904 }
905 }
906
907 /* If we had a hit in this block, include it into mute fragment */
908 if (squelch && hit) {
909 if (mute.end < sample - DTMF_GSIZE) {
910 /* There is a gap between fragments */
911 mute_fragment(dsp, &mute);
912 mute.start = (sample > DTMF_GSIZE) ? (sample - DTMF_GSIZE) : 0;
913 }
914 mute.end = limit + DTMF_GSIZE;
915 }
916
917 /* Reinitialise the detector for the next block */
918 for (i = 0; i < DTMF_MATRIX_SIZE; i++) {
921 }
922 s->td.dtmf.energy = 0.0;
923 s->td.dtmf.current_sample = 0;
924 }
925
926 if (squelch && mute.end) {
927 if (mute.end > samples) {
928 s->td.dtmf.mute_samples = mute.end - samples;
929 mute.end = samples;
930 }
931 mute_fragment(dsp, &mute);
932 }
933
934 return (s->td.dtmf.current_hit); /* return the debounced hit */
935}
936
937static int mf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[],
938 int samples, int squelch, int relax)
939{
940 float energy[6];
941 int best;
942 int second_best;
943 int i;
944 int j;
945 int sample;
946 short samp;
947 int hit;
948 int limit;
949 fragment_t mute = {0, 0};
950
951 if (squelch && s->td.mf.mute_samples > 0) {
952 mute.end = (s->td.mf.mute_samples < samples) ? s->td.mf.mute_samples : samples;
953 s->td.mf.mute_samples -= mute.end;
954 }
955
956 hit = 0;
957 for (sample = 0; sample < samples; sample = limit) {
958 /* 80 is optimised to meet the MF specs. */
959 /* XXX So then why is MF_GSIZE defined as 120? */
960 if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample)) {
961 limit = sample + (MF_GSIZE - s->td.mf.current_sample);
962 } else {
963 limit = samples;
964 }
965 /* The following unrolled loop takes only 35% (rough estimate) of the
966 time of a rolled loop on the machine on which it was developed */
967 for (j = sample; j < limit; j++) {
968 /* With GCC 2.95, the following unrolled code seems to take about 35%
969 (rough estimate) as long as a neat little 0-3 loop */
970 samp = amp[j];
971 goertzel_sample(s->td.mf.tone_out, samp);
972 goertzel_sample(s->td.mf.tone_out + 1, samp);
973 goertzel_sample(s->td.mf.tone_out + 2, samp);
974 goertzel_sample(s->td.mf.tone_out + 3, samp);
975 goertzel_sample(s->td.mf.tone_out + 4, samp);
976 goertzel_sample(s->td.mf.tone_out + 5, samp);
977 }
978 s->td.mf.current_sample += (limit - sample);
979 if (s->td.mf.current_sample < MF_GSIZE) {
980 continue;
981 }
982 /* We're at the end of an MF detection block. */
983 /* Find the two highest energies. The spec says to look for
984 two tones and two tones only. Taking this literally -ie
985 only two tones pass the minimum threshold - doesn't work
986 well. The sinc function mess, due to rectangular windowing
987 ensure that! Find the two highest energies and ensure they
988 are considerably stronger than any of the others. */
989 energy[0] = goertzel_result(&s->td.mf.tone_out[0]);
990 energy[1] = goertzel_result(&s->td.mf.tone_out[1]);
991 if (energy[0] > energy[1]) {
992 best = 0;
993 second_best = 1;
994 } else {
995 best = 1;
996 second_best = 0;
997 }
998 /*endif*/
999 for (i = 2; i < 6; i++) {
1000 energy[i] = goertzel_result(&s->td.mf.tone_out[i]);
1001 if (energy[i] >= energy[best]) {
1002 second_best = best;
1003 best = i;
1004 } else if (energy[i] >= energy[second_best]) {
1005 second_best = i;
1006 }
1007 }
1008 /* Basic signal level and twist tests */
1009 hit = 0;
1010 if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD
1011 && energy[best] < energy[second_best]*BELL_MF_TWIST
1012 && energy[best] * BELL_MF_TWIST > energy[second_best]) {
1013 /* Relative peak test */
1014 hit = -1;
1015 for (i = 0; i < 6; i++) {
1016 if (i != best && i != second_best) {
1017 if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) {
1018 /* The best two are not clearly the best */
1019 hit = 0;
1020 break;
1021 }
1022 }
1023 }
1024 }
1025 if (hit) {
1026 /* Get the values into ascending order */
1027 if (second_best < best) {
1028 i = best;
1029 best = second_best;
1030 second_best = i;
1031 }
1032 best = best * 5 + second_best - 1;
1033 hit = bell_mf_positions[best];
1034 /* Look for two successive similar results */
1035 /* The logic in the next test is:
1036 For KP we need 4 successive identical clean detects, with
1037 two blocks of something different preceeding it. For anything
1038 else we need two successive identical clean detects, with
1039 two blocks of something different preceeding it. */
1040 if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] &&
1041 ((hit != '*' && hit != s->td.mf.hits[2] && hit != s->td.mf.hits[1])||
1042 (hit == '*' && hit == s->td.mf.hits[2] && hit != s->td.mf.hits[1] &&
1043 hit != s->td.mf.hits[0]))) {
1044 store_digit(s, hit);
1045 }
1046 }
1047
1048
1049 if (hit != s->td.mf.hits[4] && hit != s->td.mf.hits[3]) {
1050 /* Two successive block without a hit terminate current digit */
1051 s->td.mf.current_hit = 0;
1052 }
1053
1054 s->td.mf.hits[0] = s->td.mf.hits[1];
1055 s->td.mf.hits[1] = s->td.mf.hits[2];
1056 s->td.mf.hits[2] = s->td.mf.hits[3];
1057 s->td.mf.hits[3] = s->td.mf.hits[4];
1058 s->td.mf.hits[4] = hit;
1059
1060 /* If we had a hit in this block, include it into mute fragment */
1061 if (squelch && hit) {
1062 if (mute.end < sample - MF_GSIZE) {
1063 /* There is a gap between fragments */
1064 mute_fragment(dsp, &mute);
1065 mute.start = (sample > MF_GSIZE) ? (sample - MF_GSIZE) : 0;
1066 }
1067 mute.end = limit + MF_GSIZE;
1068 }
1069
1070 /* Reinitialise the detector for the next block */
1071 for (i = 0; i < 6; i++) {
1072 goertzel_reset(&s->td.mf.tone_out[i]);
1073 }
1074 s->td.mf.current_sample = 0;
1075 }
1076
1077 if (squelch && mute.end) {
1078 if (mute.end > samples) {
1079 s->td.mf.mute_samples = mute.end - samples;
1080 mute.end = samples;
1081 }
1082 mute_fragment(dsp, &mute);
1083 }
1084
1085 return (s->td.mf.current_hit); /* return the debounced hit */
1086}
1087
1088static int r2_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[],
1089 int samples, int squelch, int relax, const char *r2_positions)
1090{
1091 float energy[6];
1092 int best;
1093 int second_best;
1094 int i;
1095 int j;
1096 int sample;
1097 short samp;
1098 int hit;
1099 int limit;
1100 fragment_t mute = {0, 0};
1101
1102 if (squelch && s->td.mf.mute_samples > 0) {
1103 mute.end = (s->td.mf.mute_samples < samples) ? s->td.mf.mute_samples : samples;
1104 s->td.mf.mute_samples -= mute.end;
1105 }
1106
1107 hit = 0;
1108 for (sample = 0; sample < samples; sample = limit) {
1109 if ((samples - sample) >= (R2_GSIZE - s->td.mf.current_sample)) {
1110 limit = sample + (R2_GSIZE - s->td.mf.current_sample);
1111 } else {
1112 limit = samples;
1113 }
1114 /* The following unrolled loop takes only 35% (rough estimate) of the
1115 time of a rolled loop on the machine on which it was developed */
1116 for (j = sample; j < limit; j++) {
1117 /* With GCC 2.95, the following unrolled code seems to take about 35%
1118 (rough estimate) as long as a neat little 0-3 loop */
1119 samp = amp[j];
1120 goertzel_sample(s->td.mf.tone_out, samp);
1121 goertzel_sample(s->td.mf.tone_out + 1, samp);
1122 goertzel_sample(s->td.mf.tone_out + 2, samp);
1123 goertzel_sample(s->td.mf.tone_out + 3, samp);
1124 goertzel_sample(s->td.mf.tone_out + 4, samp);
1125 goertzel_sample(s->td.mf.tone_out + 5, samp);
1126 }
1127 s->td.mf.current_sample += (limit - sample);
1128 if (s->td.mf.current_sample < R2_GSIZE) {
1129 continue;
1130 }
1131 /* We're at the end of an MF detection block. */
1132 /* Find the two highest energies. The spec says to look for
1133 two tones and two tones only. Taking this literally -ie
1134 only two tones pass the minimum threshold - doesn't work
1135 well. The sinc function mess, due to rectangular windowing
1136 ensure that! Find the two highest energies and ensure they
1137 are considerably stronger than any of the others. */
1138 energy[0] = goertzel_result(&s->td.mf.tone_out[0]);
1139 energy[1] = goertzel_result(&s->td.mf.tone_out[1]);
1140 if (energy[0] > energy[1]) {
1141 best = 0;
1142 second_best = 1;
1143 } else {
1144 best = 1;
1145 second_best = 0;
1146 }
1147 /*endif*/
1148 for (i = 2; i < 6; i++) {
1149 energy[i] = goertzel_result(&s->td.mf.tone_out[i]);
1150 if (energy[i] >= energy[best]) {
1151 second_best = best;
1152 best = i;
1153 } else if (energy[i] >= energy[second_best]) {
1154 second_best = i;
1155 }
1156 }
1157 /* Basic signal level and twist tests */
1158 hit = 0;
1159 if (energy[best] >= R2_MF_THRESHOLD && energy[second_best] >= R2_MF_THRESHOLD
1160 && energy[best] < energy[second_best]*R2_MF_TWIST
1161 && energy[best] * R2_MF_TWIST > energy[second_best]) {
1162 /* Relative peak test */
1163 hit = -1;
1164 for (i = 0; i < 6; i++) {
1165 if (i != best && i != second_best) {
1166 if (energy[i]*R2_MF_RELATIVE_PEAK >= energy[second_best]) {
1167 /* The best two are not clearly the best */
1168 hit = 0;
1169 break;
1170 }
1171 }
1172 }
1173 }
1174 if (hit) {
1175 /* Get the values into ascending order */
1176 if (second_best < best) {
1177 i = best;
1178 best = second_best;
1179 second_best = i;
1180 }
1181 best = best * 5 + second_best - 1;
1182 hit = r2_positions[best];
1183
1184 if (relax) {
1185 /* Continuous tone detection.
1186 * The application is responsible for debouncing. */
1187 store_digit(s, hit);
1188 } else {
1189 /* Discrete digit detection.
1190 * Look for two successive similar results, with something different preceding.
1191 * This is a subset of the MF logic and seems to ensure discrete digit detection. */
1192 if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] && hit != s->td.mf.hits[2]) {
1193 store_digit(s, hit);
1194 }
1195 }
1196 } else {
1197 hit = 0;
1198 }
1199
1200 s->td.mf.current_hit = hit;
1201
1202 if (!relax) {
1203 s->td.mf.hits[0] = s->td.mf.hits[1];
1204 s->td.mf.hits[1] = s->td.mf.hits[2];
1205 s->td.mf.hits[2] = s->td.mf.hits[3];
1206 s->td.mf.hits[3] = s->td.mf.hits[4];
1207 s->td.mf.hits[4] = hit;
1208 }
1209
1210 /* If we had a hit in this block, include it into mute fragment */
1211 if (squelch && hit) {
1212 if (mute.end < sample - R2_GSIZE) {
1213 /* There is a gap between fragments */
1214 mute_fragment(dsp, &mute);
1215 mute.start = (sample > R2_GSIZE) ? (sample - R2_GSIZE) : 0;
1216 }
1217 mute.end = limit + R2_GSIZE;
1218 }
1219
1220 /* Reinitialise the detector for the next block */
1221 for (i = 0; i < 6; i++) {
1222 goertzel_reset(&s->td.mf.tone_out[i]);
1223 }
1224 s->td.mf.current_sample = 0;
1225 }
1226
1227 if (squelch && mute.end) {
1228 if (mute.end > samples) {
1229 s->td.mf.mute_samples = mute.end - samples;
1230 mute.end = samples;
1231 }
1232 mute_fragment(dsp, &mute);
1233 }
1234
1235 return (s->td.mf.current_hit);
1236}
1237
1238static inline int pair_there(float p1, float p2, float i1, float i2, float e)
1239{
1240 /* See if p1 and p2 are there, relative to i1 and i2 and total energy */
1241 /* Make sure absolute levels are high enough */
1242 if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) {
1243 return 0;
1244 }
1245 /* Amplify ignored stuff */
1246 i2 *= TONE_THRESH;
1247 i1 *= TONE_THRESH;
1248 e *= TONE_THRESH;
1249 /* Check first tone */
1250 if ((p1 < i1) || (p1 < i2) || (p1 < e)) {
1251 return 0;
1252 }
1253 /* And second */
1254 if ((p2 < i1) || (p2 < i2) || (p2 < e)) {
1255 return 0;
1256 }
1257 /* Guess it's there... */
1258 return 1;
1259}
1260
1261static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len)
1262{
1263 short samp;
1264 int x;
1265 int y;
1266 int pass;
1267 int newstate = DSP_TONE_STATE_SILENCE;
1268 int res = 0;
1269 int freqcount = dsp->freqcount > FREQ_ARRAY_SIZE ? FREQ_ARRAY_SIZE : dsp->freqcount;
1270
1271 while (len) {
1272 /* Take the lesser of the number of samples we need and what we have */
1273 pass = len;
1274 if (pass > dsp->gsamp_size - dsp->gsamps) {
1275 pass = dsp->gsamp_size - dsp->gsamps;
1276 }
1277 for (x = 0; x < pass; x++) {
1278 samp = s[x];
1279 dsp->genergy += (int32_t) samp * (int32_t) samp;
1280 for (y = 0; y < freqcount; y++) {
1281 goertzel_sample(&dsp->freqs[y], samp);
1282 }
1283 }
1284 s += pass;
1285 dsp->gsamps += pass;
1286 len -= pass;
1287 if (dsp->gsamps == dsp->gsamp_size) {
1288 float hz[FREQ_ARRAY_SIZE];
1289 for (y = 0; y < FREQ_ARRAY_SIZE; y++) {
1290 hz[y] = goertzel_result(&dsp->freqs[y]);
1291 }
1292 switch (dsp->progmode) {
1293 case PROG_MODE_NA:
1294 if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) {
1295 newstate = DSP_TONE_STATE_BUSY;
1296 } else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
1297 newstate = DSP_TONE_STATE_RINGING;
1298 } else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
1299 newstate = DSP_TONE_STATE_DIALTONE;
1300 } else if (hz[HZ_950] > TONE_MIN_THRESH * TONE_THRESH) {
1301 newstate = DSP_TONE_STATE_SPECIAL1;
1302 } else if (hz[HZ_1400] > TONE_MIN_THRESH * TONE_THRESH) {
1303 /* End of SPECIAL1 or middle of SPECIAL2 */
1305 newstate = DSP_TONE_STATE_SPECIAL2;
1306 }
1307 } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) {
1308 /* End of SPECIAL2 or middle of SPECIAL3 */
1310 newstate = DSP_TONE_STATE_SPECIAL3;
1311 }
1312 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
1313 newstate = DSP_TONE_STATE_TALKING;
1314 } else {
1315 newstate = DSP_TONE_STATE_SILENCE;
1316 }
1317 break;
1318 case PROG_MODE_CR:
1319 if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) {
1320 newstate = DSP_TONE_STATE_RINGING;
1321 } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) {
1322 newstate = DSP_TONE_STATE_TALKING;
1323 } else {
1324 newstate = DSP_TONE_STATE_SILENCE;
1325 }
1326 break;
1327 case PROG_MODE_UK:
1328 if (hz[HZ_400UK] > TONE_MIN_THRESH * TONE_THRESH) {
1329 newstate = DSP_TONE_STATE_HUNGUP;
1330 } else if (pair_there(hz[HZ_350UK], hz[HZ_440UK], hz[HZ_400UK], hz[HZ_400UK], dsp->genergy)) {
1331 newstate = DSP_TONE_STATE_DIALTONE;
1332 }
1333 break;
1334 default:
1335 ast_log(LOG_WARNING, "Can't process in unknown prog mode '%u'\n", dsp->progmode);
1336 }
1337 if (newstate == dsp->tstate) {
1338 dsp->tcount++;
1339 if (dsp->ringtimeout) {
1340 dsp->ringtimeout++;
1341 }
1342 switch (dsp->tstate) {
1344 if ((dsp->features & DSP_PROGRESS_RINGING) &&
1345 (dsp->tcount == THRESH_RING)) {
1346 res = AST_CONTROL_RINGING;
1347 dsp->ringtimeout = 1;
1348 }
1349 break;
1351 if ((dsp->features & DSP_PROGRESS_BUSY) &&
1352 (dsp->tcount == THRESH_BUSY)) {
1353 res = AST_CONTROL_BUSY;
1354 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1355 }
1356 break;
1358 if ((dsp->features & DSP_PROGRESS_TALK) &&
1359 (dsp->tcount == THRESH_TALK)) {
1360 res = AST_CONTROL_ANSWER;
1361 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1362 }
1363 break;
1365 if ((dsp->features & DSP_PROGRESS_CONGESTION) &&
1366 (dsp->tcount == THRESH_CONGESTION)) {
1368 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1369 }
1370 break;
1372 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
1373 (dsp->tcount == THRESH_HANGUP)) {
1374 res = AST_CONTROL_HANGUP;
1375 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1376 }
1377 break;
1378 }
1379 if (dsp->ringtimeout == THRESH_RING2ANSWER) {
1380 ast_debug(1, "Consider call as answered because of timeout after last ring\n");
1381 res = AST_CONTROL_ANSWER;
1382 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1383 }
1384 } else {
1385 ast_debug(5, "Stop state %d with duration %d\n", dsp->tstate, dsp->tcount);
1386 ast_debug(5, "Start state %d\n", newstate);
1387 dsp->tstate = newstate;
1388 dsp->tcount = 1;
1389 }
1390
1391 /* Reset goertzel */
1392 for (x = 0; x < 7; x++) {
1393 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
1394 }
1395 dsp->gsamps = 0;
1396 dsp->genergy = 0.0;
1397 }
1398 }
1399
1400 return res;
1401}
1402
1403int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf)
1404{
1405 if (inf->frametype != AST_FRAME_VOICE) {
1406 ast_log(LOG_WARNING, "Can't check call progress of non-voice frames\n");
1407 return 0;
1408 }
1410 ast_log(LOG_WARNING, "Can only check call progress in signed-linear frames, %s not supported\n",
1412 return 0;
1413 }
1414 return __ast_dsp_call_progress(dsp, inf->data.ptr, inf->datalen / 2);
1415}
1416
1417static int __ast_dsp_silence_noise(struct ast_dsp *dsp, short *s, int len, int *totalsilence, int *totalnoise, int *frames_energy)
1418{
1419 int accum;
1420 int x;
1421 int res = 0;
1422
1423 if (!len) {
1424 return 0;
1425 }
1426 accum = 0;
1427 for (x = 0; x < len; x++) {
1428 accum += abs(s[x]);
1429 }
1430 accum /= len;
1431 if (accum < dsp->threshold) {
1432 /* Silent */
1433 dsp->totalsilence += len / (dsp->sample_rate / 1000);
1434 if (dsp->totalnoise) {
1435 /* Move and save history */
1436 memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicnoise[0]));
1437 dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
1438/* we don't want to check for busydetect that frequently */
1439#if 0
1440 dsp->busymaybe = 1;
1441#endif
1442 }
1443 dsp->totalnoise = 0;
1444 res = 1;
1445 } else {
1446 /* Not silent */
1447 dsp->totalnoise += len / (dsp->sample_rate / 1000);
1448 if (dsp->totalsilence) {
1449 int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
1450 int silence2 = dsp->historicsilence[DSP_HISTORY - 2];
1451 /* Move and save history */
1452 memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount * sizeof(dsp->historicsilence[0]));
1453 dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
1454 /* check if the previous sample differs only by BUSY_PERCENT from the one before it */
1455 if (silence1 < silence2) {
1456 if (silence1 + silence1 * BUSY_PERCENT / 100 >= silence2) {
1457 dsp->busymaybe = 1;
1458 } else {
1459 dsp->busymaybe = 0;
1460 }
1461 } else {
1462 if (silence1 - silence1 * BUSY_PERCENT / 100 <= silence2) {
1463 dsp->busymaybe = 1;
1464 } else {
1465 dsp->busymaybe = 0;
1466 }
1467 }
1468 }
1469 dsp->totalsilence = 0;
1470 }
1471 if (totalsilence) {
1472 *totalsilence = dsp->totalsilence;
1473 }
1474 if (totalnoise) {
1475 *totalnoise = dsp->totalnoise;
1476 }
1477 if (frames_energy) {
1478 *frames_energy = accum;
1479 }
1480 return res;
1481}
1482
1484{
1485 int res = 0, x;
1486#ifndef BUSYDETECT_TONEONLY
1487 int avgsilence = 0, hitsilence = 0;
1488#endif
1489 int avgtone = 0, hittone = 0;
1490
1491 /* if we have a 4 length pattern, the way busymaybe is set doesn't help us. */
1492 if (dsp->busy_cadence.length != 4) {
1493 if (!dsp->busymaybe) {
1494 return res;
1495 }
1496 }
1497
1498 for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
1499#ifndef BUSYDETECT_TONEONLY
1500 avgsilence += dsp->historicsilence[x];
1501#endif
1502 avgtone += dsp->historicnoise[x];
1503 }
1504#ifndef BUSYDETECT_TONEONLY
1505 avgsilence /= dsp->busycount;
1506#endif
1507 avgtone /= dsp->busycount;
1508 for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
1509#ifndef BUSYDETECT_TONEONLY
1510 if (avgsilence > dsp->historicsilence[x]) {
1511 if (avgsilence - (avgsilence * BUSY_PERCENT / 100) <= dsp->historicsilence[x]) {
1512 hitsilence++;
1513 }
1514 } else {
1515 if (avgsilence + (avgsilence * BUSY_PERCENT / 100) >= dsp->historicsilence[x]) {
1516 hitsilence++;
1517 }
1518 }
1519#endif
1520 if (avgtone > dsp->historicnoise[x]) {
1521 if (avgtone - (avgtone * BUSY_PERCENT / 100) <= dsp->historicnoise[x]) {
1522 hittone++;
1523 }
1524 } else {
1525 if (avgtone + (avgtone * BUSY_PERCENT / 100) >= dsp->historicnoise[x]) {
1526 hittone++;
1527 }
1528 }
1529 }
1530#ifndef BUSYDETECT_TONEONLY
1531 if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) &&
1532 (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) &&
1533 (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX))
1534#else
1535 if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX))
1536#endif
1537 {
1538#ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
1539 if (avgtone > avgsilence) {
1540 if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) {
1541 res = 1;
1542 }
1543 } else {
1544 if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) {
1545 res = 1;
1546 }
1547 }
1548#else
1549 res = 1;
1550#endif
1551 }
1552
1553 /* If we have a 4-length pattern, we can go ahead and just check it in a different way. */
1554 if (dsp->busy_cadence.length == 4) {
1555 int x;
1556 int errors = 0;
1557 int errors_max = ((4 * dsp->busycount) / 100.0) * BUSY_PAT_PERCENT;
1558
1559 for (x = DSP_HISTORY - (dsp->busycount); x < DSP_HISTORY; x += 2) {
1560 int temp_error;
1561 temp_error = abs(dsp->historicnoise[x] - dsp->busy_cadence.pattern[0]);
1562 if ((temp_error * 100) / dsp->busy_cadence.pattern[0] > BUSY_PERCENT) {
1563 errors++;
1564 }
1565
1566 temp_error = abs(dsp->historicnoise[x + 1] - dsp->busy_cadence.pattern[2]);
1567 if ((temp_error * 100) / dsp->busy_cadence.pattern[2] > BUSY_PERCENT) {
1568 errors++;
1569 }
1570
1571 temp_error = abs(dsp->historicsilence[x] - dsp->busy_cadence.pattern[1]);
1572 if ((temp_error * 100) / dsp->busy_cadence.pattern[1] > BUSY_PERCENT) {
1573 errors++;
1574 }
1575
1576 temp_error = abs(dsp->historicsilence[x + 1] - dsp->busy_cadence.pattern[3]);
1577 if ((temp_error * 100) / dsp->busy_cadence.pattern[3] > BUSY_PERCENT) {
1578 errors++;
1579 }
1580 }
1581
1582 ast_debug(5, "errors = %d max = %d\n", errors, errors_max);
1583
1584 if (errors <= errors_max) {
1585 return 1;
1586 }
1587 }
1588
1589 /* If we know the expected busy tone length, check we are in the range */
1590 if (res && (dsp->busy_cadence.pattern[0] > 0)) {
1591 if (abs(avgtone - dsp->busy_cadence.pattern[0]) > MAX(dsp->busy_cadence.pattern[0]*BUSY_PAT_PERCENT/100, 20)) {
1592#ifdef BUSYDETECT_DEBUG
1593 ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n",
1594 avgtone, dsp->busy_cadence.pattern[0]);
1595#endif
1596 res = 0;
1597 }
1598 }
1599#ifndef BUSYDETECT_TONEONLY
1600 /* If we know the expected busy tone silent-period length, check we are in the range */
1601 if (res && (dsp->busy_cadence.pattern[1] > 0)) {
1602 if (abs(avgsilence - dsp->busy_cadence.pattern[1]) > MAX(dsp->busy_cadence.pattern[1]*BUSY_PAT_PERCENT/100, 20)) {
1603#ifdef BUSYDETECT_DEBUG
1604 ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n",
1605 avgsilence, dsp->busy_cadence.pattern[1]);
1606#endif
1607 res = 0;
1608 }
1609 }
1610#endif
1611#if !defined(BUSYDETECT_TONEONLY) && defined(BUSYDETECT_DEBUG)
1612 if (res) {
1613 ast_debug(5, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
1614 } else {
1615 ast_debug(5, "busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
1616 }
1617#endif
1618 return res;
1619}
1620
1621static int ast_dsp_silence_noise_with_energy(struct ast_dsp *dsp, struct ast_frame *f, int *total, int *frames_energy, int noise)
1622{
1623 short *s;
1624 int len;
1625 int x;
1626 unsigned char *odata;
1627
1628 if (!f) {
1629 return 0;
1630 }
1631
1632 if (f->frametype != AST_FRAME_VOICE) {
1633 ast_log(LOG_WARNING, "Can't calculate silence on a non-voice frame\n");
1634 return 0;
1635 }
1636
1638 s = f->data.ptr;
1639 len = f->datalen/2;
1640 } else {
1641 odata = f->data.ptr;
1642 len = f->datalen;
1644 s = ast_alloca(len * 2);
1645 for (x = 0; x < len; x++) {
1646 s[x] = AST_MULAW(odata[x]);
1647 }
1649 s = ast_alloca(len * 2);
1650 for (x = 0; x < len; x++) {
1651 s[x] = AST_ALAW(odata[x]);
1652 }
1653 } else {
1654 ast_log(LOG_WARNING, "Can only calculate silence on signed-linear, alaw or ulaw frames, %s not supported\n",
1656 return 0;
1657 }
1658 }
1659
1660 if (noise) {
1661 return __ast_dsp_silence_noise(dsp, s, len, NULL, total, frames_energy);
1662 } else {
1663 return __ast_dsp_silence_noise(dsp, s, len, total, NULL, frames_energy);
1664 }
1665}
1666
1667int ast_dsp_silence_with_energy(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence, int *frames_energy)
1668{
1669 return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, frames_energy, 0);
1670}
1671
1672int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
1673{
1674 return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, NULL, 0);
1675}
1676
1677int ast_dsp_noise(struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise)
1678{
1679 return ast_dsp_silence_noise_with_energy(dsp, f, totalnoise, NULL, 1);
1680}
1681
1682
1683struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af)
1684{
1685 int silence;
1686 int res;
1687 int digit = 0, fax_digit = 0, custom_freq_digit = 0;
1688 int x;
1689 short *shortdata;
1690 unsigned char *odata;
1691 int len;
1692 struct ast_frame *outf = NULL;
1693
1694 if (!af) {
1695 return NULL;
1696 }
1697 if (af->frametype != AST_FRAME_VOICE) {
1698 return af;
1699 }
1700
1701 odata = af->data.ptr;
1702 len = af->datalen;
1703 /* Make sure we have short data */
1705 shortdata = af->data.ptr;
1706 len = af->datalen / 2;
1708 shortdata = ast_alloca(af->datalen * 2);
1709 for (x = 0; x < len; x++) {
1710 shortdata[x] = AST_MULAW(odata[x]);
1711 }
1713 shortdata = ast_alloca(af->datalen * 2);
1714 for (x = 0; x < len; x++) {
1715 shortdata[x] = AST_ALAW(odata[x]);
1716 }
1717 } else {
1718 /* Display warning only once. Otherwise you would get hundreds of warnings every second */
1719 if (dsp->display_inband_dtmf_warning) {
1720 /* If DTMF is enabled for the DSP, try to be helpful and warn about that specifically,
1721 * otherwise emit a more generic message that covers all other cases. */
1723 ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n",
1725 } else {
1726 ast_log(LOG_WARNING, "Can only do DSP on signed-linear, alaw or ulaw frames (%s not supported)\n",
1728 }
1729 }
1731 return af;
1732 }
1733
1734 /* Initially we do not want to mute anything */
1735 dsp->mute_fragments = 0;
1736
1737 /* Need to run the silence detection stuff for silence suppression and busy detection */
1739 res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL, NULL);
1740 }
1741
1742 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
1743 memset(&dsp->f, 0, sizeof(dsp->f));
1744 dsp->f.frametype = AST_FRAME_NULL;
1745 ast_frfree(af);
1746 return ast_frisolate(&dsp->f);
1747 }
1750 memset(&dsp->f, 0, sizeof(dsp->f));
1753 ast_frfree(af);
1754 ast_debug(1, "Requesting Hangup because the busy tone was detected on channel %s\n", ast_channel_name(chan));
1755 return ast_frisolate(&dsp->f);
1756 }
1757
1758 if ((dsp->features & DSP_FEATURE_FAX_DETECT)) {
1759 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CNG) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) {
1760 fax_digit = 'f';
1761 }
1762
1763 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) {
1764 fax_digit = 'e';
1765 }
1766 }
1767
1768 if ((dsp->features & DSP_FEATURE_FREQ_DETECT)) {
1769 if ((dsp->freqmode) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) {
1770 custom_freq_digit = 'q';
1771 }
1772 }
1773
1777 } else if (dsp->digitmode & DSP_DIGITMODE_MF) {
1778 digit = mf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
1779 } else {
1780 digit = dtmf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF));
1781 }
1782
1783 if (dsp->digit_state.current_digits) {
1784 int event = 0, event_len = 0;
1785 char event_digit = 0;
1786
1787 if (!dsp->dtmf_began) {
1788 /* We have not reported DTMF_BEGIN for anything yet */
1789
1791 event = AST_FRAME_DTMF_BEGIN;
1792 event_digit = dsp->digit_state.digits[0];
1793 }
1794 dsp->dtmf_began = 1;
1795 } else if (dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) {
1796 /* Digit changed. This means digit we have reported with DTMF_BEGIN ended */
1798 event = AST_FRAME_DTMF_END;
1799 event_digit = dsp->digit_state.digits[0];
1800 event_len = dsp->digit_state.digitlen[0] * 1000 / dsp->sample_rate;
1801 }
1802 memmove(&dsp->digit_state.digits[0], &dsp->digit_state.digits[1], dsp->digit_state.current_digits);
1803 memmove(&dsp->digit_state.digitlen[0], &dsp->digit_state.digitlen[1], dsp->digit_state.current_digits * sizeof(dsp->digit_state.digitlen[0]));
1805 dsp->dtmf_began = 0;
1806
1807 if (dsp->features & DSP_FEATURE_BUSY_DETECT) {
1808 /* Reset Busy Detector as we have some confirmed activity */
1809 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
1810 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
1811 ast_debug(1, "DTMF Detected - Reset busydetector\n");
1812 }
1813 }
1814
1815 if (event) {
1816 memset(&dsp->f, 0, sizeof(dsp->f));
1817 dsp->f.frametype = event;
1818 dsp->f.subclass.integer = event_digit;
1819 dsp->f.len = event_len;
1820 outf = &dsp->f;
1821 goto done;
1822 }
1823 }
1824 }
1825
1826 if (fax_digit) {
1827 /* Fax was detected - digit is either 'f' or 'e' */
1828
1829 memset(&dsp->f, 0, sizeof(dsp->f));
1830 dsp->f.frametype = AST_FRAME_DTMF;
1831 dsp->f.subclass.integer = fax_digit;
1832 outf = &dsp->f;
1833 goto done;
1834 }
1835
1836 if (custom_freq_digit) {
1837 /* Custom frequency was detected - digit is 'q' */
1838
1839 memset(&dsp->f, 0, sizeof(dsp->f));
1840 dsp->f.frametype = AST_FRAME_DTMF;
1841 dsp->f.subclass.integer = custom_freq_digit;
1842 outf = &dsp->f;
1843 goto done;
1844 }
1845
1846 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
1847 res = __ast_dsp_call_progress(dsp, shortdata, len);
1848 if (res) {
1849 switch (res) {
1850 case AST_CONTROL_ANSWER:
1851 case AST_CONTROL_BUSY:
1854 case AST_CONTROL_HANGUP:
1855 memset(&dsp->f, 0, sizeof(dsp->f));
1857 dsp->f.subclass.integer = res;
1858 dsp->f.src = "dsp_progress";
1859 if (chan) {
1860 ast_queue_frame(chan, &dsp->f);
1861 }
1862 break;
1863 default:
1864 ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res);
1865 }
1866 }
1867 } else if ((dsp->features & DSP_FEATURE_WAITDIALTONE)) {
1868 res = __ast_dsp_call_progress(dsp, shortdata, len);
1869 }
1870
1871done:
1872 /* Mute fragment of the frame */
1873 for (x = 0; x < dsp->mute_fragments; x++) {
1874 memset(shortdata + dsp->mute_data[x].start, 0, sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start));
1875 }
1876
1878 for (x = 0; x < len; x++) {
1879 odata[x] = AST_LIN2MU((unsigned short) shortdata[x]);
1880 }
1882 for (x = 0; x < len; x++) {
1883 odata[x] = AST_LIN2A((unsigned short) shortdata[x]);
1884 }
1885 }
1886
1887 if (outf) {
1888 if (chan) {
1889 ast_queue_frame(chan, af);
1890 }
1891 ast_frfree(af);
1892 return ast_frisolate(outf);
1893 } else {
1894 return af;
1895 }
1896}
1897
1898static void ast_dsp_prog_reset(struct ast_dsp *dsp)
1899{
1900 int max = 0;
1901 int x;
1902
1903 dsp->gsamp_size = modes[dsp->progmode].size;
1904 dsp->gsamps = 0;
1905 for (x = 0; x < FREQ_ARRAY_SIZE; x++) {
1906 if (modes[dsp->progmode].freqs[x]) {
1907 goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->sample_rate);
1908 max = x + 1;
1909 }
1910 }
1911 dsp->freqcount = max;
1912 dsp->ringtimeout = 0;
1913}
1914
1915unsigned int ast_dsp_get_sample_rate(const struct ast_dsp *dsp)
1916{
1917 return dsp->sample_rate;
1918}
1919
1920static struct ast_dsp *__ast_dsp_new(unsigned int sample_rate)
1921{
1922 struct ast_dsp *dsp;
1923
1924 if ((dsp = ast_calloc(1, sizeof(*dsp)))) {
1927 dsp->busycount = DSP_HISTORY;
1930 dsp->sample_rate = sample_rate;
1931 dsp->freqcount = 0;
1932 /* Initialize digit detector */
1935 /* Initialize initial DSP progress detect parameters */
1936 ast_dsp_prog_reset(dsp);
1937 /* Initialize fax detector */
1939 }
1940 return dsp;
1941}
1942
1944{
1946}
1947
1949{
1950 return __ast_dsp_new(sample_rate);
1951}
1952
1954{
1955 dsp->features = features;
1958 }
1959}
1960
1961
1963{
1964 return (dsp->features);
1965}
1966
1967
1968void ast_dsp_free(struct ast_dsp *dsp)
1969{
1970 ast_free(dsp);
1971}
1972
1974{
1975 dsp->threshold = threshold;
1976}
1977
1979{
1980 if (cadences < 4) {
1981 cadences = 4;
1982 }
1983 if (cadences > DSP_HISTORY) {
1985 }
1986 dsp->busycount = cadences;
1987}
1988
1989void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, const struct ast_dsp_busy_pattern *cadence)
1990{
1991 dsp->busy_cadence = *cadence;
1992 ast_debug(1, "dsp busy pattern set to %d,%d,%d,%d\n", cadence->pattern[0], cadence->pattern[1], (cadence->length == 4) ? cadence->pattern[2] : 0, (cadence->length == 4) ? cadence->pattern[3] : 0);
1993}
1994
1996{
1997 int i;
1998
1999 dsp->dtmf_began = 0;
2002 /* Reinitialise the detector for the next block */
2003 for (i = 0; i < 6; i++) {
2004 goertzel_reset(&s->tone_out[i]);
2005 }
2006 s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = 0;
2007 s->current_hit = 0;
2008 s->current_sample = 0;
2009 } else {
2011 /* Reinitialise the detector for the next block */
2012 for (i = 0; i < 4; i++) {
2013 goertzel_reset(&s->row_out[i]);
2014 goertzel_reset(&s->col_out[i]);
2015 }
2016 s->lasthit = 0;
2017 s->current_hit = 0;
2018 s->energy = 0.0;
2019 s->current_sample = 0;
2020 s->hits = 0;
2021 s->misses = 0;
2022 }
2023
2024 dsp->digit_state.digits[0] = '\0';
2025 dsp->digit_state.current_digits = 0;
2026}
2027
2028void ast_dsp_reset(struct ast_dsp *dsp)
2029{
2030 int x;
2031
2032 dsp->totalsilence = 0;
2033 dsp->gsamps = 0;
2034 for (x = 0; x < 4; x++) {
2035 dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0;
2036 }
2037 memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence));
2038 memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise));
2039 dsp->ringtimeout = 0;
2040}
2041
2042#define DSP_DIGITMODES (DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MF | DSP_DIGITMODE_R2_FORWARD | DSP_DIGITMODE_R2_BACKWARD)
2043
2045{
2046 int new;
2047 int old;
2048
2051 if (old != new) {
2052 /* Must initialize structures if switching from MF to DTMF or vice-versa */
2054 }
2055 dsp->digitmode = digitmode;
2056 return 0;
2057}
2058
2059int ast_dsp_set_freqmode(struct ast_dsp *dsp, int freq, int dur, int db, int squelch)
2060{
2061 if (freq > 0) {
2062 dsp->freqmode = 1;
2063 ast_freq_detect_init(dsp, freq, dur, db, squelch);
2064 } else {
2065 dsp->freqmode = 0;
2066 }
2067 return 0;
2068}
2069
2071{
2072 if (dsp->faxmode != faxmode) {
2073 dsp->faxmode = faxmode;
2075 }
2076 return 0;
2077}
2078
2079int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
2080{
2081 int x;
2082
2083 for (x = 0; x < ARRAY_LEN(aliases); x++) {
2084 if (!strcasecmp(aliases[x].name, zone)) {
2085 dsp->progmode = aliases[x].mode;
2086 ast_dsp_prog_reset(dsp);
2087 return 0;
2088 }
2089 }
2090 return -1;
2091}
2092
2094{
2095 return (dsp->mute_fragments > 0);
2096}
2097
2099{
2100 return dsp->tstate;
2101}
2102
2104{
2105 return dsp->tcount;
2106}
2107
2108static int _dsp_init(int reload)
2109{
2110 struct ast_config *cfg;
2111 struct ast_variable *v;
2112 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2113 int cfg_threshold;
2114 float cfg_twist;
2115
2116 if ((cfg = ast_config_load2(CONFIG_FILE_NAME, "dsp", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
2117 return 0;
2118 }
2119
2127
2129 return 0;
2130 }
2131
2132 for (v = ast_variable_browse(cfg, "default"); v; v = v->next) {
2133 if (!strcasecmp(v->name, "silencethreshold")) {
2134 if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
2135 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
2136 } else if (cfg_threshold < 0) {
2137 ast_log(LOG_WARNING, "Invalid silence threshold '%d' specified, using default\n", cfg_threshold);
2138 } else {
2139 thresholds[THRESHOLD_SILENCE] = cfg_threshold;
2140 }
2141 } else if (!strcasecmp(v->name, "dtmf_normal_twist")) {
2142 if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
2143 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
2144 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
2145 ast_log(LOG_WARNING, "Invalid dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_normal_twist);
2146 } else {
2147 dtmf_normal_twist = cfg_twist;
2148 }
2149 } else if (!strcasecmp(v->name, "dtmf_reverse_twist")) {
2150 if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
2151 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
2152 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
2153 ast_log(LOG_WARNING, "Invalid dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_reverse_twist);
2154 } else {
2155 dtmf_reverse_twist = cfg_twist;
2156 }
2157 } else if (!strcasecmp(v->name, "relax_dtmf_normal_twist")) {
2158 if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
2159 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
2160 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
2161 ast_log(LOG_WARNING, "Invalid relax_dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_normal_twist);
2162 } else {
2163 relax_dtmf_normal_twist = cfg_twist;
2164 }
2165 } else if (!strcasecmp(v->name, "relax_dtmf_reverse_twist")) {
2166 if (sscanf(v->value, "%30f", &cfg_twist) < 1) {
2167 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
2168 } else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) { /* < 3.0dB or > 20dB */
2169 ast_log(LOG_WARNING, "Invalid relax_dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_reverse_twist);
2170 } else {
2171 relax_dtmf_reverse_twist = cfg_twist;
2172 }
2173 } else if (!strcasecmp(v->name, "dtmf_hits_to_begin")) {
2174 if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
2175 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
2176 } else if (cfg_threshold < 1) { /* must be 1 or greater */
2177 ast_log(LOG_WARNING, "Invalid dtmf_hits_to_begin value '%d' specified, using default of %d\n", cfg_threshold, dtmf_hits_to_begin);
2178 } else {
2179 dtmf_hits_to_begin = cfg_threshold;
2180 }
2181 } else if (!strcasecmp(v->name, "dtmf_misses_to_end")) {
2182 if (sscanf(v->value, "%30d", &cfg_threshold) < 1) {
2183 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", v->value);
2184 } else if (cfg_threshold < 1) { /* must be 1 or greater */
2185 ast_log(LOG_WARNING, "Invalid dtmf_misses_to_end value '%d' specified, using default of %d\n", cfg_threshold, dtmf_misses_to_end);
2186 } else {
2187 dtmf_misses_to_end = cfg_threshold;
2188 }
2189 }
2190 }
2191 ast_config_destroy(cfg);
2192
2193 return 0;
2194}
2195
2197{
2198 return thresholds[which];
2199}
2200
2201#ifdef TEST_FRAMEWORK
2202static void test_tone_sample_gen(short *slin_buf, int samples, int rate, int freq, short amplitude)
2203{
2204 int idx;
2205 double sample_step = 2.0 * M_PI * freq / rate;/* radians per step */
2206
2207 for (idx = 0; idx < samples; ++idx) {
2208 slin_buf[idx] = amplitude * sin(sample_step * idx);
2209 }
2210}
2211#endif
2212
2213#ifdef TEST_FRAMEWORK
2214static void test_tone_sample_gen_add(short *slin_buf, int samples, int rate, int freq, short amplitude)
2215{
2216 int idx;
2217 double sample_step = 2.0 * M_PI * freq / rate;/* radians per step */
2218
2219 for (idx = 0; idx < samples; ++idx) {
2220 slin_buf[idx] += amplitude * sin(sample_step * idx);
2221 }
2222}
2223#endif
2224
2225#ifdef TEST_FRAMEWORK
2226static void test_dual_sample_gen(short *slin_buf, int samples, int rate, int f1, short a1, int f2, short a2)
2227{
2228 test_tone_sample_gen(slin_buf, samples, rate, f1, a1);
2229 test_tone_sample_gen_add(slin_buf, samples, rate, f2, a2);
2230}
2231#endif
2232
2233#ifdef TEST_FRAMEWORK
2234#define TONE_AMPLITUDE_MAX 0x7fff /* Max signed linear amplitude */
2235#define TONE_AMPLITUDE_MIN 80 /* Min signed linear amplitude detectable */
2236
2237static int test_tone_amplitude_sweep(struct ast_test *test, struct ast_dsp *dsp, tone_detect_state_t *tone_state)
2238{
2239 short slin_buf[tone_state->block_size];
2240 int result;
2241 int idx;
2242 struct {
2243 short amp_val;
2244 int detect;
2245 } amp_tests[] = {
2246 { .amp_val = TONE_AMPLITUDE_MAX, .detect = 1, },
2247 { .amp_val = 10000, .detect = 1, },
2248 { .amp_val = 1000, .detect = 1, },
2249 { .amp_val = 100, .detect = 1, },
2250 { .amp_val = TONE_AMPLITUDE_MIN, .detect = 1, },
2251 { .amp_val = 75, .detect = 0, },
2252 { .amp_val = 10, .detect = 0, },
2253 { .amp_val = 1, .detect = 0, },
2254 };
2255
2256 result = 0;
2257
2258 for (idx = 0; idx < ARRAY_LEN(amp_tests); ++idx) {
2259 int detected;
2260 int duration;
2261
2262 ast_debug(1, "Test %d Hz at amplitude %d\n",
2263 tone_state->freq, amp_tests[idx].amp_val);
2264 test_tone_sample_gen(slin_buf, tone_state->block_size, DEFAULT_SAMPLE_RATE,
2265 tone_state->freq, amp_tests[idx].amp_val);
2266
2267 detected = 0;
2268 for (duration = 0; !detected && duration < tone_state->hits_required + 3; ++duration) {
2269 detected = tone_detect(dsp, tone_state, slin_buf, tone_state->block_size) ? 1 : 0;
2270 }
2271 if (amp_tests[idx].detect != detected) {
2272 /*
2273 * Both messages are needed. ast_debug for when figuring out
2274 * what went wrong and the test update for normal output before
2275 * you start debugging. The different logging methods are not
2276 * synchronized.
2277 */
2278 ast_debug(1,
2279 "Test %d Hz at amplitude %d failed. Detected: %s\n",
2280 tone_state->freq, amp_tests[idx].amp_val,
2281 detected ? "yes" : "no");
2283 "Test %d Hz at amplitude %d failed. Detected: %s\n",
2284 tone_state->freq, amp_tests[idx].amp_val,
2285 detected ? "yes" : "no");
2286 result = -1;
2287 }
2288 tone_state->hit_count = 0;
2289 }
2290
2291 return result;
2292}
2293#endif
2294
2295#ifdef TEST_FRAMEWORK
2296static int test_dtmf_amplitude_sweep(struct ast_test *test, struct ast_dsp *dsp, int digit_index)
2297{
2298 short slin_buf[DTMF_GSIZE];
2299 int result;
2300 int row;
2301 int column;
2302 int idx;
2303 struct {
2304 short amp_val;
2305 int digit;
2306 } amp_tests[] = {
2307 /*
2308 * XXX Since there is no current DTMF level detection issue. This test
2309 * just checks the current detection levels.
2310 */
2311 { .amp_val = TONE_AMPLITUDE_MAX/2, .digit = dtmf_positions[digit_index], },
2312 { .amp_val = 10000, .digit = dtmf_positions[digit_index], },
2313 { .amp_val = 1000, .digit = dtmf_positions[digit_index], },
2314 { .amp_val = 500, .digit = dtmf_positions[digit_index], },
2315 { .amp_val = 250, .digit = dtmf_positions[digit_index], },
2316 { .amp_val = 200, .digit = dtmf_positions[digit_index], },
2317 { .amp_val = 180, .digit = dtmf_positions[digit_index], },
2318 /* Various digits detect and not detect in this range */
2319 { .amp_val = 170, .digit = 0, },
2320 { .amp_val = 100, .digit = 0, },
2321 /*
2322 * Amplitudes below TONE_AMPLITUDE_MIN start having questionable detection
2323 * over quantization and background noise.
2324 */
2325 { .amp_val = TONE_AMPLITUDE_MIN, .digit = 0, },
2326 { .amp_val = 75, .digit = 0, },
2327 { .amp_val = 10, .digit = 0, },
2328 { .amp_val = 1, .digit = 0, },
2329 };
2330
2331 row = (digit_index >> 2) & 0x03;
2332 column = digit_index & 0x03;
2333
2334 result = 0;
2335
2336 for (idx = 0; idx < ARRAY_LEN(amp_tests); ++idx) {
2337 int digit;
2338 int duration;
2339
2340 ast_debug(1, "Test '%c' at amplitude %d\n",
2341 dtmf_positions[digit_index], amp_tests[idx].amp_val);
2342 test_dual_sample_gen(slin_buf, ARRAY_LEN(slin_buf), DEFAULT_SAMPLE_RATE,
2343 (int) dtmf_row[row], amp_tests[idx].amp_val,
2344 (int) dtmf_col[column], amp_tests[idx].amp_val);
2345
2346 digit = 0;
2347 for (duration = 0; !digit && duration < 3; ++duration) {
2348 digit = dtmf_detect(dsp, &dsp->digit_state, slin_buf, ARRAY_LEN(slin_buf),
2349 0, 0);
2350 }
2351 if (amp_tests[idx].digit != digit) {
2352 /*
2353 * Both messages are needed. ast_debug for when figuring out
2354 * what went wrong and the test update for normal output before
2355 * you start debugging. The different logging methods are not
2356 * synchronized.
2357 */
2358 ast_debug(1,
2359 "Test '%c' at amplitude %d failed. Detected Digit: '%c'\n",
2360 dtmf_positions[digit_index], amp_tests[idx].amp_val,
2361 digit ?: ' ');
2363 "Test '%c' at amplitude %d failed. Detected Digit: '%c'\n",
2364 dtmf_positions[digit_index], amp_tests[idx].amp_val,
2365 digit ?: ' ');
2366 result = -1;
2367 }
2368 ast_dsp_digitreset(dsp);
2369 }
2370
2371 return result;
2372}
2373#endif
2374
2375#ifdef TEST_FRAMEWORK
2376static int test_dtmf_twist_sweep(struct ast_test *test, struct ast_dsp *dsp, int digit_index)
2377{
2378 short slin_buf[DTMF_GSIZE];
2379 int result;
2380 int row;
2381 int column;
2382 int idx;
2383 struct {
2384 short amp_row;
2385 short amp_col;
2386 int digit;
2387 } twist_tests[] = {
2388 /*
2389 * XXX Since there is no current DTMF twist detection issue. This test
2390 * just checks the current detection levels.
2391 *
2392 * Normal twist has the column higher than the row amplitude.
2393 * Reverse twist is the other way.
2394 */
2395 { .amp_row = 1000 + 1800, .amp_col = 1000 + 0, .digit = 0, },
2396 { .amp_row = 1000 + 1700, .amp_col = 1000 + 0, .digit = 0, },
2397 /* Various digits detect and not detect in this range */
2398 { .amp_row = 1000 + 1400, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
2399 { .amp_row = 1000 + 1300, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
2400 { .amp_row = 1000 + 1200, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
2401 { .amp_row = 1000 + 1100, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
2402 { .amp_row = 1000 + 1000, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
2403 { .amp_row = 1000 + 100, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
2404 { .amp_row = 1000 + 0, .amp_col = 1000 + 100, .digit = dtmf_positions[digit_index], },
2405 { .amp_row = 1000 + 0, .amp_col = 1000 + 200, .digit = dtmf_positions[digit_index], },
2406 { .amp_row = 1000 + 0, .amp_col = 1000 + 300, .digit = dtmf_positions[digit_index], },
2407 { .amp_row = 1000 + 0, .amp_col = 1000 + 400, .digit = dtmf_positions[digit_index], },
2408 { .amp_row = 1000 + 0, .amp_col = 1000 + 500, .digit = dtmf_positions[digit_index], },
2409 { .amp_row = 1000 + 0, .amp_col = 1000 + 550, .digit = dtmf_positions[digit_index], },
2410 /* Various digits detect and not detect in this range */
2411 { .amp_row = 1000 + 0, .amp_col = 1000 + 650, .digit = 0, },
2412 { .amp_row = 1000 + 0, .amp_col = 1000 + 700, .digit = 0, },
2413 { .amp_row = 1000 + 0, .amp_col = 1000 + 800, .digit = 0, },
2414 };
2415 float save_normal_twist;
2416 float save_reverse_twist;
2417
2418 save_normal_twist = dtmf_normal_twist;
2419 save_reverse_twist = dtmf_reverse_twist;
2422
2423 row = (digit_index >> 2) & 0x03;
2424 column = digit_index & 0x03;
2425
2426 result = 0;
2427
2428 for (idx = 0; idx < ARRAY_LEN(twist_tests); ++idx) {
2429 int digit;
2430 int duration;
2431
2432 ast_debug(1, "Test '%c' twist row %d col %d amplitudes\n",
2433 dtmf_positions[digit_index],
2434 twist_tests[idx].amp_row, twist_tests[idx].amp_col);
2435 test_dual_sample_gen(slin_buf, ARRAY_LEN(slin_buf), DEFAULT_SAMPLE_RATE,
2436 (int) dtmf_row[row], twist_tests[idx].amp_row,
2437 (int) dtmf_col[column], twist_tests[idx].amp_col);
2438
2439 digit = 0;
2440 for (duration = 0; !digit && duration < 3; ++duration) {
2441 digit = dtmf_detect(dsp, &dsp->digit_state, slin_buf, ARRAY_LEN(slin_buf),
2442 0, 0);
2443 }
2444 if (twist_tests[idx].digit != digit) {
2445 /*
2446 * Both messages are needed. ast_debug for when figuring out
2447 * what went wrong and the test update for normal output before
2448 * you start debugging. The different logging methods are not
2449 * synchronized.
2450 */
2451 ast_debug(1,
2452 "Test '%c' twist row %d col %d amplitudes failed. Detected Digit: '%c'\n",
2453 dtmf_positions[digit_index],
2454 twist_tests[idx].amp_row, twist_tests[idx].amp_col,
2455 digit ?: ' ');
2457 "Test '%c' twist row %d col %d amplitudes failed. Detected Digit: '%c'\n",
2458 dtmf_positions[digit_index],
2459 twist_tests[idx].amp_row, twist_tests[idx].amp_col,
2460 digit ?: ' ');
2461 result = -1;
2462 }
2463 ast_dsp_digitreset(dsp);
2464 }
2465
2466 dtmf_normal_twist = save_normal_twist;
2467 dtmf_reverse_twist = save_reverse_twist;
2468
2469 return result;
2470}
2471#endif
2472
2473#ifdef TEST_FRAMEWORK
2474static int test_tone_freq_sweep(struct ast_test *test, struct ast_dsp *dsp, tone_detect_state_t *tone_state, short amplitude)
2475{
2476 short slin_buf[tone_state->block_size];
2477 int result;
2478 int freq;
2479 int lower_freq;
2480 int upper_freq;
2481
2482 /* Calculate detection frequency range */
2483 lower_freq = tone_state->freq - 4;
2484 upper_freq = tone_state->freq + 4;
2485
2486 result = 0;
2487
2488 /* Sweep frequencies loop. */
2489 for (freq = 100; freq <= 3500; freq += 1) {
2490 int detected;
2491 int duration;
2492 int expect_detection;
2493
2494 if (freq == tone_state->freq) {
2495 /* This case is done by the amplitude sweep. */
2496 continue;
2497 }
2498
2499 expect_detection = (lower_freq <= freq && freq <= upper_freq) ? 1 : 0;
2500
2501 ast_debug(1, "Test %d Hz detection given %d Hz tone at amplitude %d. Range:%d-%d Expect detect: %s\n",
2502 tone_state->freq, freq, amplitude, lower_freq, upper_freq,
2503 expect_detection ? "yes" : "no");
2504 test_tone_sample_gen(slin_buf, tone_state->block_size, DEFAULT_SAMPLE_RATE, freq,
2505 amplitude);
2506
2507 detected = 0;
2508 for (duration = 0; !detected && duration < tone_state->hits_required + 3; ++duration) {
2509 detected = tone_detect(dsp, tone_state, slin_buf, tone_state->block_size) ? 1 : 0;
2510 }
2511 if (expect_detection != detected) {
2512 /*
2513 * Both messages are needed. ast_debug for when figuring out
2514 * what went wrong and the test update for normal output before
2515 * you start debugging. The different logging methods are not
2516 * synchronized.
2517 */
2518 ast_debug(1,
2519 "Test %d Hz detection given %d Hz tone at amplitude %d failed. Range:%d-%d Detected: %s\n",
2520 tone_state->freq, freq, amplitude, lower_freq, upper_freq,
2521 detected ? "yes" : "no");
2523 "Test %d Hz detection given %d Hz tone at amplitude %d failed. Range:%d-%d Detected: %s\n",
2524 tone_state->freq, freq, amplitude, lower_freq, upper_freq,
2525 detected ? "yes" : "no");
2526 result = -1;
2527 }
2528 tone_state->hit_count = 0;
2529 }
2530
2531 return result;
2532}
2533#endif
2534
2535#ifdef TEST_FRAMEWORK
2536AST_TEST_DEFINE(test_dsp_fax_detect)
2537{
2538 struct ast_dsp *dsp;
2540
2541 switch (cmd) {
2542 case TEST_INIT:
2543 info->name = "fax";
2544 info->category = "/main/dsp/";
2545 info->summary = "DSP fax tone detect unit test";
2546 info->description =
2547 "Tests fax tone detection code.";
2548 return AST_TEST_NOT_RUN;
2549 case TEST_EXECUTE:
2550 break;
2551 }
2552
2553 dsp = ast_dsp_new();
2554 if (!dsp) {
2555 return AST_TEST_FAIL;
2556 }
2557
2559
2560 /* Test CNG tone amplitude detection */
2561 if (test_tone_amplitude_sweep(test, dsp, &dsp->cng_tone_state)) {
2563 }
2564
2565 /* Test CED tone amplitude detection */
2566 if (test_tone_amplitude_sweep(test, dsp, &dsp->ced_tone_state)) {
2568 }
2569
2570 /* Test CNG tone frequency detection */
2571 if (test_tone_freq_sweep(test, dsp, &dsp->cng_tone_state, TONE_AMPLITUDE_MAX)) {
2573 }
2574 if (test_tone_freq_sweep(test, dsp, &dsp->cng_tone_state, TONE_AMPLITUDE_MIN)) {
2576 }
2577
2578 /* Test CED tone frequency detection */
2579 if (test_tone_freq_sweep(test, dsp, &dsp->ced_tone_state, TONE_AMPLITUDE_MAX)) {
2581 }
2582 if (test_tone_freq_sweep(test, dsp, &dsp->ced_tone_state, TONE_AMPLITUDE_MIN)) {
2584 }
2585
2586 ast_dsp_free(dsp);
2587 return result;
2588}
2589#endif
2590
2591#ifdef TEST_FRAMEWORK
2592AST_TEST_DEFINE(test_dsp_dtmf_detect)
2593{
2594 int idx;
2595 struct ast_dsp *dsp;
2597
2598 switch (cmd) {
2599 case TEST_INIT:
2600 info->name = "dtmf";
2601 info->category = "/main/dsp/";
2602 info->summary = "DSP DTMF detect unit test";
2603 info->description =
2604 "Tests DTMF detection code.";
2605 return AST_TEST_NOT_RUN;
2606 case TEST_EXECUTE:
2607 break;
2608 }
2609
2610 dsp = ast_dsp_new();
2611 if (!dsp) {
2612 return AST_TEST_FAIL;
2613 }
2614
2616
2617 for (idx = 0; dtmf_positions[idx]; ++idx) {
2618 if (test_dtmf_amplitude_sweep(test, dsp, idx)) {
2620 }
2621 }
2622
2623 for (idx = 0; dtmf_positions[idx]; ++idx) {
2624 if (test_dtmf_twist_sweep(test, dsp, idx)) {
2626 }
2627 }
2628
2629 ast_dsp_free(dsp);
2630 return result;
2631}
2632#endif
2633
2634static int unload_module(void)
2635{
2636 AST_TEST_UNREGISTER(test_dsp_fax_detect);
2637 AST_TEST_UNREGISTER(test_dsp_dtmf_detect);
2638
2639 return 0;
2640}
2641
2642static int load_module(void)
2643{
2644 if (_dsp_init(0)) {
2646 }
2647
2648 AST_TEST_REGISTER(test_dsp_fax_detect);
2649 AST_TEST_REGISTER(test_dsp_dtmf_detect);
2650
2652}
2653
2654static int reload_module(void)
2655{
2656 return _dsp_init(1);
2657}
2658
2660 .support_level = AST_MODULE_SUPPORT_CORE,
2661 .load = load_module,
2662 .unload = unload_module,
2664 .load_pri = AST_MODPRI_CORE,
2665 .requires = "extconfig",
A-Law to Signed linear conversion.
#define AST_LIN2A(a)
Definition alaw.h:50
#define AST_ALAW(a)
Definition alaw.h:84
char digit
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition astmm.h:288
#define ast_free(a)
Definition astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
#define ast_log
Definition astobj2.c:42
static PGresult * result
Definition cel_pgsql.c:84
static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX]
Definition chan_dahdi.c:820
unsigned int cos
Definition chan_iax2.c:380
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition channel.c:1171
@ AST_SOFTHANGUP_DEV
Definition channel.h:1141
void ast_channel_softhangup_internal_flag_add(struct ast_channel *chan, int value)
static void ast_mf_detect_init(mf_detect_state_t *s, unsigned int sample_rate)
Definition dsp.c:563
static int thresholds[THRESHOLD_MAX]
Definition dsp.c:344
#define DEF_DTMF_HITS_TO_BEGIN
Definition dsp.c:241
void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
Set the minimum average magnitude threshold to determine talking by the DSP.
Definition dsp.c:1973
#define BELL_MF_THRESHOLD
Definition dsp.c:200
void ast_dsp_free(struct ast_dsp *dsp)
Definition dsp.c:1968
int ast_dsp_get_tcount(struct ast_dsp *dsp)
Get tcount (Threshold counter)
Definition dsp.c:2103
#define DEFAULT_THRESHOLD
Default minimum average magnitude threshold to determine talking/noise by the DSP.
Definition dsp.c:140
#define DEF_DTMF_REVERSE_TWIST
Definition dsp.c:192
static void ast_tone_detect_init(tone_detect_state_t *s, int freq, int duration, int amp, unsigned int sample_rate)
Definition dsp.c:466
gsamp_thresh
Definition dsp.c:157
@ THRESH_RING
Definition dsp.c:158
@ THRESH_CONGESTION
Definition dsp.c:161
@ THRESH_RING2ANSWER
Definition dsp.c:163
@ THRESH_TALK
Definition dsp.c:159
@ THRESH_HANGUP
Definition dsp.c:162
@ THRESH_BUSY
Definition dsp.c:160
#define FAX_TONE_CED_DB
Definition dsp.c:225
struct ast_frame * ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af)
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress,...
Definition dsp.c:1683
#define DTMF_TO_TOTAL_ENERGY
Definition dsp.c:198
#define BELL_MF_RELATIVE_PEAK
Definition dsp.c:202
#define DEF_DTMF_MISSES_TO_END
Definition dsp.c:246
static const int DEFAULT_SILENCE_THRESHOLD
The default silence threshold we will use if an alternate configured value is not present or is inval...
Definition dsp.c:252
static const char dtmf_positions[]
Definition dsp.c:341
#define R2_MF_THRESHOLD
Definition dsp.c:204
static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len)
Definition dsp.c:1261
#define DTMF_MATRIX_SIZE
Definition dsp.c:168
static void goertzel_init(goertzel_state_t *s, float freq, unsigned int sample_rate)
Definition dsp.c:392
#define R2_GSIZE
Definition dsp.c:236
static struct progalias aliases[]
static int _dsp_init(int reload)
Definition dsp.c:2108
static int tone_detect(struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp, int samples)
Definition dsp.c:605
static const float r2_forward_tones[]
Definition dsp.c:335
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Process the audio frame for silence.
Definition dsp.c:1672
#define FAX_TONE_CNG_FREQ
Definition dsp.c:215
void ast_dsp_digitreset(struct ast_dsp *dsp)
Reset DTMF detector.
Definition dsp.c:1995
#define DEF_RELAX_DTMF_NORMAL_TWIST
Definition dsp.c:186
static int mf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax)
Definition dsp.c:937
struct ast_dsp * ast_dsp_new_with_rate(unsigned int sample_rate)
Allocates a new dsp with a specific internal sample rate used during processing.
Definition dsp.c:1948
#define FAX_TONE_CED_DURATION
Definition dsp.c:224
#define DTMF_THRESHOLD
Definition dsp.c:182
#define TONE_MIN_THRESH
Definition dsp.c:154
static const char bell_mf_positions[]
Definition dsp.c:342
static void ast_fax_detect_init(struct ast_dsp *s)
Definition dsp.c:527
#define MAX_DTMF_DIGITS
Definition dsp.c:166
int ast_dsp_silence_with_energy(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence, int *frames_energy)
Process the audio frame for silence.
Definition dsp.c:1667
#define DEF_DTMF_NORMAL_TWIST
Definition dsp.c:185
#define CONFIG_FILE_NAME
Definition dsp.c:254
static float goertzel_result(goertzel_state_t *s)
Definition dsp.c:378
#define FAX_TONE_CNG_DB
Definition dsp.c:217
int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf)
Scans for progress indication in audio.
Definition dsp.c:1403
void ast_dsp_reset(struct ast_dsp *dsp)
Reset total silence count.
Definition dsp.c:2028
static void ast_freq_detect_init(struct ast_dsp *s, int freq, int dur, int db, int squelch)
Definition dsp.c:538
void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, const struct ast_dsp_busy_pattern *cadence)
Set expected lengths of the busy tone.
Definition dsp.c:1989
unsigned int ast_dsp_get_sample_rate(const struct ast_dsp *dsp)
Retrieve the sample rate this DSP structure was created with.
Definition dsp.c:1915
#define FAX_TONE_CED_FREQ
Definition dsp.c:223
static int reload_module(void)
Definition dsp.c:2654
#define DTMF_RELATIVE_PEAK_COL
Definition dsp.c:197
static struct progress modes[]
#define DTMF_GSIZE
Definition dsp.c:233
#define R2_MF_TWIST
Definition dsp.c:205
static void ast_digit_detect_init(digit_detect_state_t *s, int digitmode, unsigned int sample_rate)
Definition dsp.c:587
static const float dtmf_row[]
Definition dsp.c:326
static void goertzel_sample(goertzel_state_t *s, short sample)
Definition dsp.c:352
#define DEF_RELAX_DTMF_REVERSE_TWIST
Definition dsp.c:193
static int pair_there(float p1, float p2, float i1, float i2, float e)
Definition dsp.c:1238
static int r2_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax, const char *r2_positions)
Definition dsp.c:1088
static const float mf_tones[]
Definition dsp.c:332
static float dtmf_reverse_twist
Definition dsp.c:346
int ast_dsp_get_features(struct ast_dsp *dsp)
Get features.
Definition dsp.c:1962
#define TONE_THRESHOLD
Definition dsp.c:183
busy_detect
Definition dsp.c:142
@ BUSY_MAX
Definition dsp.c:147
@ BUSY_PAT_PERCENT
Definition dsp.c:144
@ BUSY_MIN
Definition dsp.c:146
@ BUSY_PERCENT
Definition dsp.c:143
@ BUSY_THRESHOLD
Definition dsp.c:145
#define R2_MF_RELATIVE_PEAK
Definition dsp.c:206
prog_mode
Definition dsp.c:79
@ PROG_MODE_CR
Definition dsp.c:81
@ PROG_MODE_UK
Definition dsp.c:82
@ PROG_MODE_NA
Definition dsp.c:80
static int dtmf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[], int samples, int squelch, int relax)
Definition dsp.c:729
int ast_dsp_set_digitmode(struct ast_dsp *dsp, int digitmode)
Set digit mode.
Definition dsp.c:2044
freq_index
Definition dsp.c:85
@ HZ_425
Definition dsp.c:96
@ HZ_950
Definition dsp.c:91
@ HZ_350UK
Definition dsp.c:99
@ HZ_620
Definition dsp.c:90
@ HZ_440
Definition dsp.c:88
@ HZ_440UK
Definition dsp.c:101
@ HZ_480
Definition dsp.c:89
@ HZ_350
Definition dsp.c:87
@ HZ_1400
Definition dsp.c:92
@ HZ_400UK
Definition dsp.c:100
@ HZ_1800
Definition dsp.c:93
static void goertzel_reset(goertzel_state_t *s)
Definition dsp.c:398
static int ast_dsp_silence_noise_with_energy(struct ast_dsp *dsp, struct ast_frame *f, int *total, int *frames_energy, int noise)
Definition dsp.c:1621
gsamp_size
Definition dsp.c:73
@ GSAMP_SIZE_NA
Definition dsp.c:74
@ GSAMP_SIZE_CR
Definition dsp.c:75
@ GSAMP_SIZE_UK
Definition dsp.c:76
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
Definition dsp.c:2196
static void ast_dtmf_detect_init(dtmf_detect_state_t *s, unsigned int sample_rate)
Definition dsp.c:547
static void ast_r2_detect_init(mf_detect_state_t *s, unsigned int sample_rate, int backward)
Definition dsp.c:575
#define FREQ_ARRAY_SIZE
Definition dsp.c:115
static void mute_fragment(struct ast_dsp *dsp, fragment_t *fragment)
Definition dsp.c:456
#define DTMF_RELATIVE_PEAK_ROW
Definition dsp.c:196
#define DSP_HISTORY
Definition dsp.c:151
static int dtmf_misses_to_end
Definition dsp.c:350
static int dtmf_hits_to_begin
Definition dsp.c:349
#define DEFAULT_SAMPLE_RATE
Definition dsp.c:227
static int load_module(void)
Definition dsp.c:2642
int ast_dsp_noise(struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise)
Process the audio frame for noise.
Definition dsp.c:1677
static const float r2_backward_tones[]
Definition dsp.c:338
int ast_dsp_get_tstate(struct ast_dsp *dsp)
Get tstate (Tone State)
Definition dsp.c:2098
int ast_dsp_was_muted(struct ast_dsp *dsp)
Returns true if DSP code was muting any fragment of the last processed frame. Muting (squelching) hap...
Definition dsp.c:2093
static int unload_module(void)
Definition dsp.c:2634
static float relax_dtmf_normal_twist
Definition dsp.c:347
int ast_dsp_busydetect(struct ast_dsp *dsp)
Return non-zero if historically this should be a busy, request that ast_dsp_silence has already been ...
Definition dsp.c:1483
static void store_digit(digit_detect_state_t *s, char digit)
Definition dsp.c:716
int ast_dsp_set_faxmode(struct ast_dsp *dsp, int faxmode)
Set fax mode.
Definition dsp.c:2070
#define BELL_MF_TWIST
Definition dsp.c:201
static const float dtmf_col[]
Definition dsp.c:329
#define MF_GSIZE
Definition dsp.c:230
#define FAX_TONE_CNG_DURATION
Definition dsp.c:216
int ast_dsp_set_freqmode(struct ast_dsp *dsp, int freq, int dur, int db, int squelch)
Set arbitrary frequency detection mode.
Definition dsp.c:2059
static struct ast_dsp * __ast_dsp_new(unsigned int sample_rate)
Definition dsp.c:1920
void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
Set number of required cadences for busy.
Definition dsp.c:1978
static const char r2_mf_positions[]
Definition dsp.c:343
static float dtmf_normal_twist
Definition dsp.c:345
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition dsp.c:1953
static float relax_dtmf_reverse_twist
Definition dsp.c:348
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition dsp.c:1943
static int __ast_dsp_silence_noise(struct ast_dsp *dsp, short *s, int len, int *totalsilence, int *totalnoise, int *frames_energy)
Definition dsp.c:1417
int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
Set zone for doing progress detection.
Definition dsp.c:2079
#define DSP_DIGITMODES
Definition dsp.c:2042
#define TONE_THRESH
Definition dsp.c:153
static void ast_dsp_prog_reset(struct ast_dsp *dsp)
Definition dsp.c:1898
Convenient Signal Processing routines.
threshold
Definition dsp.h:73
@ THRESHOLD_SILENCE
Definition dsp.h:75
@ THRESHOLD_MAX
Definition dsp.h:77
#define DSP_PROGRESS_RINGING
Definition dsp.h:42
#define DSP_TONE_STATE_SPECIAL3
Definition dsp.h:61
#define DSP_FEATURE_WAITDIALTONE
Definition dsp.h:46
#define DSP_TONE_STATE_SPECIAL2
Definition dsp.h:60
#define DSP_FEATURE_BUSY_DETECT
Definition dsp.h:27
#define DSP_TONE_STATE_DIALTONE
Definition dsp.h:56
#define DSP_PROGRESS_TALK
Definition dsp.h:41
#define DSP_TONE_STATE_SILENCE
Definition dsp.h:54
#define DSP_DIGITMODE_NOQUELCH
Definition dsp.h:36
#define DSP_DIGITMODE_MF
Definition dsp.h:32
#define DSP_TONE_STATE_BUSY
Definition dsp.h:58
#define DSP_DIGITMODE_MUTEMAX
Definition dsp.h:38
#define DSP_FEATURE_DIGIT_DETECT
Definition dsp.h:28
#define DSP_PROGRESS_BUSY
Definition dsp.h:43
#define DSP_FEATURE_FAX_DETECT
Definition dsp.h:29
#define DSP_TONE_STATE_SPECIAL1
Definition dsp.h:59
#define DSP_FAXMODE_DETECT_SQUELCH
Definition dsp.h:51
#define DSP_FAXMODE_DETECT_CED
Definition dsp.h:50
#define DSP_PROGRESS_CONGESTION
Definition dsp.h:44
#define DSP_FEATURE_CALL_PROGRESS
Definition dsp.h:45
#define DSP_DIGITMODE_MUTECONF
Definition dsp.h:37
#define DSP_FAXMODE_DETECT_CNG
Definition dsp.h:49
#define DSP_FEATURE_SILENCE_SUPPRESS
Definition dsp.h:26
#define DSP_TONE_STATE_HUNGUP
Definition dsp.h:62
#define DSP_FEATURE_FREQ_DETECT
Definition dsp.h:47
#define DSP_TONE_STATE_TALKING
Definition dsp.h:57
#define DSP_DIGITMODE_R2_BACKWARD
Definition dsp.h:34
#define DSP_TONE_STATE_RINGING
Definition dsp.h:55
#define DSP_DIGITMODE_DTMF
Definition dsp.h:31
#define DSP_DIGITMODE_RELAXDTMF
Definition dsp.h:39
#define DSP_DIGITMODE_R2_FORWARD
Definition dsp.h:33
char * end
Definition eagi_proxy.c:73
#define abs(x)
Definition f2c.h:195
#define max(a, b)
Definition f2c.h:198
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition format.c:201
@ AST_FORMAT_CMP_EQUAL
Definition format.h:36
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition format.c:334
Media Format Cache API.
int ast_format_cache_is_slinear(struct ast_format *format)
Determines if a format is one of the cached slin formats.
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
struct ast_format * ast_format_alaw
Built-in cached alaw format.
static const char name[]
Definition format_mp3.c:68
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Configuration File Parser.
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
#define CONFIG_STATUS_FILEMISSING
#define CONFIG_STATUS_FILEUNCHANGED
@ CONFIG_FLAG_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition extconf.c:1287
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition extconf.c:1213
Asterisk internal frame definitions.
#define AST_FRAME_DTMF
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define ast_frfree(fr)
@ AST_FRAME_DTMF_END
@ AST_FRAME_DTMF_BEGIN
@ AST_FRAME_CONTROL
@ AST_CONTROL_CONGESTION
@ AST_CONTROL_ANSWER
@ AST_CONTROL_RINGING
@ AST_CONTROL_HANGUP
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_WARNING
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition module.h:331
@ AST_MODFLAG_GLOBAL_SYMBOLS
Definition module.h:330
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition module.h:557
@ AST_MODPRI_CORE
Definition module.h:338
@ AST_MODULE_SUPPORT_CORE
Definition module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition module.h:46
@ AST_MODULE_LOAD_FAILURE
Module could not be loaded properly.
Definition module.h:102
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70
Options provided by main asterisk program.
static int total
Definition res_adsi.c:970
static char pass[512]
static int reload(void)
#define NULL
Definition resample.c:96
#define M_PI
Definition resample.c:83
Main Channel structure associated with a channel.
int pattern[4]
Definition dsp.h:70
Definition dsp.c:421
fragment_t mute_data[5]
Definition dsp.c:450
int historicnoise[DSP_HISTORY]
Definition dsp.c:433
int tcount
Definition dsp.c:441
int faxmode
Definition dsp.c:443
unsigned int sample_rate
Definition dsp.c:449
int busymaybe
Definition dsp.c:430
int mute_fragments
Definition dsp.c:448
int busycount
Definition dsp.c:431
int totalsilence
Definition dsp.c:425
goertzel_state_t freqs[FREQ_ARRAY_SIZE]
Definition dsp.c:435
int tstate
Definition dsp.c:440
int threshold
Definition dsp.c:423
struct ast_frame f
Definition dsp.c:422
digit_detect_state_t digit_state
Definition dsp.c:451
int totalnoise
Definition dsp.c:427
tone_detect_state_t ced_tone_state
Definition dsp.c:453
int historicsilence[DSP_HISTORY]
Definition dsp.c:434
enum prog_mode progmode
Definition dsp.c:439
int freqcount
Definition dsp.c:436
int features
Definition dsp.c:428
int digitmode
Definition dsp.c:442
enum gsamp_size gsamp_size
Definition dsp.c:438
int display_inband_dtmf_warning
Definition dsp.c:446
int dtmf_began
Definition dsp.c:445
float genergy
Definition dsp.c:447
int freqmode
Definition dsp.c:444
int gsamps
Definition dsp.c:437
int ringtimeout
Definition dsp.c:429
struct ast_dsp_busy_pattern busy_cadence
Definition dsp.c:432
tone_detect_state_t cng_tone_state
Definition dsp.c:452
Structure used to handle boolean flags.
Definition utils.h:220
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
enum ast_frame_type frametype
union ast_frame::@235 data
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
mf_detect_state_t mf
Definition dsp.c:322
dtmf_detect_state_t dtmf
Definition dsp.c:321
int digitlen[MAX_DTMF_DIGITS+1]
Definition dsp.c:315
char digits[MAX_DTMF_DIGITS+1]
Definition dsp.c:314
union digit_detect_state_t::@368 td
goertzel_state_t row_out[DTMF_MATRIX_SIZE]
Definition dsp.c:292
goertzel_state_t col_out[DTMF_MATRIX_SIZE]
Definition dsp.c:293
int start
Definition dsp.c:404
int end
Definition dsp.c:405
int mute_samples
Definition dsp.c:309
int hits[5]
Definition dsp.c:307
goertzel_state_t tone_out[6]
Definition dsp.c:305
int current_hit
Definition dsp.c:306
int current_sample
Definition dsp.c:308
char * name
Definition dsp.c:105
enum prog_mode mode
Definition dsp.c:106
enum gsamp_size size
Definition dsp.c:118
int freqs[FREQ_ARRAY_SIZE]
Definition dsp.c:119
float threshold
Definition dsp.c:283
goertzel_state_t tone
Definition dsp.c:277
int samples_pending
Definition dsp.c:279
Test Framework API.
@ TEST_INIT
Definition test.h:200
@ TEST_EXECUTE
Definition test.h:201
#define AST_TEST_REGISTER(cb)
Definition test.h:127
#define ast_test_status_update(a, b, c...)
Definition test.h:129
#define AST_TEST_UNREGISTER(cb)
Definition test.h:128
#define AST_TEST_DEFINE(hdr)
Definition test.h:126
ast_test_result_state
Definition test.h:193
@ AST_TEST_PASS
Definition test.h:195
@ AST_TEST_FAIL
Definition test.h:196
@ AST_TEST_NOT_RUN
Definition test.h:194
int done
u-Law to Signed linear conversion
#define AST_MULAW(a)
Definition ulaw.h:85
#define AST_LIN2MU(a)
Definition ulaw.h:49
Utility functions.
#define ARRAY_LEN(a)
Definition utils.h:706
#define MAX(a, b)
Definition utils.h:254