summaryrefslogtreecommitdiff
path: root/main/dsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/dsp.c')
-rw-r--r--main/dsp.c121
1 files changed, 86 insertions, 35 deletions
diff --git a/main/dsp.c b/main/dsp.c
index 884f610e7..6ba9abdaa 100644
--- a/main/dsp.c
+++ b/main/dsp.c
@@ -205,9 +205,9 @@ enum gsamp_thresh {
#define DTMF_GSIZE 102
/* How many successive hits needed to consider begin of a digit */
-#define DTMF_HITS_TO_BEGIN 4
+#define DTMF_HITS_TO_BEGIN 2
/* How many successive misses needed to consider end of a digit */
-#define DTMF_MISSES_TO_END 4
+#define DTMF_MISSES_TO_END 3
/*!
* \brief The default silence threshold we will use if an alternate
@@ -353,7 +353,7 @@ typedef struct {
} fragment_t;
/* Note on tone suppression (squelching). Individual detectors (DTMF/MF/generic tone)
- * report fragmens of the frame in which detected tone resides and which needs
+ * report fragments of the frame in which detected tone resides and which needs
* to be "muted" in order to suppress the tone. To mark fragment for muting,
* detectors call mute_fragment passing fragment_t there. Multiple fragments
* can be marked and ast_dsp_process later will mute all of them.
@@ -438,7 +438,7 @@ static void ast_tone_detect_init(tone_detect_state_t *s, int freq, int duration,
s->block_size = periods_in_block * sample_rate / freq;
/* tone_detect is currently only used to detect fax tones and we
- do not need suqlching the fax tones */
+ do not need squelching the fax tones */
s->squelch = 0;
/* Account for the first and the last block to be incomplete
@@ -550,7 +550,7 @@ static int tone_detect(struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp
for (i = limit, ptr = amp ; i > 0; i--, ptr++) {
samp = *ptr;
- /* signed 32 bit int should be enough to suqare any possible signed 16 bit value */
+ /* signed 32 bit int should be enough to square any possible signed 16 bit value */
s->energy += (int32_t) samp * (int32_t) samp;
goertzel_sample(&s->tone, samp);
@@ -727,39 +727,90 @@ static int dtmf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp
}
}
- if (hit == s->td.dtmf.lasthit) {
- if (s->td.dtmf.current_hit) {
- /* We are in the middle of a digit already */
- if (hit) {
- if (hit != s->td.dtmf.current_hit) {
- /* Look for a start of a new digit.
- This is because hits_to_begin may be smaller than misses_to_end
- and we may find the beginning of new digit before we consider last one ended. */
- s->td.dtmf.current_hit = 0;
- } else {
- /* Current hit was same as last, so increment digit duration (of last digit) */
- s->digitlen[s->current_digits - 1] += DTMF_GSIZE;
- }
- } else {
- /* No Digit */
- s->td.dtmf.misses++;
- if (s->td.dtmf.misses == s->td.dtmf.misses_to_end) {
- /* There were enough misses to consider digit ended */
- s->td.dtmf.current_hit = 0;
- }
- }
- } else if (hit) {
- /* Detecting new digit */
- s->td.dtmf.hits++;
- if (s->td.dtmf.hits == s->td.dtmf.hits_to_begin) {
- store_digit(s, hit);
- s->td.dtmf.current_hit = hit;
+/*
+ * Adapted from ETSI ES 201 235-3 V1.3.1 (2006-03)
+ * (40ms reference is tunable with hits_to_begin and misses_to_end)
+ * each hit/miss is 12.75ms with DTMF_GSIZE at 102
+ *
+ * Character recognition: When not DRC *(1) and then
+ * Shall exist VSC > 40 ms (hits_to_begin)
+ * May exist 20 ms <= VSC <= 40 ms
+ * Shall not exist VSC < 20 ms
+ *
+ * Character recognition: When DRC and then
+ * Shall cease Not VSC > 40 ms (misses_to_end)
+ * May cease 20 ms >= Not VSC >= 40 ms
+ * Shall not cease Not VSC < 20 ms
+ *
+ * *(1) or optionally a different digit recognition condition
+ *
+ * Legend: VSC The continuous existence of a valid signal condition.
+ * Not VSC The continuous non-existence of valid signal condition.
+ * DRC The existence of digit recognition condition.
+ * Not DRC The non-existence of digit recognition condition.
+ */
+
+/*
+ * Example: hits_to_begin=2 misses_to_end=3
+ * -------A last_hit=A hits=0&1
+ * ------AA hits=2 current_hit=A misses=0 BEGIN A
+ * -----AA- misses=1 last_hit=' ' hits=0
+ * ----AA-- misses=2
+ * ---AA--- misses=3 current_hit=' ' END A
+ * --AA---B last_hit=B hits=0&1
+ * -AA---BC last_hit=C hits=0&1
+ * AA---BCC hits=2 current_hit=C misses=0 BEGIN C
+ * A---BCC- misses=1 last_hit=' ' hits=0
+ * ---BCC-C misses=0 last_hit=C hits=0&1
+ * --BCC-CC misses=0
+ *
+ * Example: hits_to_begin=3 misses_to_end=2
+ * -------A last_hit=A hits=0&1
+ * ------AA hits=2
+ * -----AAA hits=3 current_hit=A misses=0 BEGIN A
+ * ----AAAB misses=1 last_hit=B hits=0&1
+ * ---AAABB misses=2 current_hit=' ' hits=2 END A
+ * --AAABBB hits=3 current_hit=B misses=0 BEGIN B
+ * -AAABBBB misses=0
+ *
+ * Example: hits_to_begin=2 misses_to_end=2
+ * -------A last_hit=A hits=0&1
+ * ------AA hits=2 current_hit=A misses=0 BEGIN A
+ * -----AAB misses=1 hits=0&1
+ * ----AABB misses=2 current_hit=' ' hits=2 current_hit=B misses=0 BEGIN B
+ * ---AABBB misses=0
+ */
+
+ if (s->td.dtmf.current_hit) {
+ /* We are in the middle of a digit already */
+ if (hit != s->td.dtmf.current_hit) {
+ s->td.dtmf.misses++;
+ if (s->td.dtmf.misses == s->td.dtmf.misses_to_end) {
+ /* There were enough misses to consider digit ended */
+ s->td.dtmf.current_hit = 0;
}
+ } else {
+ s->td.dtmf.misses = 0;
+ /* Current hit was same as last, so increment digit duration (of last digit) */
+ s->digitlen[s->current_digits - 1] += DTMF_GSIZE;
}
- } else {
- s->td.dtmf.hits = 1;
- s->td.dtmf.misses = 1;
+ }
+
+ /* Look for a start of a new digit no matter if we are already in the middle of some
+ digit or not. This is because hits_to_begin may be smaller than misses_to_end
+ and we may find begin of new digit before we consider last one ended. */
+
+ if (hit != s->td.dtmf.lasthit) {
s->td.dtmf.lasthit = hit;
+ s->td.dtmf.hits = 0;
+ }
+ if (hit && hit != s->td.dtmf.current_hit) {
+ s->td.dtmf.hits++;
+ if (s->td.dtmf.hits == s->td.dtmf.hits_to_begin) {
+ store_digit(s, hit);
+ s->td.dtmf.current_hit = hit;
+ s->td.dtmf.misses = 0;
+ }
}
/* If we had a hit in this block, include it into mute fragment */