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 },
115 #define FREQ_ARRAY_SIZE 7
119 int freqs[FREQ_ARRAY_SIZE];
140 #define DEFAULT_THRESHOLD 512
151 #define DSP_HISTORY 15
153 #define TONE_THRESH 10.0
154 #define TONE_MIN_THRESH 1e8
166 #define MAX_DTMF_DIGITS 128
168 #define DTMF_MATRIX_SIZE 4
182 #define DTMF_THRESHOLD 8.0e7
183 #define TONE_THRESHOLD 7.8e7
185 #define DEF_DTMF_NORMAL_TWIST 6.31
186 #define DEF_RELAX_DTMF_NORMAL_TWIST 6.31
189 #define DEF_DTMF_REVERSE_TWIST 2.51
190 #define DEF_RELAX_DTMF_REVERSE_TWIST 6.61
192 #define DEF_DTMF_REVERSE_TWIST 2.51
193 #define DEF_RELAX_DTMF_REVERSE_TWIST 3.98
196 #define DTMF_RELATIVE_PEAK_ROW 6.3
197 #define DTMF_RELATIVE_PEAK_COL 6.3
198 #define DTMF_TO_TOTAL_ENERGY 42.0
200 #define BELL_MF_THRESHOLD 1.6e9
201 #define BELL_MF_TWIST 4.0
202 #define BELL_MF_RELATIVE_PEAK 12.6
204 #if defined(BUSYDETECT_TONEONLY) && defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
205 #error You cant use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE
211 #define FAX_TONE_CNG_FREQ 1100
212 #define FAX_TONE_CNG_DURATION 500
213 #define FAX_TONE_CNG_DB 16
219 #define FAX_TONE_CED_FREQ 2100
220 #define FAX_TONE_CED_DURATION 2600
221 #define FAX_TONE_CED_DB 16
223 #define DEFAULT_SAMPLE_RATE 8000
229 #define DTMF_GSIZE 102
234 #define DEF_DTMF_HITS_TO_BEGIN 2
239 #define DEF_DTMF_MISSES_TO_END 3
247 #define CONFIG_FILE_NAME "dsp.conf"
307 char digits[MAX_DTMF_DIGITS + 1];
308 int digitlen[MAX_DTMF_DIGITS + 1];
319 static const float dtmf_row[] = {
320 697.0, 770.0, 852.0, 941.0
322 static const float dtmf_col[] = {
323 1209.0, 1336.0, 1477.0, 1633.0
325 static const float mf_tones[] = {
326 700.0, 900.0, 1100.0, 1300.0, 1500.0, 1700.0
328 static const char dtmf_positions[] =
"123A" "456B" "789C" "*0#D";
329 static const char bell_mf_positions[] =
"1247C-358A--69*---0B----#";
330 static int thresholds[THRESHOLD_MAX];
331 static float dtmf_normal_twist;
332 static float dtmf_reverse_twist;
333 static float relax_dtmf_normal_twist;
334 static float relax_dtmf_reverse_twist;
335 static int dtmf_hits_to_begin;
336 static int dtmf_misses_to_end;
352 s->
v3 = (s->
fac * s->
v2) >> 15;
356 if (abs(s->
v3) > (1 << 15)) {
368 r.value = (s->
v3 * s->
v3) + (s->
v2 * s->
v2);
369 r.value -= ((s->
v2 * s->
v3) >> 15) * s->
fac;
375 return (
float)r.value * (float)(1 << r.power);
378 static inline void goertzel_init(
goertzel_state_t *s,
float freq,
unsigned int sample_rate)
381 s->
fac = (int)(32768.0 * 2.0 * cos(2.0 * M_PI * freq / sample_rate));
425 enum prog_mode progmode;
432 int display_inband_dtmf_warning;
435 unsigned int sample_rate;
444 if (dsp->mute_fragments >= ARRAY_LEN(dsp->mute_data)) {
445 ast_log(LOG_ERROR,
"Too many fragments to mute. Ignoring\n");
449 dsp->mute_data[dsp->mute_fragments++] = *fragment;
452 static void ast_tone_detect_init(
tone_detect_state_t *s,
int freq,
int duration,
int amp,
unsigned int sample_rate)
454 int duration_samples;
456 int periods_in_block;
461 duration_samples = duration * sample_rate / 1000;
463 duration_samples = duration_samples * 9 / 10;
468 s->block_size = (20 * sample_rate) / 1000;
470 periods_in_block = s->block_size * freq / sample_rate;
475 if (periods_in_block < 5) {
476 periods_in_block = 5;
480 s->block_size = periods_in_block * sample_rate / freq;
488 s->hits_required = (duration_samples - (s->block_size - 1)) / s->block_size;
490 goertzel_init(&s->tone, freq, sample_rate);
492 s->samples_pending = s->block_size;
507 x = pow(10.0, amp / 10.0);
508 s->threshold = x / (x + 1);
510 ast_debug(1,
"Setup tone %d Hz, %d ms, block_size=%d, hits_required=%d\n", freq, duration, s->block_size, s->hits_required);
513 static void ast_fax_detect_init(
struct ast_dsp *s)
515 ast_tone_detect_init(&s->cng_tone_state, FAX_TONE_CNG_FREQ, FAX_TONE_CNG_DURATION, FAX_TONE_CNG_DB, s->sample_rate);
516 ast_tone_detect_init(&s->ced_tone_state, FAX_TONE_CED_FREQ, FAX_TONE_CED_DURATION, FAX_TONE_CED_DB, s->sample_rate);
517 if (s->faxmode & DSP_FAXMODE_DETECT_SQUELCH) {
518 s->cng_tone_state.squelch = 1;
519 s->ced_tone_state.squelch = 1;
524 static void ast_freq_detect_init(
struct ast_dsp *s,
int freq,
int dur,
int db,
int squelch)
527 ast_tone_detect_init(&s->cng_tone_state, freq, dur, db, s->sample_rate);
528 if (s->freqmode & squelch) {
529 s->cng_tone_state.squelch = 1;
537 for (i = 0; i < DTMF_MATRIX_SIZE; i++) {
538 goertzel_init(&s->row_out[i], dtmf_row[i], sample_rate);
539 goertzel_init(&s->col_out[i], dtmf_col[i], sample_rate);
544 s->current_sample = 0;
553 for (i = 0; i < 6; i++) {
554 goertzel_init(&s->tone_out[i], mf_tones[i], sample_rate);
556 s->hits[0] = s->hits[1] = s->hits[2] = s->hits[3] = s->hits[4] = 0;
557 s->current_sample = 0;
563 s->current_digits = 0;
564 s->detected_digits = 0;
569 ast_mf_detect_init(&s->td.mf, sample_rate);
571 ast_dtmf_detect_init(&s->td.dtmf, sample_rate);
587 if (s->squelch && s->mute_samples > 0) {
588 mute.end = (s->mute_samples < samples) ? s->mute_samples : samples;
589 s->mute_samples -= mute.end;
592 for (start = 0; start < samples; start = end) {
594 limit = samples - start;
595 if (limit > s->samples_pending) {
596 limit = s->samples_pending;
600 for (i = limit, ptr = amp ; i > 0; i--, ptr++) {
603 s->energy += (int32_t) samp * (int32_t) samp;
605 goertzel_sample(&s->tone, samp);
608 s->samples_pending -= limit;
610 if (s->samples_pending) {
615 tone_energy = goertzel_result(&s->tone);
619 s->energy *= s->block_size;
621 ast_debug(10,
"%d Hz tone %2d Ew=%.4E, Et=%.4E, s/n=%10.2f\n", s->freq, s->hit_count, tone_energy, s->energy, tone_energy / (s->energy - tone_energy));
623 if (TONE_THRESHOLD <= tone_energy
624 && tone_energy > s->energy * s->threshold) {
625 ast_debug(10,
"%d Hz tone Hit! %2d Ew=%.4E, Et=%.4E, s/n=%10.2f\n", s->freq, s->hit_count, tone_energy, s->energy, tone_energy / (s->energy - tone_energy));
633 if (hit == s->last_hit) {
637 }
else if (!s->hit_count) {
643 if (s->hit_count == s->hits_required) {
644 ast_debug(1,
"%d Hz tone detected\n", s->freq);
651 if (s->squelch && hit) {
652 if (mute.end < start - s->block_size) {
654 mute_fragment(dsp, &mute);
655 mute.start = (start > s->block_size) ? (start - s->block_size) : 0;
657 mute.end = end + s->block_size;
662 goertzel_reset(&s->tone);
666 s->samples_pending = s->block_size;
671 if (s->squelch && mute.end) {
672 if (mute.end > samples) {
673 s->mute_samples = mute.end - samples;
676 mute_fragment(dsp, &mute);
684 s->detected_digits++;
685 if (s->current_digits < MAX_DTMF_DIGITS) {
686 s->digitlen[s->current_digits] = 0;
687 s->digits[s->current_digits++] = digit;
688 s->digits[s->current_digits] =
'\0';
690 ast_log(LOG_WARNING,
"Digit lost due to full buffer\n");
697 float row_energy[DTMF_MATRIX_SIZE];
698 float col_energy[DTMF_MATRIX_SIZE];
709 if (squelch && s->td.dtmf.mute_samples > 0) {
710 mute.end = (s->td.dtmf.mute_samples < samples) ? s->td.dtmf.mute_samples : samples;
711 s->td.dtmf.mute_samples -= mute.end;
715 for (sample = 0; sample < samples; sample = limit) {
717 if ((samples - sample) >= (DTMF_GSIZE - s->td.dtmf.current_sample)) {
718 limit = sample + (DTMF_GSIZE - s->td.dtmf.current_sample);
724 for (j = sample; j < limit; j++) {
726 s->td.dtmf.energy += (int32_t) samp * (int32_t) samp;
729 goertzel_sample(s->td.dtmf.row_out, samp);
730 goertzel_sample(s->td.dtmf.col_out, samp);
731 goertzel_sample(s->td.dtmf.row_out + 1, samp);
732 goertzel_sample(s->td.dtmf.col_out + 1, samp);
733 goertzel_sample(s->td.dtmf.row_out + 2, samp);
734 goertzel_sample(s->td.dtmf.col_out + 2, samp);
735 goertzel_sample(s->td.dtmf.row_out + 3, samp);
736 goertzel_sample(s->td.dtmf.col_out + 3, samp);
739 s->td.dtmf.current_sample += (limit - sample);
740 if (s->td.dtmf.current_sample < DTMF_GSIZE) {
745 row_energy[0] = goertzel_result(&s->td.dtmf.row_out[0]);
746 col_energy[0] = goertzel_result(&s->td.dtmf.col_out[0]);
748 for (best_row = best_col = 0, i = 1; i < DTMF_MATRIX_SIZE; i++) {
749 row_energy[i] = goertzel_result(&s->td.dtmf.row_out[i]);
750 if (row_energy[i] > row_energy[best_row]) {
753 col_energy[i] = goertzel_result(&s->td.dtmf.col_out[i]);
754 if (col_energy[i] > col_energy[best_col]) {
758 ast_debug(10,
"DTMF best '%c' Erow=%.4E Ecol=%.4E Erc=%.4E Et=%.4E\n",
759 dtmf_positions[(best_row << 2) + best_col],
760 row_energy[best_row], col_energy[best_col],
761 row_energy[best_row] + col_energy[best_col], s->td.dtmf.energy);
764 if (row_energy[best_row] >= DTMF_THRESHOLD &&
765 col_energy[best_col] >= DTMF_THRESHOLD &&
766 col_energy[best_col] < row_energy[best_row] * (relax ? relax_dtmf_reverse_twist : dtmf_reverse_twist) &&
767 row_energy[best_row] < col_energy[best_col] * (relax ? relax_dtmf_normal_twist : dtmf_normal_twist)) {
769 for (i = 0; i < DTMF_MATRIX_SIZE; i++) {
770 if ((i != best_col &&
771 col_energy[i] * DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) ||
773 && row_energy[i] * DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) {
778 if (i >= DTMF_MATRIX_SIZE &&
779 (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY * s->td.dtmf.energy) {
781 hit = dtmf_positions[(best_row << 2) + best_col];
840 if (s->td.dtmf.current_hit) {
842 if (hit != s->td.dtmf.current_hit) {
844 if (s->td.dtmf.misses == dtmf_misses_to_end) {
846 s->td.dtmf.current_hit = 0;
849 s->td.dtmf.misses = 0;
851 s->digitlen[s->current_digits - 1] += DTMF_GSIZE;
859 if (hit != s->td.dtmf.lasthit) {
860 s->td.dtmf.lasthit = hit;
863 if (hit && hit != s->td.dtmf.current_hit) {
865 if (s->td.dtmf.hits == dtmf_hits_to_begin) {
867 s->digitlen[s->current_digits - 1] = dtmf_hits_to_begin * DTMF_GSIZE;
868 s->td.dtmf.current_hit = hit;
869 s->td.dtmf.misses = 0;
874 if (squelch && hit) {
875 if (mute.end < sample - DTMF_GSIZE) {
877 mute_fragment(dsp, &mute);
878 mute.start = (sample > DTMF_GSIZE) ? (sample - DTMF_GSIZE) : 0;
880 mute.end = limit + DTMF_GSIZE;
884 for (i = 0; i < DTMF_MATRIX_SIZE; i++) {
885 goertzel_reset(&s->td.dtmf.row_out[i]);
886 goertzel_reset(&s->td.dtmf.col_out[i]);
888 s->td.dtmf.energy = 0.0;
889 s->td.dtmf.current_sample = 0;
892 if (squelch && mute.end) {
893 if (mute.end > samples) {
894 s->td.dtmf.mute_samples = mute.end - samples;
897 mute_fragment(dsp, &mute);
900 return (s->td.dtmf.current_hit);
904 int samples,
int squelch,
int relax)
917 if (squelch && s->td.mf.mute_samples > 0) {
918 mute.end = (s->td.mf.mute_samples < samples) ? s->td.mf.mute_samples : samples;
919 s->td.mf.mute_samples -= mute.end;
923 for (sample = 0; sample < samples; sample = limit) {
926 if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample)) {
927 limit = sample + (MF_GSIZE - s->td.mf.current_sample);
933 for (j = sample; j < limit; j++) {
937 goertzel_sample(s->td.mf.tone_out, samp);
938 goertzel_sample(s->td.mf.tone_out + 1, samp);
939 goertzel_sample(s->td.mf.tone_out + 2, samp);
940 goertzel_sample(s->td.mf.tone_out + 3, samp);
941 goertzel_sample(s->td.mf.tone_out + 4, samp);
942 goertzel_sample(s->td.mf.tone_out + 5, samp);
944 s->td.mf.current_sample += (limit - sample);
945 if (s->td.mf.current_sample < MF_GSIZE) {
955 energy[0] = goertzel_result(&s->td.mf.tone_out[0]);
956 energy[1] = goertzel_result(&s->td.mf.tone_out[1]);
957 if (energy[0] > energy[1]) {
965 for (i = 2; i < 6; i++) {
966 energy[i] = goertzel_result(&s->td.mf.tone_out[i]);
967 if (energy[i] >= energy[best]) {
970 }
else if (energy[i] >= energy[second_best]) {
976 if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD
977 && energy[best] < energy[second_best]*BELL_MF_TWIST
978 && energy[best] * BELL_MF_TWIST > energy[second_best]) {
981 for (i = 0; i < 6; i++) {
982 if (i != best && i != second_best) {
983 if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) {
993 if (second_best < best) {
998 best = best * 5 + second_best - 1;
999 hit = bell_mf_positions[best];
1006 if (hit == s->td.mf.hits[4] && hit == s->td.mf.hits[3] &&
1007 ((hit !=
'*' && hit != s->td.mf.hits[2] && hit != s->td.mf.hits[1])||
1008 (hit ==
'*' && hit == s->td.mf.hits[2] && hit != s->td.mf.hits[1] &&
1009 hit != s->td.mf.hits[0]))) {
1010 store_digit(s, hit);
1015 if (hit != s->td.mf.hits[4] && hit != s->td.mf.hits[3]) {
1017 s->td.mf.current_hit = 0;
1020 s->td.mf.hits[0] = s->td.mf.hits[1];
1021 s->td.mf.hits[1] = s->td.mf.hits[2];
1022 s->td.mf.hits[2] = s->td.mf.hits[3];
1023 s->td.mf.hits[3] = s->td.mf.hits[4];
1024 s->td.mf.hits[4] = hit;
1027 if (squelch && hit) {
1028 if (mute.end < sample - MF_GSIZE) {
1030 mute_fragment(dsp, &mute);
1031 mute.start = (sample > MF_GSIZE) ? (sample - MF_GSIZE) : 0;
1033 mute.end = limit + MF_GSIZE;
1037 for (i = 0; i < 6; i++) {
1038 goertzel_reset(&s->td.mf.tone_out[i]);
1040 s->td.mf.current_sample = 0;
1043 if (squelch && mute.end) {
1044 if (mute.end > samples) {
1045 s->td.mf.mute_samples = mute.end - samples;
1048 mute_fragment(dsp, &mute);
1051 return (s->td.mf.current_hit);
1054 static inline int pair_there(
float p1,
float p2,
float i1,
float i2,
float e)
1066 if ((p1 < i1) || (p1 < i2) || (p1 < e)) {
1070 if ((p2 < i1) || (p2 < i2) || (p2 < e)) {
1077 static int __ast_dsp_call_progress(
struct ast_dsp *dsp,
short *s,
int len)
1083 int newstate = DSP_TONE_STATE_SILENCE;
1085 int freqcount = dsp->freqcount > FREQ_ARRAY_SIZE ? FREQ_ARRAY_SIZE : dsp->freqcount;
1090 if (pass > dsp->gsamp_size - dsp->gsamps) {
1091 pass = dsp->gsamp_size - dsp->gsamps;
1093 for (x = 0; x < pass; x++) {
1095 dsp->genergy += (int32_t) samp * (int32_t) samp;
1096 for (y = 0; y < freqcount; y++) {
1097 goertzel_sample(&dsp->freqs[y], samp);
1101 dsp->gsamps += pass;
1103 if (dsp->gsamps == dsp->gsamp_size) {
1104 float hz[FREQ_ARRAY_SIZE];
1105 for (y = 0; y < FREQ_ARRAY_SIZE; y++) {
1106 hz[y] = goertzel_result(&dsp->freqs[y]);
1108 switch (dsp->progmode) {
1110 if (pair_there(hz[HZ_480], hz[HZ_620], hz[
HZ_350], hz[HZ_440], dsp->genergy)) {
1111 newstate = DSP_TONE_STATE_BUSY;
1112 }
else if (pair_there(hz[HZ_440], hz[HZ_480], hz[HZ_350], hz[HZ_620], dsp->genergy)) {
1113 newstate = DSP_TONE_STATE_RINGING;
1114 }
else if (pair_there(hz[HZ_350], hz[HZ_440], hz[HZ_480], hz[HZ_620], dsp->genergy)) {
1115 newstate = DSP_TONE_STATE_DIALTONE;
1117 newstate = DSP_TONE_STATE_SPECIAL1;
1120 if (dsp->tstate == DSP_TONE_STATE_SPECIAL1 || dsp->tstate == DSP_TONE_STATE_SPECIAL2) {
1121 newstate = DSP_TONE_STATE_SPECIAL2;
1125 if (dsp->tstate == DSP_TONE_STATE_SPECIAL2 || dsp->tstate == DSP_TONE_STATE_SPECIAL3) {
1126 newstate = DSP_TONE_STATE_SPECIAL3;
1129 newstate = DSP_TONE_STATE_TALKING;
1131 newstate = DSP_TONE_STATE_SILENCE;
1136 newstate = DSP_TONE_STATE_RINGING;
1138 newstate = DSP_TONE_STATE_TALKING;
1140 newstate = DSP_TONE_STATE_SILENCE;
1145 newstate = DSP_TONE_STATE_HUNGUP;
1146 }
else if (pair_there(hz[
HZ_350UK], hz[HZ_440UK], hz[HZ_400UK], hz[HZ_400UK], dsp->genergy)) {
1147 newstate = DSP_TONE_STATE_DIALTONE;
1151 ast_log(LOG_WARNING,
"Can't process in unknown prog mode '%u'\n", dsp->progmode);
1153 if (newstate == dsp->tstate) {
1155 if (dsp->ringtimeout) {
1158 switch (dsp->tstate) {
1159 case DSP_TONE_STATE_RINGING:
1163 dsp->ringtimeout = 1;
1166 case DSP_TONE_STATE_BUSY:
1170 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1173 case DSP_TONE_STATE_TALKING:
1177 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1180 case DSP_TONE_STATE_SPECIAL3:
1184 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1187 case DSP_TONE_STATE_HUNGUP:
1188 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS) &&
1191 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1196 ast_debug(1,
"Consider call as answered because of timeout after last ring\n");
1198 dsp->features &= ~DSP_FEATURE_CALL_PROGRESS;
1201 ast_debug(5,
"Stop state %d with duration %d\n", dsp->tstate, dsp->tcount);
1202 ast_debug(5,
"Start state %d\n", newstate);
1203 dsp->tstate = newstate;
1208 for (x = 0; x < 7; x++) {
1209 dsp->freqs[x].
v2 = dsp->freqs[x].
v3 = 0.0;
1222 ast_log(LOG_WARNING,
"Can't check call progress of non-voice frames\n");
1226 ast_log(LOG_WARNING,
"Can only check call progress in signed-linear frames, %s not supported\n",
1230 return __ast_dsp_call_progress(dsp, inf->
data.ptr, inf->
datalen / 2);
1233 static int __ast_dsp_silence_noise(
struct ast_dsp *dsp,
short *s,
int len,
int *totalsilence,
int *totalnoise,
int *frames_energy)
1243 for (x = 0; x < len; x++) {
1247 if (accum < dsp->threshold) {
1252 memmove(dsp->historicnoise +
DSP_HISTORY - dsp->busycount, dsp->historicnoise +
DSP_HISTORY - dsp->busycount + 1, dsp->busycount *
sizeof(dsp->historicnoise[0]));
1263 dsp->
totalnoise += len / (dsp->sample_rate / 1000);
1265 int silence1 = dsp->historicsilence[
DSP_HISTORY - 1];
1266 int silence2 = dsp->historicsilence[
DSP_HISTORY - 2];
1268 memmove(dsp->historicsilence +
DSP_HISTORY - dsp->busycount, dsp->historicsilence +
DSP_HISTORY - dsp->busycount + 1, dsp->busycount *
sizeof(dsp->historicsilence[0]));
1271 if (silence1 < silence2) {
1272 if (silence1 + silence1 *
BUSY_PERCENT / 100 >= silence2) {
1278 if (silence1 - silence1 *
BUSY_PERCENT / 100 <= silence2) {
1293 if (frames_energy) {
1294 *frames_energy = accum;
1302 #ifndef BUSYDETECT_TONEONLY
1303 int avgsilence = 0, hitsilence = 0;
1305 int avgtone = 0, hittone = 0;
1308 if (dsp->busy_cadence.
length != 4) {
1309 if (!dsp->busymaybe) {
1315 #ifndef BUSYDETECT_TONEONLY
1316 avgsilence += dsp->historicsilence[x];
1318 avgtone += dsp->historicnoise[x];
1320 #ifndef BUSYDETECT_TONEONLY
1321 avgsilence /= dsp->busycount;
1323 avgtone /= dsp->busycount;
1325 #ifndef BUSYDETECT_TONEONLY
1326 if (avgsilence > dsp->historicsilence[x]) {
1327 if (avgsilence - (avgsilence *
BUSY_PERCENT / 100) <= dsp->historicsilence[x]) {
1331 if (avgsilence + (avgsilence *
BUSY_PERCENT / 100) >= dsp->historicsilence[x]) {
1336 if (avgtone > dsp->historicnoise[x]) {
1337 if (avgtone - (avgtone *
BUSY_PERCENT / 100) <= dsp->historicnoise[x]) {
1341 if (avgtone + (avgtone *
BUSY_PERCENT / 100) >= dsp->historicnoise[x]) {
1346 #ifndef BUSYDETECT_TONEONLY
1347 if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) &&
1351 if ((hittone >= dsp->busycount - 1) && (avgtone >=
BUSY_MIN && avgtone <=
BUSY_MAX))
1354 #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
1355 if (avgtone > avgsilence) {
1356 if (avgtone - avgtone*
BUSY_PERCENT/100 <= avgsilence) {
1360 if (avgtone + avgtone*
BUSY_PERCENT/100 >= avgsilence) {
1370 if (dsp->busy_cadence.
length == 4) {
1377 temp_error = abs(dsp->historicnoise[x] - dsp->busy_cadence.
pattern[0]);
1382 temp_error = abs(dsp->historicnoise[x + 1] - dsp->busy_cadence.
pattern[2]);
1387 temp_error = abs(dsp->historicsilence[x] - dsp->busy_cadence.
pattern[1]);
1392 temp_error = abs(dsp->historicsilence[x + 1] - dsp->busy_cadence.
pattern[3]);
1398 ast_debug(5,
"errors = %d max = %d\n", errors, errors_max);
1400 if (errors <= errors_max) {
1406 if (res && (dsp->busy_cadence.
pattern[0] > 0)) {
1408 #ifdef BUSYDETECT_DEBUG
1409 ast_debug(5,
"busy detector: avgtone of %d not close enough to desired %d\n",
1410 avgtone, dsp->busy_cadence.
pattern[0]);
1415 #ifndef BUSYDETECT_TONEONLY
1417 if (res && (dsp->busy_cadence.
pattern[1] > 0)) {
1419 #ifdef BUSYDETECT_DEBUG
1420 ast_debug(5,
"busy detector: avgsilence of %d not close enough to desired %d\n",
1421 avgsilence, dsp->busy_cadence.
pattern[1]);
1427 #if !defined(BUSYDETECT_TONEONLY) && defined(BUSYDETECT_DEBUG)
1429 ast_debug(5,
"ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
1431 ast_debug(5,
"busy detector: FAILED with avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
1437 static int ast_dsp_silence_noise_with_energy(
struct ast_dsp *dsp,
struct ast_frame *f,
int *total,
int *frames_energy,
int noise)
1442 unsigned char *odata;
1449 ast_log(LOG_WARNING,
"Can't calculate silence on a non-voice frame\n");
1457 odata = f->
data.ptr;
1461 for (x = 0; x < len; x++) {
1462 s[x] = AST_MULAW(odata[x]);
1466 for (x = 0; x < len; x++) {
1467 s[x] = AST_ALAW(odata[x]);
1470 ast_log(LOG_WARNING,
"Can only calculate silence on signed-linear, alaw or ulaw frames, %s not supported\n",
1477 return __ast_dsp_silence_noise(dsp, s, len, NULL, total, frames_energy);
1479 return __ast_dsp_silence_noise(dsp, s, len, total, NULL, frames_energy);
1485 return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, frames_energy, 0);
1490 return ast_dsp_silence_noise_with_energy(dsp, f, totalsilence, NULL, 0);
1495 return ast_dsp_silence_noise_with_energy(dsp, f, totalnoise, NULL, 1);
1503 int digit = 0, fax_digit = 0, custom_freq_digit = 0;
1506 unsigned char *odata;
1517 odata = af->
data.ptr;
1521 shortdata = af->
data.ptr;
1525 for (x = 0; x <
len; x++) {
1526 shortdata[x] = AST_MULAW(odata[x]);
1530 for (x = 0; x <
len; x++) {
1531 shortdata[x] = AST_ALAW(odata[x]);
1535 if (dsp->display_inband_dtmf_warning) {
1538 if ((dsp->features & DSP_FEATURE_DIGIT_DETECT) && (dsp->digitmode &
DSP_DIGITMODE_DTMF)) {
1539 ast_log(LOG_WARNING,
"Inband DTMF is not supported on codec %s. Use RFC2833\n",
1542 ast_log(LOG_WARNING,
"Can only do DSP on signed-linear, alaw or ulaw frames (%s not supported)\n",
1546 dsp->display_inband_dtmf_warning = 0;
1551 dsp->mute_fragments = 0;
1554 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) || (dsp->features & DSP_FEATURE_BUSY_DETECT)) {
1555 res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL, NULL);
1558 if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) {
1559 memset(&dsp->f, 0,
sizeof(dsp->f));
1566 memset(&dsp->f, 0,
sizeof(dsp->f));
1570 ast_debug(1,
"Requesting Hangup because the busy tone was detected on channel %s\n", ast_channel_name(chan));
1574 if ((dsp->features & DSP_FEATURE_FAX_DETECT)) {
1575 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CNG) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) {
1579 if ((dsp->faxmode & DSP_FAXMODE_DETECT_CED) && tone_detect(dsp, &dsp->ced_tone_state, shortdata, len)) {
1585 if ((dsp->freqmode) && tone_detect(dsp, &dsp->cng_tone_state, shortdata, len)) {
1586 custom_freq_digit =
'q';
1590 if (dsp->features & (DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_BUSY_DETECT)) {
1597 if (dsp->digit_state.current_digits) {
1598 int event = 0, event_len = 0;
1599 char event_digit = 0;
1601 if (!dsp->dtmf_began) {
1604 if (dsp->features & DSP_FEATURE_DIGIT_DETECT) {
1606 event_digit = dsp->digit_state.digits[0];
1608 dsp->dtmf_began = 1;
1610 }
else if (dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) {
1612 if (dsp->features & DSP_FEATURE_DIGIT_DETECT) {
1614 event_digit = dsp->digit_state.digits[0];
1615 event_len = dsp->digit_state.digitlen[0] * 1000 / dsp->sample_rate;
1617 memmove(&dsp->digit_state.digits[0], &dsp->digit_state.digits[1], dsp->digit_state.current_digits);
1618 memmove(&dsp->digit_state.digitlen[0], &dsp->digit_state.digitlen[1], dsp->digit_state.current_digits *
sizeof(dsp->digit_state.digitlen[0]));
1619 dsp->digit_state.current_digits--;
1620 dsp->dtmf_began = 0;
1622 if (dsp->features & DSP_FEATURE_BUSY_DETECT) {
1624 memset(dsp->historicsilence, 0,
sizeof(dsp->historicsilence));
1625 memset(dsp->historicnoise, 0,
sizeof(dsp->historicnoise));
1626 ast_debug(1,
"DTMF Detected - Reset busydetector\n");
1631 memset(&dsp->f, 0,
sizeof(dsp->f));
1634 dsp->f.
len = event_len;
1644 memset(&dsp->f, 0,
sizeof(dsp->f));
1651 if (custom_freq_digit) {
1654 memset(&dsp->f, 0,
sizeof(dsp->f));
1661 if ((dsp->features & DSP_FEATURE_CALL_PROGRESS)) {
1662 res = __ast_dsp_call_progress(dsp, shortdata, len);
1670 memset(&dsp->f, 0,
sizeof(dsp->f));
1673 dsp->f.
src =
"dsp_progress";
1679 ast_log(LOG_WARNING,
"Don't know how to represent call progress message %d\n", res);
1683 res = __ast_dsp_call_progress(dsp, shortdata, len);
1688 for (x = 0; x < dsp->mute_fragments; x++) {
1689 memset(shortdata + dsp->mute_data[x].start, 0,
sizeof(int16_t) * (dsp->mute_data[x].end - dsp->mute_data[x].start));
1693 for (x = 0; x <
len; x++) {
1694 odata[x] = AST_LIN2MU((
unsigned short) shortdata[x]);
1697 for (x = 0; x <
len; x++) {
1698 odata[x] = AST_LIN2A((
unsigned short) shortdata[x]);
1713 static void ast_dsp_prog_reset(
struct ast_dsp *dsp)
1718 dsp->gsamp_size = modes[dsp->progmode].size;
1720 for (x = 0; x < FREQ_ARRAY_SIZE; x++) {
1721 if (modes[dsp->progmode].freqs[x]) {
1722 goertzel_init(&dsp->freqs[x], (
float)modes[dsp->progmode].freqs[x], dsp->sample_rate);
1726 dsp->freqcount = max;
1727 dsp->ringtimeout = 0;
1732 return dsp->sample_rate;
1735 static struct ast_dsp *__ast_dsp_new(
unsigned int sample_rate)
1741 dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
1744 dsp->faxmode = DSP_FAXMODE_DETECT_CNG;
1745 dsp->sample_rate = sample_rate;
1748 ast_digit_detect_init(&dsp->digit_state, dsp->digitmode &
DSP_DIGITMODE_MF, dsp->sample_rate);
1749 dsp->display_inband_dtmf_warning = 1;
1751 ast_dsp_prog_reset(dsp);
1753 ast_fax_detect_init(dsp);
1760 return __ast_dsp_new(DEFAULT_SAMPLE_RATE);
1765 return __ast_dsp_new(sample_rate);
1770 dsp->features = features;
1771 if (!(features & DSP_FEATURE_DIGIT_DETECT)) {
1772 dsp->display_inband_dtmf_warning = 0;
1779 return (dsp->features);
1783 void ast_dsp_free(
struct ast_dsp *dsp)
1790 dsp->threshold = threshold;
1801 dsp->busycount = cadences;
1806 dsp->busy_cadence = *cadence;
1814 dsp->dtmf_began = 0;
1818 for (i = 0; i < 6; i++) {
1819 goertzel_reset(&s->tone_out[i]);
1821 s->hits[4] = s->hits[3] = s->hits[2] = s->hits[1] = s->hits[0] = 0;
1823 s->current_sample = 0;
1827 for (i = 0; i < 4; i++) {
1828 goertzel_reset(&s->row_out[i]);
1829 goertzel_reset(&s->col_out[i]);
1834 s->current_sample = 0;
1839 dsp->digit_state.digits[0] =
'\0';
1840 dsp->digit_state.current_digits = 0;
1849 for (x = 0; x < 4; x++) {
1850 dsp->freqs[x].
v2 = dsp->freqs[x].
v3 = 0.0;
1852 memset(dsp->historicsilence, 0,
sizeof(dsp->historicsilence));
1853 memset(dsp->historicnoise, 0,
sizeof(dsp->historicnoise));
1854 dsp->ringtimeout = 0;
1866 ast_digit_detect_init(&dsp->digit_state,
new &
DSP_DIGITMODE_MF, dsp->sample_rate);
1868 dsp->digitmode = digitmode;
1876 ast_freq_detect_init(dsp, freq, dur, db, squelch);
1885 if (dsp->faxmode != faxmode) {
1886 dsp->faxmode = faxmode;
1887 ast_fax_detect_init(dsp);
1896 for (x = 0; x < ARRAY_LEN(aliases); x++) {
1897 if (!strcasecmp(aliases[x].name, zone)) {
1898 dsp->progmode = aliases[x].mode;
1899 ast_dsp_prog_reset(dsp);
1908 return (dsp->mute_fragments > 0);
1921 static int _dsp_init(
int reload)
1929 if ((cfg =
ast_config_load2(CONFIG_FILE_NAME,
"dsp", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
1934 dtmf_normal_twist = DEF_DTMF_NORMAL_TWIST;
1935 dtmf_reverse_twist = DEF_DTMF_REVERSE_TWIST;
1936 relax_dtmf_normal_twist = DEF_RELAX_DTMF_NORMAL_TWIST;
1937 relax_dtmf_reverse_twist = DEF_RELAX_DTMF_REVERSE_TWIST;
1938 dtmf_hits_to_begin = DEF_DTMF_HITS_TO_BEGIN;
1939 dtmf_misses_to_end = DEF_DTMF_MISSES_TO_END;
1941 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
1945 for (v = ast_variable_browse(cfg,
"default"); v; v = v->
next) {
1946 if (!strcasecmp(v->
name,
"silencethreshold")) {
1947 if (sscanf(v->
value,
"%30d", &cfg_threshold) < 1) {
1948 ast_log(LOG_WARNING,
"Unable to convert '%s' to a numeric value.\n", v->
value);
1949 }
else if (cfg_threshold < 0) {
1950 ast_log(LOG_WARNING,
"Invalid silence threshold '%d' specified, using default\n", cfg_threshold);
1952 thresholds[THRESHOLD_SILENCE] = cfg_threshold;
1954 }
else if (!strcasecmp(v->
name,
"dtmf_normal_twist")) {
1955 if (sscanf(v->
value,
"%30f", &cfg_twist) < 1) {
1956 ast_log(LOG_WARNING,
"Unable to convert '%s' to a numeric value.\n", v->
value);
1957 }
else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {
1958 ast_log(LOG_WARNING,
"Invalid dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_normal_twist);
1960 dtmf_normal_twist = cfg_twist;
1962 }
else if (!strcasecmp(v->
name,
"dtmf_reverse_twist")) {
1963 if (sscanf(v->
value,
"%30f", &cfg_twist) < 1) {
1964 ast_log(LOG_WARNING,
"Unable to convert '%s' to a numeric value.\n", v->
value);
1965 }
else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {
1966 ast_log(LOG_WARNING,
"Invalid dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, dtmf_reverse_twist);
1968 dtmf_reverse_twist = cfg_twist;
1970 }
else if (!strcasecmp(v->
name,
"relax_dtmf_normal_twist")) {
1971 if (sscanf(v->
value,
"%30f", &cfg_twist) < 1) {
1972 ast_log(LOG_WARNING,
"Unable to convert '%s' to a numeric value.\n", v->
value);
1973 }
else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {
1974 ast_log(LOG_WARNING,
"Invalid relax_dtmf_normal_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_normal_twist);
1976 relax_dtmf_normal_twist = cfg_twist;
1978 }
else if (!strcasecmp(v->
name,
"relax_dtmf_reverse_twist")) {
1979 if (sscanf(v->
value,
"%30f", &cfg_twist) < 1) {
1980 ast_log(LOG_WARNING,
"Unable to convert '%s' to a numeric value.\n", v->
value);
1981 }
else if ((cfg_twist < 2.0) || (cfg_twist > 100.0)) {
1982 ast_log(LOG_WARNING,
"Invalid relax_dtmf_reverse_twist value '%.2f' specified, using default of %.2f\n", cfg_twist, relax_dtmf_reverse_twist);
1984 relax_dtmf_reverse_twist = cfg_twist;
1986 }
else if (!strcasecmp(v->
name,
"dtmf_hits_to_begin")) {
1987 if (sscanf(v->
value,
"%30d", &cfg_threshold) < 1) {
1988 ast_log(LOG_WARNING,
"Unable to convert '%s' to a numeric value.\n", v->
value);
1989 }
else if (cfg_threshold < 1) {
1990 ast_log(LOG_WARNING,
"Invalid dtmf_hits_to_begin value '%d' specified, using default of %d\n", cfg_threshold, dtmf_hits_to_begin);
1992 dtmf_hits_to_begin = cfg_threshold;
1994 }
else if (!strcasecmp(v->
name,
"dtmf_misses_to_end")) {
1995 if (sscanf(v->
value,
"%30d", &cfg_threshold) < 1) {
1996 ast_log(LOG_WARNING,
"Unable to convert '%s' to a numeric value.\n", v->
value);
1997 }
else if (cfg_threshold < 1) {
1998 ast_log(LOG_WARNING,
"Invalid dtmf_misses_to_end value '%d' specified, using default of %d\n", cfg_threshold, dtmf_misses_to_end);
2000 dtmf_misses_to_end = cfg_threshold;
2011 return thresholds[which];
2014 #ifdef TEST_FRAMEWORK
2015 static void test_tone_sample_gen(
short *slin_buf,
int samples,
int rate,
int freq,
short amplitude)
2018 double sample_step = 2.0 * M_PI * freq / rate;
2020 for (idx = 0; idx < samples; ++idx) {
2021 slin_buf[idx] = amplitude * sin(sample_step * idx);
2026 #ifdef TEST_FRAMEWORK
2027 static void test_tone_sample_gen_add(
short *slin_buf,
int samples,
int rate,
int freq,
short amplitude)
2030 double sample_step = 2.0 * M_PI * freq / rate;
2032 for (idx = 0; idx < samples; ++idx) {
2033 slin_buf[idx] += amplitude * sin(sample_step * idx);
2038 #ifdef TEST_FRAMEWORK
2039 static void test_dual_sample_gen(
short *slin_buf,
int samples,
int rate,
int f1,
short a1,
int f2,
short a2)
2041 test_tone_sample_gen(slin_buf, samples, rate, f1, a1);
2042 test_tone_sample_gen_add(slin_buf, samples, rate, f2, a2);
2046 #ifdef TEST_FRAMEWORK
2047 #define TONE_AMPLITUDE_MAX 0x7fff
2048 #define TONE_AMPLITUDE_MIN 80
2052 short slin_buf[tone_state->block_size];
2059 { .amp_val = TONE_AMPLITUDE_MAX, .detect = 1, },
2060 { .amp_val = 10000, .detect = 1, },
2061 { .amp_val = 1000, .detect = 1, },
2062 { .amp_val = 100, .detect = 1, },
2063 { .amp_val = TONE_AMPLITUDE_MIN, .detect = 1, },
2064 { .amp_val = 75, .detect = 0, },
2065 { .amp_val = 10, .detect = 0, },
2066 { .amp_val = 1, .detect = 0, },
2071 for (idx = 0; idx < ARRAY_LEN(amp_tests); ++idx) {
2075 ast_debug(1,
"Test %d Hz at amplitude %d\n",
2076 tone_state->freq, amp_tests[idx].amp_val);
2077 test_tone_sample_gen(slin_buf, tone_state->block_size, DEFAULT_SAMPLE_RATE,
2078 tone_state->freq, amp_tests[idx].amp_val);
2081 for (duration = 0; !detected && duration < tone_state->hits_required + 3; ++duration) {
2082 detected = tone_detect(dsp, tone_state, slin_buf, tone_state->block_size) ? 1 : 0;
2084 if (amp_tests[idx].detect != detected) {
2092 "Test %d Hz at amplitude %d failed. Detected: %s\n",
2093 tone_state->freq, amp_tests[idx].amp_val,
2094 detected ?
"yes" :
"no");
2095 ast_test_status_update(test,
2096 "Test %d Hz at amplitude %d failed. Detected: %s\n",
2097 tone_state->freq, amp_tests[idx].amp_val,
2098 detected ?
"yes" :
"no");
2101 tone_state->hit_count = 0;
2108 #ifdef TEST_FRAMEWORK
2109 static int test_dtmf_amplitude_sweep(
struct ast_test *test,
struct ast_dsp *dsp,
int digit_index)
2111 short slin_buf[DTMF_GSIZE];
2124 { .amp_val = TONE_AMPLITUDE_MAX/2, .digit = dtmf_positions[digit_index], },
2125 { .amp_val = 10000, .digit = dtmf_positions[digit_index], },
2126 { .amp_val = 1000, .digit = dtmf_positions[digit_index], },
2127 { .amp_val = 500, .digit = dtmf_positions[digit_index], },
2128 { .amp_val = 250, .digit = dtmf_positions[digit_index], },
2129 { .amp_val = 200, .digit = dtmf_positions[digit_index], },
2130 { .amp_val = 180, .digit = dtmf_positions[digit_index], },
2132 { .amp_val = 170, .digit = 0, },
2133 { .amp_val = 100, .digit = 0, },
2138 { .amp_val = TONE_AMPLITUDE_MIN, .digit = 0, },
2139 { .amp_val = 75, .digit = 0, },
2140 { .amp_val = 10, .digit = 0, },
2141 { .amp_val = 1, .digit = 0, },
2144 row = (digit_index >> 2) & 0x03;
2145 column = digit_index & 0x03;
2149 for (idx = 0; idx < ARRAY_LEN(amp_tests); ++idx) {
2153 ast_debug(1,
"Test '%c' at amplitude %d\n",
2154 dtmf_positions[digit_index], amp_tests[idx].amp_val);
2155 test_dual_sample_gen(slin_buf, ARRAY_LEN(slin_buf), DEFAULT_SAMPLE_RATE,
2156 (
int) dtmf_row[row], amp_tests[idx].amp_val,
2157 (
int) dtmf_col[column], amp_tests[idx].amp_val);
2160 for (duration = 0; !digit && duration < 3; ++duration) {
2161 digit = dtmf_detect(dsp, &dsp->digit_state, slin_buf, ARRAY_LEN(slin_buf),
2164 if (amp_tests[idx].digit != digit) {
2172 "Test '%c' at amplitude %d failed. Detected Digit: '%c'\n",
2173 dtmf_positions[digit_index], amp_tests[idx].amp_val,
2175 ast_test_status_update(test,
2176 "Test '%c' at amplitude %d failed. Detected Digit: '%c'\n",
2177 dtmf_positions[digit_index], amp_tests[idx].amp_val,
2188 #ifdef TEST_FRAMEWORK
2189 static int test_dtmf_twist_sweep(
struct ast_test *test,
struct ast_dsp *dsp,
int digit_index)
2191 short slin_buf[DTMF_GSIZE];
2208 { .amp_row = 1000 + 1800, .amp_col = 1000 + 0, .digit = 0, },
2209 { .amp_row = 1000 + 1700, .amp_col = 1000 + 0, .digit = 0, },
2211 { .amp_row = 1000 + 1400, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
2212 { .amp_row = 1000 + 1300, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
2213 { .amp_row = 1000 + 1200, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
2214 { .amp_row = 1000 + 1100, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
2215 { .amp_row = 1000 + 1000, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
2216 { .amp_row = 1000 + 100, .amp_col = 1000 + 0, .digit = dtmf_positions[digit_index], },
2217 { .amp_row = 1000 + 0, .amp_col = 1000 + 100, .digit = dtmf_positions[digit_index], },
2218 { .amp_row = 1000 + 0, .amp_col = 1000 + 200, .digit = dtmf_positions[digit_index], },
2219 { .amp_row = 1000 + 0, .amp_col = 1000 + 300, .digit = dtmf_positions[digit_index], },
2220 { .amp_row = 1000 + 0, .amp_col = 1000 + 400, .digit = dtmf_positions[digit_index], },
2221 { .amp_row = 1000 + 0, .amp_col = 1000 + 500, .digit = dtmf_positions[digit_index], },
2222 { .amp_row = 1000 + 0, .amp_col = 1000 + 550, .digit = dtmf_positions[digit_index], },
2224 { .amp_row = 1000 + 0, .amp_col = 1000 + 650, .digit = 0, },
2225 { .amp_row = 1000 + 0, .amp_col = 1000 + 700, .digit = 0, },
2226 { .amp_row = 1000 + 0, .amp_col = 1000 + 800, .digit = 0, },
2228 float save_normal_twist;
2229 float save_reverse_twist;
2231 save_normal_twist = dtmf_normal_twist;
2232 save_reverse_twist = dtmf_reverse_twist;
2233 dtmf_normal_twist = DEF_DTMF_NORMAL_TWIST;
2234 dtmf_reverse_twist = DEF_DTMF_REVERSE_TWIST;
2236 row = (digit_index >> 2) & 0x03;
2237 column = digit_index & 0x03;
2241 for (idx = 0; idx < ARRAY_LEN(twist_tests); ++idx) {
2245 ast_debug(1,
"Test '%c' twist row %d col %d amplitudes\n",
2246 dtmf_positions[digit_index],
2247 twist_tests[idx].amp_row, twist_tests[idx].amp_col);
2248 test_dual_sample_gen(slin_buf, ARRAY_LEN(slin_buf), DEFAULT_SAMPLE_RATE,
2249 (
int) dtmf_row[row], twist_tests[idx].amp_row,
2250 (
int) dtmf_col[column], twist_tests[idx].amp_col);
2253 for (duration = 0; !digit && duration < 3; ++duration) {
2254 digit = dtmf_detect(dsp, &dsp->digit_state, slin_buf, ARRAY_LEN(slin_buf),
2257 if (twist_tests[idx].digit != digit) {
2265 "Test '%c' twist row %d col %d amplitudes failed. Detected Digit: '%c'\n",
2266 dtmf_positions[digit_index],
2267 twist_tests[idx].amp_row, twist_tests[idx].amp_col,
2269 ast_test_status_update(test,
2270 "Test '%c' twist row %d col %d amplitudes failed. Detected Digit: '%c'\n",
2271 dtmf_positions[digit_index],
2272 twist_tests[idx].amp_row, twist_tests[idx].amp_col,
2279 dtmf_normal_twist = save_normal_twist;
2280 dtmf_reverse_twist = save_reverse_twist;
2286 #ifdef TEST_FRAMEWORK
2287 static int test_tone_freq_sweep(
struct ast_test *test,
struct ast_dsp *dsp,
tone_detect_state_t *tone_state,
short amplitude)
2289 short slin_buf[tone_state->block_size];
2296 lower_freq = tone_state->freq - 4;
2297 upper_freq = tone_state->freq + 4;
2302 for (freq = 100; freq <= 3500; freq += 1) {
2305 int expect_detection;
2307 if (freq == tone_state->freq) {
2312 expect_detection = (lower_freq <= freq && freq <= upper_freq) ? 1 : 0;
2314 ast_debug(1,
"Test %d Hz detection given %d Hz tone at amplitude %d. Range:%d-%d Expect detect: %s\n",
2315 tone_state->freq, freq, amplitude, lower_freq, upper_freq,
2316 expect_detection ?
"yes" :
"no");
2317 test_tone_sample_gen(slin_buf, tone_state->block_size, DEFAULT_SAMPLE_RATE, freq,
2321 for (duration = 0; !detected && duration < tone_state->hits_required + 3; ++duration) {
2322 detected = tone_detect(dsp, tone_state, slin_buf, tone_state->block_size) ? 1 : 0;
2324 if (expect_detection != detected) {
2332 "Test %d Hz detection given %d Hz tone at amplitude %d failed. Range:%d-%d Detected: %s\n",
2333 tone_state->freq, freq, amplitude, lower_freq, upper_freq,
2334 detected ?
"yes" :
"no");
2335 ast_test_status_update(test,
2336 "Test %d Hz detection given %d Hz tone at amplitude %d failed. Range:%d-%d Detected: %s\n",
2337 tone_state->freq, freq, amplitude, lower_freq, upper_freq,
2338 detected ?
"yes" :
"no");
2341 tone_state->hit_count = 0;
2348 #ifdef TEST_FRAMEWORK
2352 enum ast_test_result_state result;
2357 info->category =
"/main/dsp/";
2358 info->summary =
"DSP fax tone detect unit test";
2360 "Tests fax tone detection code.";
2361 return AST_TEST_NOT_RUN;
2368 return AST_TEST_FAIL;
2371 result = AST_TEST_PASS;
2374 if (test_tone_amplitude_sweep(test, dsp, &dsp->cng_tone_state)) {
2375 result = AST_TEST_FAIL;
2379 if (test_tone_amplitude_sweep(test, dsp, &dsp->ced_tone_state)) {
2380 result = AST_TEST_FAIL;
2384 if (test_tone_freq_sweep(test, dsp, &dsp->cng_tone_state, TONE_AMPLITUDE_MAX)) {
2385 result = AST_TEST_FAIL;
2387 if (test_tone_freq_sweep(test, dsp, &dsp->cng_tone_state, TONE_AMPLITUDE_MIN)) {
2388 result = AST_TEST_FAIL;
2392 if (test_tone_freq_sweep(test, dsp, &dsp->ced_tone_state, TONE_AMPLITUDE_MAX)) {
2393 result = AST_TEST_FAIL;
2395 if (test_tone_freq_sweep(test, dsp, &dsp->ced_tone_state, TONE_AMPLITUDE_MIN)) {
2396 result = AST_TEST_FAIL;
2404 #ifdef TEST_FRAMEWORK
2409 enum ast_test_result_state result;
2413 info->name =
"dtmf";
2414 info->category =
"/main/dsp/";
2415 info->summary =
"DSP DTMF detect unit test";
2417 "Tests DTMF detection code.";
2418 return AST_TEST_NOT_RUN;
2425 return AST_TEST_FAIL;
2428 result = AST_TEST_PASS;
2430 for (idx = 0; dtmf_positions[idx]; ++idx) {
2431 if (test_dtmf_amplitude_sweep(test, dsp, idx)) {
2432 result = AST_TEST_FAIL;
2436 for (idx = 0; dtmf_positions[idx]; ++idx) {
2437 if (test_dtmf_twist_sweep(test, dsp, idx)) {
2438 result = AST_TEST_FAIL;
2447 static int unload_module(
void)
2449 AST_TEST_UNREGISTER(test_dsp_fax_detect);
2450 AST_TEST_UNREGISTER(test_dsp_dtmf_detect);
2455 static int load_module(
void)
2461 AST_TEST_REGISTER(test_dsp_fax_detect);
2462 AST_TEST_REGISTER(test_dsp_dtmf_detect);
2467 static int reload_module(
void)
2469 return _dsp_init(1);
2472 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER,
"DSP",
2473 .support_level = AST_MODULE_SUPPORT_CORE,
2474 .load = load_module,
2475 .unload = unload_module,
2476 .reload = reload_module,
2478 .requires =
"extconfig",
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...
A-Law to Signed linear conversion.
struct ast_variable * next
#define DSP_PROGRESS_RINGING
Main Channel structure associated with a channel.
Asterisk main include file. File version handling, generic pbx functions.
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...
#define DSP_DIGITMODE_DTMF
void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
Set the minimum average magnitude threshold to determine talking by the DSP.
Convenient Signal Processing routines.
#define DSP_DIGITMODE_MUTECONF
#define DSP_PROGRESS_BUSY
static const int DEFAULT_SILENCE_THRESHOLD
The default silence threshold we will use if an alternate configured value is not present or is inval...
int ast_dsp_set_call_progress_zone(struct ast_dsp *dsp, char *zone)
Set zone for doing progress detection.
#define DSP_PROGRESS_TALK
int ast_dsp_get_features(struct ast_dsp *dsp)
Get features.
int ast_dsp_set_digitmode(struct ast_dsp *dsp, int digitmode)
Set digit mode.
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Structure for variables, used for configurations and for channel variables.
#define DSP_PROGRESS_CONGESTION
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 ...
void ast_dsp_reset(struct ast_dsp *dsp)
Reset total silence count.
struct ast_frame_subclass subclass
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Process the audio frame for silence.
int ast_dsp_noise(struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise)
Process the audio frame for noise.
Configuration File Parser.
#define DSP_DIGITMODE_RELAXDTMF
u-Law to Signed linear conversion
General Asterisk PBX channel definitions.
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
void ast_dsp_digitreset(struct ast_dsp *dsp)
Reset DTMF detector.
Asterisk internal frame definitions.
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
#define ast_debug(level,...)
Log a DEBUG message.
#define DEFAULT_THRESHOLD
Default minimum average magnitude threshold to determine talking/noise by the DSP.
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define DSP_DIGITMODE_MUTEMAX
int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf)
Scans for progress indication in audio.
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.
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.
unsigned int ast_dsp_get_sample_rate(const struct ast_dsp *dsp)
Retrieve the sample rate this DSP structure was created with.
union ast_frame::@224 data
#define ast_calloc(num, len)
A wrapper for calloc()
Module could not be loaded properly.
int ast_dsp_set_faxmode(struct ast_dsp *dsp, int faxmode)
Set fax mode.
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
int ast_dsp_get_tcount(struct ast_dsp *dsp)
Get tcount (Threshold counter)
Structure used to handle boolean flags.
int ast_dsp_get_tstate(struct ast_dsp *dsp)
Get tstate (Tone State)
Data structure associated with a single frame of data.
#define AST_TEST_DEFINE(hdr)
Options provided by main asterisk program.
void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, const struct ast_dsp_busy_pattern *cadence)
Set expected lengths of the busy tone.
enum ast_frame_type frametype
#define DSP_DIGITMODE_NOQUELCH
struct ast_format * format
#define DSP_FEATURE_FREQ_DETECT
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
#define DSP_FEATURE_WAITDIALTONE
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
int ast_dsp_set_freqmode(struct ast_dsp *dsp, int freq, int dur, int db, int squelch)
Set arbitrary frequency detection mode.
void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
Set number of required cadences for busy.