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.3 2003/10/06 09:43:27 itojun Exp $
10 *
11 * $FreeBSD$
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/* A-law 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
31static int alaw2linear(unsigned char a_val)
32{
33        int             t;
34        int             seg;
35
36        a_val ^= 0x55;
37
38        t = (a_val & QUANT_MASK) << 4;
39        seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
40        switch (seg) {
41        case 0:
42                t += 8;
43                break;
44        case 1:
45                t += 0x108;
46                break;
47        default:
48                t += 0x108;
49                t <<= seg - 1;
50        }
51        return ((a_val & SIGN_BIT) ? t : -t);
52}
53
54#ifdef USE_COS
55/* The frequencies we're trying to detect */
56static int dtmf[8] = {697, 770, 852, 941, 1209, 1336, 1477, 1633};
57#else
58/* precalculated: p1[kk] = (-cos(2 * 3.141592 * dtmf[kk] / 8000.0) * FSC) */
59static int p1[8] = {-3497, -3369, -3212, -3027, -2384, -2040, -1635, -1164};
60#endif
61
62/* This is the Q of the filter (pole radius) */
63#define POLRAD .99
64
65#define P2 ((int)(POLRAD*POLRAD*FSC))
66
67int
68main(int argc, char **argv)
69{
70	int i, kk, t, nn, s, so, ia;
71	int x, c, d, f, h[8], k[8], n, y[8];
72#ifdef USE_COS
73	int p1[8];
74#endif
75	int alaw[256];
76	char key[256];
77
78	for (kk = 0; kk < 8; kk++) {
79		y[kk] = h[kk] = k[kk] = 0;
80#ifdef USE_COS
81		p1[kk] = (-cos(2 * 3.141592 * dtmf[kk] / 8000.0) * FSC);
82#endif
83	}
84
85	for (i = 0; i < 256; i++) {
86		key[i] = '?';
87		alaw[i] = alaw2linear(i) / (32768/FSC);
88	}
89
90	/* We encode the tones in 8 bits, translate those to symbol */
91	key[0x00] = '\0';
92
93	key[0x11] = '1'; key[0x12] = '4'; key[0x14] = '7'; key[0x18] = '*';
94	key[0x21] = '2'; key[0x22] = '5'; key[0x24] = '8'; key[0x28] = '0';
95	key[0x41] = '3'; key[0x42] = '6'; key[0x44] = '9'; key[0x48] = '#';
96	key[0x81] = 'A'; key[0x82] = 'B'; key[0x84] = 'C'; key[0x88] = 'D';
97
98	nn = 0;
99	ia = 0;
100	so = 0;
101	t = 0;
102	while ((i = getchar()) != EOF)
103	{
104		t++;
105
106		/* Convert to our format */
107		x = alaw[i];
108
109		/* Input amplitude */
110		if (x > 0)
111			ia += (x - ia) / 128;
112		else
113			ia += (-x - ia) / 128;
114
115		/* For each tone */
116		s = 0;
117		for (kk = 0; kk < 8; kk++) {
118
119			/* Turn the crank */
120			c = (P2 * (x - k[kk])) / FSC;
121			d = x + c;
122			f = (p1[kk] * (d - h[kk])) / FSC;
123			n = x - k[kk] - c;
124			k[kk] = h[kk] + f;
125			h[kk] = f + d;
126
127			/* Detect and Average */
128			if (n > 0)
129				y[kk] += (n - y[kk]) / 64;
130			else
131				y[kk] += (-n - y[kk]) / 64;
132
133			/* Threshold */
134			if (y[kk] > FSC/10 && y[kk] > ia)
135				s |= 1 << kk;
136		}
137
138		/* Hysteresis and noise supressor */
139		if (s != so) {
140/* printf("x %d %x -> %x\n",t,so, s); */
141			nn = 0;
142			so = s;
143		} else if (nn++ == 520 && key[s]) {
144			putchar(key[s]);
145/* printf(" %d %x\n",t,s); */
146		}
147	}
148	putchar('\n');
149	return (0);
150}
151