Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.sbin / i4b / dtmfdecode / dtmfdecode.c
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  * ----------------------------------------------------------------------------
8  *
9  * $Id: dtmfdecode.c,v 1.6 1999/12/13 21:25:24 hm Exp $
10  *
11  * $FreeBSD: src/usr.sbin/i4b/dtmfdecode/dtmfdecode.c,v 1.4.2.1 2001/08/01 17:45:02 obrien Exp $
12  *
13  * Extract DTMF signalling from ISDN4BSD A-law coded audio data
14  *
15  * A-Law to linear conversion from the sox package.
16  *
17  */
18
19 #include <stdio.h>
20 #include <math.h>
21
22 /* Integer math scaling factor */
23 #define FSC     (1<<12)
24
25 /* Alaw parameters */
26 #define SIGN_BIT        (0x80)          /* Sign bit for a A-law byte. */
27 #define QUANT_MASK      (0xf)           /* Quantization field mask. */
28 #define SEG_SHIFT       (4)             /* Left shift for segment number. */
29 #define SEG_MASK        (0x70)          /* Segment field mask. */
30
31 static int
32 alaw2linear(a_val)
33         unsigned char   a_val;
34 {
35         int             t;
36         int             seg;
37
38         a_val ^= 0x55;
39
40         t = (a_val & QUANT_MASK) << 4;
41         seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
42         switch (seg) {
43         case 0:
44                 t += 8;
45                 break;
46         case 1:
47                 t += 0x108;
48                 break;
49         default:
50                 t += 0x108;
51                 t <<= seg - 1;
52         }
53         return ((a_val & SIGN_BIT) ? t : -t);
54 }
55
56 #ifdef USE_COS
57 /* The frequencies we're trying to detect */
58 static int dtmf[8] = {697, 770, 852, 941, 1209, 1336, 1477, 1633};
59 #else
60 /* precalculated: p1[kk] = (-cos(2 * 3.141592 * dtmf[kk] / 8000.0) * FSC) */
61 static int p1[8] = {-3497, -3369, -3212, -3027, -2384, -2040, -1635, -1164};
62 #endif
63
64 /* This is the Q of the filter (pole radius) */
65 #define POLRAD .99
66
67 #define P2 ((int)(POLRAD*POLRAD*FSC))
68
69 int
70 main(int argc, char **argv)
71 {
72         int i, kk, t, nn, s, so, ia;
73         int x, c, d, f, h[8], k[8], n, y[8];
74 #ifdef USE_COS
75         int p1[8];
76 #endif  
77         int alaw[256];
78         char key[256];
79
80         for (kk = 0; kk < 8; kk++) {
81                 y[kk] = h[kk] = k[kk] = 0;
82 #ifdef USE_COS
83                 p1[kk] = (-cos(2 * 3.141592 * dtmf[kk] / 8000.0) * FSC);
84 #endif          
85         }
86
87         for (i = 0; i < 256; i++) {
88                 key[i] = '?';
89                 alaw[i] = alaw2linear(i) / (32768/FSC);
90         }
91
92         /* We encode the tones in 8 bits, translate those to symbol */
93         key[0x00] = '\0';
94
95         key[0x11] = '1'; key[0x12] = '4'; key[0x14] = '7'; key[0x18] = '*';
96         key[0x21] = '2'; key[0x22] = '5'; key[0x24] = '8'; key[0x28] = '0';
97         key[0x41] = '3'; key[0x42] = '6'; key[0x44] = '9'; key[0x48] = '#';
98         key[0x81] = 'A'; key[0x82] = 'B'; key[0x84] = 'C'; key[0x88] = 'D';
99
100         nn = 0;
101         ia = 0;
102         so = 0;
103         t = 0;
104         while ((i = getchar()) != EOF)
105         {
106                 t++;
107
108                 /* Convert to our format */
109                 x = alaw[i];
110
111                 /* Input amplitude */
112                 if (x > 0)
113                         ia += (x - ia) / 128;
114                 else
115                         ia += (-x - ia) / 128;
116
117                 /* For each tone */
118                 s = 0;
119                 for(kk = 0; kk < 8; kk++) {
120
121                         /* Turn the crank */
122                         c = (P2 * (x - k[kk])) / FSC;
123                         d = x + c;
124                         f = (p1[kk] * (d - h[kk])) / FSC;
125                         n = x - k[kk] - c;
126                         k[kk] = h[kk] + f;
127                         h[kk] = f + d;
128
129                         /* Detect and Average */
130                         if (n > 0)
131                                 y[kk] += (n - y[kk]) / 64;
132                         else
133                                 y[kk] += (-n - y[kk]) / 64;
134
135                         /* Threshold */
136                         if (y[kk] > FSC/10 && y[kk] > ia)
137                                 s |= 1 << kk;
138                 }
139
140                 /* Hysteresis and noise supressor */
141                 if (s != so) {
142 /* printf("x %d %x -> %x\n",t,so, s); */
143                         nn = 0;
144                         so = s;
145                 } else if (nn++ == 520 && key[s]) {
146                         putchar(key[s]);
147 /* printf(" %d %x\n",t,s); */
148                 }
149         }
150         putchar('\n');
151         return (0);
152 }