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