/* * DTMF decoder. * * Copyright by Andreas Eversberg (jolly@eversberg.eu) * based on different decoders such as ISDN4Linux * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. *
*/
/************************************************************* * calculate the coefficients of the given sample and decode *
*************************************************************/
/* the given sample is decoded. if the sample is not long enough for a * complete frame, the decoding is finished and continued with the next * call of this function. * * the algorithm is very good for detection with a minimum of errors. i * tested it allot. it even works with very short tones (40ms). the only * disadvantage is, that it doesn't work good with different volumes of both * tones. this will happen, if accoustically coupled dialers are used. * it sometimes detects tones during speech, which is normal for decoders. * use sequences to given commands during calls. * * dtmf - points to a structure of the current dtmf state * spl and len - the sample * fmt - 0 = alaw, 1 = ulaw, 2 = coefficients from HFC DTMF hw-decoder
*/
u8
*dsp_dtmf_goertzel_decode(struct dsp *dsp, u8 *data, int len, int fmt)
{
u8 what; int size; signedshort *buf;
s32 sk, sk1, sk2; int k, n, i;
s32 *hfccoeff;
s32 result[NCOEFF], tresh, treshl; int lowgroup, highgroup;
s64 cos2pik_;
dsp->dtmf.digits[0] = '\0';
/* Note: The function will loop until the buffer has not enough samples * left to decode a full frame.
*/
again: /* convert samples */
size = dsp->dtmf.size;
buf = dsp->dtmf.buffer; switch (fmt) { case 0: /* alaw */ case 1: /* ulaw */ while (size < DSP_DTMF_NPOINTS && len) {
buf[size++] = dsp_audio_law_to_s32[*data++];
len--;
} break;
case 2: /* HFC coefficients */ default: if (len < 64) { if (len > 0)
printk(KERN_ERR "%s: coefficients have invalid " "size. (is=%d < must=%d)\n",
__func__, len, 64); return dsp->dtmf.digits;
}
hfccoeff = (s32 *)data; for (k = 0; k < NCOEFF; k++) {
sk2 = (*hfccoeff++) >> 4;
sk = (*hfccoeff++) >> 4; if (sk > 32767 || sk < -32767 || sk2 > 32767
|| sk2 < -32767)
printk(KERN_WARNING "DTMF-Detection overflow\n"); /* compute |X(k)|**2 */
result[k] =
(sk * sk) -
(((cos2pik[k] * sk) >> 15) * sk2) +
(sk2 * sk2);
}
data += 64;
len -= 64; goto coefficients; break;
}
dsp->dtmf.size = size;
if (size < DSP_DTMF_NPOINTS) return dsp->dtmf.digits;
dsp->dtmf.size = 0;
/* now we have a full buffer of signed long samples - we do goertzel */ for (k = 0; k < NCOEFF; k++) {
sk = 0;
sk1 = 0;
sk2 = 0;
buf = dsp->dtmf.buffer;
cos2pik_ = cos2pik[k]; for (n = 0; n < DSP_DTMF_NPOINTS; n++) {
sk = ((cos2pik_ * sk1) >> 15) - sk2 + (*buf++);
sk2 = sk1;
sk1 = sk;
}
sk >>= 8;
sk2 >>= 8; if (sk > 32767 || sk < -32767 || sk2 > 32767 || sk2 < -32767)
printk(KERN_WARNING "DTMF-Detection overflow\n"); /* compute |X(k)|**2 */
result[k] =
(sk * sk) -
(((cos2pik[k] * sk) >> 15) * sk2) +
(sk2 * sk2);
}
/* our (squared) coefficients have been calculated, we need to process * them.
*/
coefficients:
tresh = 0; for (i = 0; i < NCOEFF; i++) { if (result[i] < 0)
result[i] = 0; if (result[i] > dsp->dtmf.treshold) { if (result[i] > tresh)
tresh = result[i];
}
}
if (tresh == 0) {
what = 0; goto storedigit;
}
if (dsp_debug & DEBUG_DSP_DTMFCOEFF) {
s32 tresh_100 = tresh/100;
/* calc digit (lowgroup/highgroup) */
lowgroup = -1;
highgroup = -1;
treshl = tresh >> 3; /* tones which are not on, must be below 9 dB */
tresh = tresh >> 2; /* touchtones must match within 6 dB */ for (i = 0; i < NCOEFF; i++) { if (result[i] < treshl) continue; /* ignore */ if (result[i] < tresh) {
lowgroup = -1;
highgroup = -1; break; /* noise in between */
} /* good level found. This is allowed only one time per group */ if (i < NCOEFF / 2) { /* lowgroup */ if (lowgroup >= 0) { /* Bad. Another tone found. */
lowgroup = -1; break;
} else
lowgroup = i;
} else { /* higroup */ if (highgroup >= 0) { /* Bad. Another tone found. */
highgroup = -1; break;
} else
highgroup = i - (NCOEFF / 2);
}
}
/* get digit or null */
what = 0; if (lowgroup >= 0 && highgroup >= 0)
what = dtmf_matrix[lowgroup][highgroup];
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.