--- dsp.c.dist 2006-03-20 15:23:21.000000000 -0600 +++ dsp.c 2006-03-21 14:55:31.000000000 -0600 @@ -61,10 +61,12 @@ #define GSAMP_SIZE_NA 183 /* North America - 350, 440, 480, 620, 950, 1400, 1800 Hz */ #define GSAMP_SIZE_CR 188 /* Costa Rica, Brazil - Only care about 425 Hz */ #define GSAMP_SIZE_UK 160 /* UK disconnect goertzel feed - shoud trigger 400hz */ +#define GSAMP_SIZE_HN 183 /* Honduras - Patch Copyleft 2006 by Chris Maj */ #define PROG_MODE_NA 0 #define PROG_MODE_CR 1 #define PROG_MODE_UK 2 +#define PROG_MODE_HN 3 /* For US modes */ #define HZ_350 0 @@ -90,6 +92,7 @@ { "cr", PROG_MODE_CR }, { "br", PROG_MODE_CR }, { "uk", PROG_MODE_UK }, + { "hn", PROG_MODE_HN }, }; static struct progress { @@ -99,6 +102,7 @@ { GSAMP_SIZE_NA, { 350, 440, 480, 620, 950, 1400, 1800 } }, /* North America */ { GSAMP_SIZE_CR, { 425 } }, { GSAMP_SIZE_UK, { 400 } }, + { GSAMP_SIZE_HN, { 400, 440, 480, 620, 950, 350, 1800 } }, /* Honduras */ }; #define DEFAULT_THRESHOLD 512 @@ -119,6 +123,8 @@ #define TONE_MIN_THRESH 1e8 /* How much tone there should be at least to attempt */ #define COUNT_THRESH 3 /* Need at least 50ms of stuff to count it */ #define UK_HANGUP_THRESH 60 /* This is the threshold for the UK */ +#define HN_RING_THRESH 10 /* This is the threshold for counting Honduras rings */ +#define SILENCE_BUCKETS 50 /* This is the count of Honduras silence buckets */ #define MAX_DTMF_DIGITS 128 @@ -329,6 +335,10 @@ int digitmode; int thinkdigit; float genergy; + float avg_silence_genergy; + float silence_buckets[SILENCE_BUCKETS]; + int total_silence_hits; + int ring_received; union { dtmf_detect_state_t dtmf; mf_detect_state_t mf; @@ -1035,6 +1045,8 @@ int pass; int newstate = DSP_TONE_STATE_SILENCE; int res = 0; + float thresh_tone, thresh_talk, cumulative_silence; + int i; int thresh = (dsp->progmode == PROG_MODE_UK) ? UK_HANGUP_THRESH : COUNT_THRESH; while(len) { /* Take the lesser of the number of samples we need and what we have */ @@ -1079,6 +1091,53 @@ } else newstate = DSP_TONE_STATE_SILENCE; break; + case PROG_MODE_HN: + /* if theres been enough silence on the line to account for a reasonable average line energy, then use that */ + if(dsp->total_silence_hits > SILENCE_BUCKETS) { + thresh_talk = dsp->avg_silence_genergy * 2.0; + thresh_tone = dsp->avg_silence_genergy * 1000.0; + } else { + thresh_talk = 0; + thresh_tone = TONE_MIN_THRESH * TONE_THRESH; + } + //ast_log(LOG_DEBUG, "400 %.2e 440 %.2e energy %.2e hardmin %.2e thresh_talk %.2e thresh_tone %.2e\n", hz[HZ_400], hz[HZ_440], dsp->genergy, TONE_MIN_THRESH * TONE_THRESH, thresh_talk, thresh_tone); + if (hz[HZ_400] > thresh_tone && hz[HZ_400] > hz[HZ_440]) { + //ast_log(LOG_DEBUG, "Honduras Hum and/or Honduras Busy\n"); + newstate = DSP_TONE_STATE_SILENCE; + } else if (hz[HZ_440] > thresh_tone && hz[HZ_440] > hz[HZ_400]) { + //ast_log(LOG_DEBUG, "Honduras Ringing\n"); + thresh = HN_RING_THRESH; + newstate = DSP_TONE_STATE_RINGING; + } else if (dsp->genergy > thresh_talk && thresh_talk > 0) { + /* pull the ring_received check right below if lots of numbers do not produce a ring before answering */ + /* the downside to removing the check is that any telco-generated spoken error messages (disco, busy, etc.) will be answered */ + if (dsp->tstate != DSP_TONE_STATE_RINGING && dsp->ring_received) { + //ast_log(LOG_DEBUG, "Honduras Really Talking\n"); + newstate = DSP_TONE_STATE_TALKING; + } else { + //ast_log(LOG_DEBUG, "Honduras Possibly Talking\n"); + newstate = DSP_TONE_STATE_SILENCE; + } + } else { + /* collect a running average of recent silence on the line for talk energy comparisons */ + //ast_log(LOG_DEBUG, "Honduras Silence\n"); + if(dsp->genergy > 0) { + dsp->silence_buckets[dsp->total_silence_hits % SILENCE_BUCKETS] = dsp->genergy; + if(dsp->total_silence_hits >= SILENCE_BUCKETS) { + cumulative_silence=0.0; + for(i=0;isilence_buckets[i]; + dsp->avg_silence_genergy = cumulative_silence / SILENCE_BUCKETS; + } + /* prevent silence hits from overflowing */ + if(dsp->total_silence_hits == 2 * SILENCE_BUCKETS) + dsp->total_silence_hits = SILENCE_BUCKETS; + else + dsp->total_silence_hits++; + } + newstate = DSP_TONE_STATE_SILENCE; + } + break; case PROG_MODE_CR: if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) { newstate = DSP_TONE_STATE_RINGING; @@ -1107,9 +1166,10 @@ res = AST_CONTROL_ANSWER; dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; } else if ((dsp->features & DSP_PROGRESS_RINGING) && - dsp->tstate == DSP_TONE_STATE_RINGING) + dsp->tstate == DSP_TONE_STATE_RINGING) { res = AST_CONTROL_RINGING; - else if ((dsp->features & DSP_PROGRESS_CONGESTION) && + dsp->ring_received = 1; + } else if ((dsp->features & DSP_PROGRESS_CONGESTION) && dsp->tstate == DSP_TONE_STATE_SPECIAL3) { res = AST_CONTROL_CONGESTION; dsp->features &= ~DSP_FEATURE_CALL_PROGRESS; @@ -1561,6 +1621,9 @@ dsp->gsamp_size = modes[dsp->progmode].size; dsp->gsamps = 0; + dsp->total_silence_hits = 0; + dsp->avg_silence_genergy = 0; + dsp->ring_received = 0; for (x=0;xprogmode].freqs) / sizeof(modes[dsp->progmode].freqs[0]);x++) { if (modes[dsp->progmode].freqs[x]) { goertzel_init(&dsp->freqs[x], (float)modes[dsp->progmode].freqs[x], dsp->gsamp_size);