Added a parameter to semaphore constructor to avoid ambiguity
[pwlib.git] / src / ptclib / dtmf.cxx
blobe1fdb75e5b422120591c7f75aca02f1406cd8cb7
1 /*
2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
9 * Extract DTMF signals from 16 bit PCM audio
11 * Originally written by Poul-Henning Kamp <phk@freebsd.org>
12 * Made into a C++ class by Roger Hardiman <roger@freebsd.org>, January 2002
14 * $Log$
15 * Revision 1.7 2003/03/17 07:39:25 robertj
16 * Fixed possible invalid value causing DTMF detector to crash.
18 * Revision 1.6 2002/02/20 02:59:34 yurik
19 * Added end of line to trace statement
21 * Revision 1.5 2002/02/12 10:21:56 rogerh
22 * Stop sending '?' when a bad DTMF tone is detected.
24 * Revision 1.4 2002/01/24 11:14:45 rogerh
25 * Back out robert's change. It did not work (no sign extending)
26 * and replace it with a better solution which should be happy on both big
27 * endian and little endian systems.
29 * Revision 1.3 2002/01/24 10:40:17 rogerh
30 * Add version log
35 #ifdef __GNUC__
36 #pragma implementation "dtmf.h"
37 #endif
39 #include <ptlib.h>
40 #include <ptclib/dtmf.h>
43 /* Integer math scaling factor */
44 #define FSC (1<<12)
46 /* This is the Q of the filter (pole radius) */
47 #define POLRAD .99
49 #define P2 ((int)(POLRAD*POLRAD*FSC))
53 PDTMFDecoder::PDTMFDecoder()
55 // Initialise the class
56 int i,kk;
57 for (kk = 0; kk < 8; kk++) {
58 y[kk] = h[kk] = k[kk] = 0;
61 nn = 0;
62 ia = 0;
63 so = 0;
65 for (i = 0; i < 256; i++) {
66 key[i] = '?';
69 /* We encode the tones in 8 bits, translate those to symbol */
70 key[0x11] = '1'; key[0x12] = '4'; key[0x14] = '7'; key[0x18] = '*';
71 key[0x21] = '2'; key[0x22] = '5'; key[0x24] = '8'; key[0x28] = '0';
72 key[0x41] = '3'; key[0x42] = '6'; key[0x44] = '9'; key[0x48] = '#';
73 key[0x81] = 'A'; key[0x82] = 'B'; key[0x84] = 'C'; key[0x88] = 'D';
75 /* The frequencies we're trying to detect */
76 /* These are precalculated to save processing power */
77 /* static int dtmf[8] = {697, 770, 852, 941, 1209, 1336, 1477, 1633}; */
78 /* p1[kk] = (-cos(2 * 3.141592 * dtmf[kk] / 8000.0) * FSC) */
79 p1[0] = -3497; p1[1] = -3369; p1[2] = -3212; p1[3] = -3027;
80 p1[4] = -2384; p1[5] = -2040; p1[6] = -1635; p1[7] = -1164;
84 PString PDTMFDecoder::Decode(const void *buf, PINDEX bytes)
86 int x;
87 int s, kk;
88 int c, d, f, n;
89 short *buffer = (short *)buf;
91 PINDEX numSamples = bytes >> 1;
93 PString keyString;
95 PINDEX pos;
96 for (pos = 0; pos < numSamples; pos++) {
98 /* Read (and scale) the next 16 bit sample */
99 x = ((int)(*buffer++)) / (32768/FSC);
101 /* Input amplitude */
102 if (x > 0)
103 ia += (x - ia) / 128;
104 else
105 ia += (-x - ia) / 128;
107 /* For each tone */
108 s = 0;
109 for(kk = 0; kk < 8; kk++) {
111 /* Turn the crank */
112 c = (P2 * (x - k[kk])) / FSC;
113 d = x + c;
114 f = (p1[kk] * (d - h[kk])) / FSC;
115 n = x - k[kk] - c;
116 k[kk] = h[kk] + f;
117 h[kk] = f + d;
119 /* Detect and Average */
120 if (n > 0)
121 y[kk] += (n - y[kk]) / 64;
122 else
123 y[kk] += (-n - y[kk]) / 64;
125 /* Threshold */
126 if (y[kk] > FSC/10 && y[kk] > ia)
127 s |= 1 << kk;
130 /* Hysteresis and noise supressor */
131 if (s != so) {
132 nn = 0;
133 so = s;
134 } else if (nn++ == 520 && s < 256 && key[s] != '?') {
135 PTRACE(3,"DTMF\tDetected '" << key[s] << "' in PCM-16 stream");
136 keyString += key[s];
139 return keyString;