Index: main/dsp.c =================================================================== --- main/dsp.c (revision 262325) +++ main/dsp.c (working copy) @@ -274,6 +274,10 @@ { char digits[MAX_DTMF_DIGITS + 1]; int current_digits; + /* Store lengths separately, because next digit may begin before last has + * ended (because hits_to_begin may be less than misses_to_end). */ + int digitlen[MAX_DTMF_DIGITS + 1]; + int current_len; int detected_digits; int lost_digits; @@ -503,6 +507,7 @@ static void ast_digit_detect_init(digit_detect_state_t *s, int mf) { s->current_digits = 0; + s->current_len = 0; s->detected_digits = 0; s->lost_digits = 0; s->digits[0] = '\0'; @@ -622,6 +627,7 @@ { s->detected_digits++; if (s->current_digits < MAX_DTMF_DIGITS) { + s->digitlen[s->current_digits] = 0; s->digits[s->current_digits++] = digit; s->digits[s->current_digits] = '\0'; } else { @@ -722,6 +728,7 @@ 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; + s->digitlen[s->current_len++] = s->td.dtmf.hits * DTMF_GSIZE; } } else { s->td.dtmf.misses = 0; @@ -1383,7 +1390,7 @@ digit = dtmf_detect(dsp, &dsp->digit_state, shortdata, len, (dsp->digitmode & DSP_DIGITMODE_NOQUELCH) == 0, (dsp->digitmode & DSP_DIGITMODE_RELAXDTMF)); if (dsp->digit_state.current_digits) { - int event = 0; + int event = 0, event_len; char event_digit = 0; if (!dsp->dtmf_began) { @@ -1395,14 +1402,18 @@ } dsp->dtmf_began = 1; - } else if (dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) { + /* Don't transmit the end until we have a length. New beginnings can be detected before previous endings. */ + } else if ((dsp->digit_state.current_digits > 1 || digit != dsp->digit_state.digits[0]) && dsp->digit_state.digitlen[0] > 0) { /* Digit changed. This means digit we have reported with DTMF_BEGIN ended */ if (dsp->features & DSP_FEATURE_DIGIT_DETECT) { event = AST_FRAME_DTMF_END; event_digit = dsp->digit_state.digits[0]; + event_len = dsp->digit_state.digitlen[0] * 1000 / SAMPLE_RATE; } - memmove(dsp->digit_state.digits, dsp->digit_state.digits + 1, dsp->digit_state.current_digits); + memmove(&dsp->digit_state.digits[0], &dsp->digit_state.digits[1], dsp->digit_state.current_digits); dsp->digit_state.current_digits--; + memmove(&dsp->digit_state.digitlen[0], &dsp->digit_state.digitlen[1], dsp->digit_state.current_len * sizeof(dsp->digit_state.digitlen[0])); + dsp->digit_state.current_len--; dsp->dtmf_began = 0; if (dsp->features & DSP_FEATURE_BUSY_DETECT) { @@ -1417,6 +1428,7 @@ memset(&dsp->f, 0, sizeof(dsp->f)); dsp->f.frametype = event; dsp->f.subclass.integer = event_digit; + dsp->f.len = event_len; outf = &dsp->f; goto done; }