1 /* $Id: isdn_audio.c,v 1.1.2.2 2004/01/12 22:37:18 keil Exp $
3 * Linux ISDN subsystem, audio conversion and compression (linklevel).
5 * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
6 * DTMF code (c) 1996 by Christian Mock (cm@kukuruz.ping.at)
7 * Silence detection (c) 1998 by Armin Schindler (mac@gismo.telekom.de)
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
14 #include <linux/isdn.h>
15 #include <linux/slab.h>
16 #include "isdn_audio.h"
17 #include "isdn_common.h"
19 char *isdn_audio_revision = "$Revision: 1.1.2.2 $";
22 * Misc. lookup-tables.
25 /* ulaw -> signed 16-bit */
26 static short isdn_audio_ulaw_to_s16[] =
28 0x8284, 0x8684, 0x8a84, 0x8e84, 0x9284, 0x9684, 0x9a84, 0x9e84,
29 0xa284, 0xa684, 0xaa84, 0xae84, 0xb284, 0xb684, 0xba84, 0xbe84,
30 0xc184, 0xc384, 0xc584, 0xc784, 0xc984, 0xcb84, 0xcd84, 0xcf84,
31 0xd184, 0xd384, 0xd584, 0xd784, 0xd984, 0xdb84, 0xdd84, 0xdf84,
32 0xe104, 0xe204, 0xe304, 0xe404, 0xe504, 0xe604, 0xe704, 0xe804,
33 0xe904, 0xea04, 0xeb04, 0xec04, 0xed04, 0xee04, 0xef04, 0xf004,
34 0xf0c4, 0xf144, 0xf1c4, 0xf244, 0xf2c4, 0xf344, 0xf3c4, 0xf444,
35 0xf4c4, 0xf544, 0xf5c4, 0xf644, 0xf6c4, 0xf744, 0xf7c4, 0xf844,
36 0xf8a4, 0xf8e4, 0xf924, 0xf964, 0xf9a4, 0xf9e4, 0xfa24, 0xfa64,
37 0xfaa4, 0xfae4, 0xfb24, 0xfb64, 0xfba4, 0xfbe4, 0xfc24, 0xfc64,
38 0xfc94, 0xfcb4, 0xfcd4, 0xfcf4, 0xfd14, 0xfd34, 0xfd54, 0xfd74,
39 0xfd94, 0xfdb4, 0xfdd4, 0xfdf4, 0xfe14, 0xfe34, 0xfe54, 0xfe74,
40 0xfe8c, 0xfe9c, 0xfeac, 0xfebc, 0xfecc, 0xfedc, 0xfeec, 0xfefc,
41 0xff0c, 0xff1c, 0xff2c, 0xff3c, 0xff4c, 0xff5c, 0xff6c, 0xff7c,
42 0xff88, 0xff90, 0xff98, 0xffa0, 0xffa8, 0xffb0, 0xffb8, 0xffc0,
43 0xffc8, 0xffd0, 0xffd8, 0xffe0, 0xffe8, 0xfff0, 0xfff8, 0x0000,
44 0x7d7c, 0x797c, 0x757c, 0x717c, 0x6d7c, 0x697c, 0x657c, 0x617c,
45 0x5d7c, 0x597c, 0x557c, 0x517c, 0x4d7c, 0x497c, 0x457c, 0x417c,
46 0x3e7c, 0x3c7c, 0x3a7c, 0x387c, 0x367c, 0x347c, 0x327c, 0x307c,
47 0x2e7c, 0x2c7c, 0x2a7c, 0x287c, 0x267c, 0x247c, 0x227c, 0x207c,
48 0x1efc, 0x1dfc, 0x1cfc, 0x1bfc, 0x1afc, 0x19fc, 0x18fc, 0x17fc,
49 0x16fc, 0x15fc, 0x14fc, 0x13fc, 0x12fc, 0x11fc, 0x10fc, 0x0ffc,
50 0x0f3c, 0x0ebc, 0x0e3c, 0x0dbc, 0x0d3c, 0x0cbc, 0x0c3c, 0x0bbc,
51 0x0b3c, 0x0abc, 0x0a3c, 0x09bc, 0x093c, 0x08bc, 0x083c, 0x07bc,
52 0x075c, 0x071c, 0x06dc, 0x069c, 0x065c, 0x061c, 0x05dc, 0x059c,
53 0x055c, 0x051c, 0x04dc, 0x049c, 0x045c, 0x041c, 0x03dc, 0x039c,
54 0x036c, 0x034c, 0x032c, 0x030c, 0x02ec, 0x02cc, 0x02ac, 0x028c,
55 0x026c, 0x024c, 0x022c, 0x020c, 0x01ec, 0x01cc, 0x01ac, 0x018c,
56 0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
57 0x00f4, 0x00e4, 0x00d4, 0x00c4, 0x00b4, 0x00a4, 0x0094, 0x0084,
58 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
59 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000
62 /* alaw -> signed 16-bit */
63 static short isdn_audio_alaw_to_s16[] =
65 0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4,
66 0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74,
67 0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4,
68 0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64,
69 0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4,
70 0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4,
71 0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4,
72 0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4,
73 0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64,
74 0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34,
75 0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844,
76 0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24,
77 0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64,
78 0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4,
79 0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964,
80 0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4,
81 0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24,
82 0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94,
83 0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924,
84 0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94,
85 0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24,
86 0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14,
87 0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24,
88 0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14,
89 0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4,
90 0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54,
91 0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4,
92 0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64,
93 0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4,
94 0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4,
95 0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4,
96 0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4
100 static char isdn_audio_alaw_to_ulaw[] =
102 0xab, 0x2b, 0xe3, 0x63, 0x8b, 0x0b, 0xc9, 0x49,
103 0xba, 0x3a, 0xf6, 0x76, 0x9b, 0x1b, 0xd7, 0x57,
104 0xa3, 0x23, 0xdd, 0x5d, 0x83, 0x03, 0xc1, 0x41,
105 0xb2, 0x32, 0xeb, 0x6b, 0x93, 0x13, 0xcf, 0x4f,
106 0xaf, 0x2f, 0xe7, 0x67, 0x8f, 0x0f, 0xcd, 0x4d,
107 0xbe, 0x3e, 0xfe, 0x7e, 0x9f, 0x1f, 0xdb, 0x5b,
108 0xa7, 0x27, 0xdf, 0x5f, 0x87, 0x07, 0xc5, 0x45,
109 0xb6, 0x36, 0xef, 0x6f, 0x97, 0x17, 0xd3, 0x53,
110 0xa9, 0x29, 0xe1, 0x61, 0x89, 0x09, 0xc7, 0x47,
111 0xb8, 0x38, 0xf2, 0x72, 0x99, 0x19, 0xd5, 0x55,
112 0xa1, 0x21, 0xdc, 0x5c, 0x81, 0x01, 0xbf, 0x3f,
113 0xb0, 0x30, 0xe9, 0x69, 0x91, 0x11, 0xce, 0x4e,
114 0xad, 0x2d, 0xe5, 0x65, 0x8d, 0x0d, 0xcb, 0x4b,
115 0xbc, 0x3c, 0xfa, 0x7a, 0x9d, 0x1d, 0xd9, 0x59,
116 0xa5, 0x25, 0xde, 0x5e, 0x85, 0x05, 0xc3, 0x43,
117 0xb4, 0x34, 0xed, 0x6d, 0x95, 0x15, 0xd1, 0x51,
118 0xac, 0x2c, 0xe4, 0x64, 0x8c, 0x0c, 0xca, 0x4a,
119 0xbb, 0x3b, 0xf8, 0x78, 0x9c, 0x1c, 0xd8, 0x58,
120 0xa4, 0x24, 0xde, 0x5e, 0x84, 0x04, 0xc2, 0x42,
121 0xb3, 0x33, 0xec, 0x6c, 0x94, 0x14, 0xd0, 0x50,
122 0xb0, 0x30, 0xe8, 0x68, 0x90, 0x10, 0xce, 0x4e,
123 0xbf, 0x3f, 0xfe, 0x7e, 0xa0, 0x20, 0xdc, 0x5c,
124 0xa8, 0x28, 0xe0, 0x60, 0x88, 0x08, 0xc6, 0x46,
125 0xb7, 0x37, 0xf0, 0x70, 0x98, 0x18, 0xd4, 0x54,
126 0xaa, 0x2a, 0xe2, 0x62, 0x8a, 0x0a, 0xc8, 0x48,
127 0xb9, 0x39, 0xf4, 0x74, 0x9a, 0x1a, 0xd6, 0x56,
128 0xa2, 0x22, 0xdd, 0x5d, 0x82, 0x02, 0xc0, 0x40,
129 0xb1, 0x31, 0xea, 0x6a, 0x92, 0x12, 0xcf, 0x4f,
130 0xae, 0x2e, 0xe6, 0x66, 0x8e, 0x0e, 0xcc, 0x4c,
131 0xbd, 0x3d, 0xfc, 0x7c, 0x9e, 0x1e, 0xda, 0x5a,
132 0xa6, 0x26, 0xdf, 0x5f, 0x86, 0x06, 0xc4, 0x44,
133 0xb5, 0x35, 0xee, 0x6e, 0x96, 0x16, 0xd2, 0x52
137 static char isdn_audio_ulaw_to_alaw[] =
139 0xab, 0x55, 0xd5, 0x15, 0x95, 0x75, 0xf5, 0x35,
140 0xb5, 0x45, 0xc5, 0x05, 0x85, 0x65, 0xe5, 0x25,
141 0xa5, 0x5d, 0xdd, 0x1d, 0x9d, 0x7d, 0xfd, 0x3d,
142 0xbd, 0x4d, 0xcd, 0x0d, 0x8d, 0x6d, 0xed, 0x2d,
143 0xad, 0x51, 0xd1, 0x11, 0x91, 0x71, 0xf1, 0x31,
144 0xb1, 0x41, 0xc1, 0x01, 0x81, 0x61, 0xe1, 0x21,
145 0x59, 0xd9, 0x19, 0x99, 0x79, 0xf9, 0x39, 0xb9,
146 0x49, 0xc9, 0x09, 0x89, 0x69, 0xe9, 0x29, 0xa9,
147 0xd7, 0x17, 0x97, 0x77, 0xf7, 0x37, 0xb7, 0x47,
148 0xc7, 0x07, 0x87, 0x67, 0xe7, 0x27, 0xa7, 0xdf,
149 0x9f, 0x7f, 0xff, 0x3f, 0xbf, 0x4f, 0xcf, 0x0f,
150 0x8f, 0x6f, 0xef, 0x2f, 0x53, 0x13, 0x73, 0x33,
151 0xb3, 0x43, 0xc3, 0x03, 0x83, 0x63, 0xe3, 0x23,
152 0xa3, 0x5b, 0xdb, 0x1b, 0x9b, 0x7b, 0xfb, 0x3b,
153 0xbb, 0xbb, 0x4b, 0x4b, 0xcb, 0xcb, 0x0b, 0x0b,
154 0x8b, 0x8b, 0x6b, 0x6b, 0xeb, 0xeb, 0x2b, 0x2b,
155 0xab, 0x54, 0xd4, 0x14, 0x94, 0x74, 0xf4, 0x34,
156 0xb4, 0x44, 0xc4, 0x04, 0x84, 0x64, 0xe4, 0x24,
157 0xa4, 0x5c, 0xdc, 0x1c, 0x9c, 0x7c, 0xfc, 0x3c,
158 0xbc, 0x4c, 0xcc, 0x0c, 0x8c, 0x6c, 0xec, 0x2c,
159 0xac, 0x50, 0xd0, 0x10, 0x90, 0x70, 0xf0, 0x30,
160 0xb0, 0x40, 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x20,
161 0x58, 0xd8, 0x18, 0x98, 0x78, 0xf8, 0x38, 0xb8,
162 0x48, 0xc8, 0x08, 0x88, 0x68, 0xe8, 0x28, 0xa8,
163 0xd6, 0x16, 0x96, 0x76, 0xf6, 0x36, 0xb6, 0x46,
164 0xc6, 0x06, 0x86, 0x66, 0xe6, 0x26, 0xa6, 0xde,
165 0x9e, 0x7e, 0xfe, 0x3e, 0xbe, 0x4e, 0xce, 0x0e,
166 0x8e, 0x6e, 0xee, 0x2e, 0x52, 0x12, 0x72, 0x32,
167 0xb2, 0x42, 0xc2, 0x02, 0x82, 0x62, 0xe2, 0x22,
168 0xa2, 0x5a, 0xda, 0x1a, 0x9a, 0x7a, 0xfa, 0x3a,
169 0xba, 0xba, 0x4a, 0x4a, 0xca, 0xca, 0x0a, 0x0a,
170 0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a
173 #define NCOEFF 8 /* number of frequencies to be analyzed */
174 #define DTMF_TRESH 4000 /* above this is dtmf */
175 #define SILENCE_TRESH 200 /* below this is silence */
176 #define AMP_BITS 9 /* bits per sample, reduced to avoid overflow */
180 /* For DTMF recognition:
181 * 2 * cos(2 * PI * k / N) precalculated for all k
183 static int cos2pik[NCOEFF] =
185 55813, 53604, 51193, 48591, 38114, 33057, 25889, 18332
188 static char dtmf_matrix[4][4] =
190 {'1', '2', '3', 'A'},
191 {'4', '5', '6', 'B'},
192 {'7', '8', '9', 'C'},
197 isdn_audio_tlookup(const u_char *table, u_char *buff, unsigned long n)
200 unsigned long d0, d1, d2, d3;
201 __asm__ __volatile__(
207 : "=&b"(d0), "=&c"(d1), "=&D"(d2), "=&S"(d3)
208 : "0"((long) table), "1"(n), "2"((long) buff), "3"((long) buff)
212 *buff = table[*(unsigned char *)buff], buff++;
217 isdn_audio_ulaw2alaw(unsigned char *buff, unsigned long len)
219 isdn_audio_tlookup(isdn_audio_ulaw_to_alaw, buff, len);
223 isdn_audio_alaw2ulaw(unsigned char *buff, unsigned long len)
225 isdn_audio_tlookup(isdn_audio_alaw_to_ulaw, buff, len);
229 * linear <-> adpcm conversion stuff
230 * Most parts from the mgetty-package.
231 * (C) by Gert Doering and Klaus Weidner
232 * Used by permission of Gert Doering
236 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
238 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
242 isdn_audio_linear2ulaw(int sample)
244 static int exp_lut[256] =
246 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
247 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
248 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
249 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
250 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
251 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
252 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
253 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
254 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
255 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
256 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
257 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
258 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
259 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
260 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
261 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
266 unsigned char ulawbyte;
268 /* Get the sample into sign-magnitude. */
269 sign = (sample >> 8) & 0x80; /* set aside the sign */
271 sample = -sample; /* get magnitude */
273 sample = CLIP; /* clip the magnitude */
275 /* Convert from 16 bit linear to ulaw. */
276 sample = sample + BIAS;
277 exponent = exp_lut[(sample >> 7) & 0xFF];
278 mantissa = (sample >> (exponent + 3)) & 0x0F;
279 ulawbyte = ~(sign | (exponent << 4) | mantissa);
281 /* optional CCITT trap */
289 static int Mx[3][8] =
291 {0x3800, 0x5600, 0, 0, 0, 0, 0, 0},
292 {0x399a, 0x3a9f, 0x4d14, 0x6607, 0, 0, 0, 0},
293 {0x3556, 0x3556, 0x399A, 0x3A9F, 0x4200, 0x4D14, 0x6607, 0x6607},
296 static int bitmask[9] =
298 0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
302 isdn_audio_get_bits(adpcm_state * s, unsigned char **in, int *len)
304 while (s->nleft < s->nbits) {
307 s->word = (s->word << 8) | d;
310 s->nleft -= s->nbits;
311 return (s->word >> s->nleft) & bitmask[s->nbits];
315 isdn_audio_put_bits(int data, int nbits, adpcm_state * s,
316 unsigned char **out, int *len)
318 s->word = (s->word << nbits) | (data & bitmask[nbits]);
320 while (s->nleft >= 8) {
321 int d = (s->word >> (s->nleft - 8));
322 *(out[0]++) = d & 255;
329 isdn_audio_adpcm_init(adpcm_state * s, int nbits)
332 s = kmalloc(sizeof(adpcm_state), GFP_ATOMIC);
344 isdn_audio_dtmf_init(dtmf_state * s)
347 s = kmalloc(sizeof(dtmf_state), GFP_ATOMIC);
356 * Decompression of adpcm data to a/u-law
361 isdn_audio_adpcm2xlaw(adpcm_state * s, int fmt, unsigned char *in,
362 unsigned char *out, int len)
366 int nbits = s->nbits;
370 int e = isdn_audio_get_bits(s, &in, &len);
373 if (nbits == 4 && e == 0)
375 sign = (e >> (nbits - 1)) ? -1 : 1;
376 e &= bitmask[nbits - 1];
377 a += sign * ((e << 1) + 1) * d >> 1;
381 *out++ = isdn_audio_ulaw_to_alaw[
382 isdn_audio_linear2ulaw(a << 2)];
384 *out++ = isdn_audio_linear2ulaw(a << 2);
386 d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
396 isdn_audio_xlaw2adpcm(adpcm_state * s, int fmt, unsigned char *in,
397 unsigned char *out, int len)
401 int nbits = s->nbits;
406 nmax = 1 << (nbits - 1);
411 delta = (isdn_audio_alaw_to_s16[*in++] >> 2) - a;
413 delta = (isdn_audio_ulaw_to_s16[*in++] >> 2) - a;
418 while (--nmax && delta > d) {
422 if (nbits == 4 && ((e & 0x0f) == 0))
424 isdn_audio_put_bits(e, nbits, s, &out, &olen);
425 sign = (e >> (nbits - 1)) ? -1 : 1;
426 e &= bitmask[nbits - 1];
428 a += sign * ((e << 1) + 1) * d >> 1;
431 d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
441 * Goertzel algorithm.
442 * See http://ptolemy.eecs.berkeley.edu/~pino/Ptolemy/papers/96/dtmf_ict/
444 * Result is stored into an sk_buff and queued up for later
448 isdn_audio_goertzel(int *sample, modem_info * info)
458 skb = dev_alloc_skb(sizeof(int) * NCOEFF);
461 "isdn_audio: Could not alloc DTMF result for ttyI%d\n",
465 result = (int *) skb_put(skb, sizeof(int) * NCOEFF);
466 for (k = 0; k < NCOEFF; k++) {
468 for (n = 0; n < DTMF_NPOINTS; n++) {
469 sk = sample[n] + ((cos2pik[k] * sk1) >> 15) - sk2;
473 /* Avoid overflows */
476 /* compute |X(k)|**2 */
477 /* report overflows. This should not happen. */
478 /* Comment this out if desired */
479 if (sk < -32768 || sk > 32767)
481 "isdn_audio: dtmf goertzel overflow, sk=%d\n", sk);
482 if (sk2 < -32768 || sk2 > 32767)
484 "isdn_audio: dtmf goertzel overflow, sk2=%d\n", sk2);
486 ((sk * sk) >> AMP_BITS) -
487 ((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) +
488 ((sk2 * sk2) >> AMP_BITS);
490 skb_queue_tail(&info->dtmf_queue, skb);
491 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
495 isdn_audio_eval_dtmf(modem_info * info)
509 while ((skb = skb_dequeue(&info->dtmf_queue))) {
510 result = (int *) skb->data;
511 s = info->dtmf_state;
512 grp[LOGRP] = grp[HIGRP] = -1;
515 for (i = 0; i < NCOEFF; i++) {
516 if (result[i] > DTMF_TRESH) {
517 if (result[i] > thresh)
520 else if (result[i] < SILENCE_TRESH)
523 if (silence == NCOEFF)
527 thresh = thresh >> 4; /* touchtones must match within 12 dB */
528 for (i = 0; i < NCOEFF; i++) {
529 if (result[i] < thresh)
530 continue; /* ignore */
531 /* good level found. This is allowed only one time per group */
532 if (i < NCOEFF / 2) {
534 if (grp[LOGRP] >= 0) {
535 // Bad. Another tone found. */
543 if (grp[HIGRP] >= 0) { // Bad. Another tone found. */
548 grp[HIGRP] = i - NCOEFF/2;
551 if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {
552 what = dtmf_matrix[grp[LOGRP]][grp[HIGRP]];
553 if (s->last != ' ' && s->last != '.')
554 s->last = what; /* min. 1 non-DTMF between DTMF */
561 if ((what != s->last) && (what != ' ') && (what != '.')) {
562 printk(KERN_DEBUG "dtmf: tt='%c'\n", what);
567 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
568 ISDN_AUDIO_SKB_LOCK(skb) = 0;
569 di = info->isdn_driver;
570 ch = info->isdn_channel;
571 __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
572 dev->drv[di]->rcvcount[ch] += 2;
573 /* Schedule dequeuing */
574 if ((dev->modempoll) && (info->rcvsched))
575 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
576 wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
584 * Decode DTMF tones, queue result in separate sk_buf for
587 * s = pointer to state-struct.
588 * buf = input audio data
589 * len = size of audio data.
590 * fmt = audio data format (0 = ulaw, 1 = alaw)
593 isdn_audio_calc_dtmf(modem_info * info, unsigned char *buf, int len, int fmt)
595 dtmf_state *s = info->dtmf_state;
600 c = DTMF_NPOINTS - s->idx;
605 for (i = 0; i < c; i++) {
608 isdn_audio_alaw_to_s16[*buf++] >> (15 - AMP_BITS);
611 isdn_audio_ulaw_to_s16[*buf++] >> (15 - AMP_BITS);
613 if (s->idx == DTMF_NPOINTS) {
614 isdn_audio_goertzel(s->buf, info);
622 isdn_audio_silence_init(silence_state * s)
625 s = kmalloc(sizeof(silence_state), GFP_ATOMIC);
634 isdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt)
636 silence_state *s = info->silence_state;
640 if (!info->emu.vpar[1]) return;
642 for (i = 0; i < len; i++) {
644 c = isdn_audio_alaw_to_ulaw[*buf++];
651 if (c > (info->emu.vpar[1] * 4)) {
655 if (s->idx < 210000) s->idx++;
661 isdn_audio_put_dle_code(modem_info * info, u_char code)
668 skb = dev_alloc_skb(2);
671 "isdn_audio: Could not alloc skb for ttyI%d\n",
675 p = (char *) skb_put(skb, 2);
678 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
679 ISDN_AUDIO_SKB_LOCK(skb) = 0;
680 di = info->isdn_driver;
681 ch = info->isdn_channel;
682 __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
683 dev->drv[di]->rcvcount[ch] += 2;
684 /* Schedule dequeuing */
685 if ((dev->modempoll) && (info->rcvsched))
686 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
687 wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
691 isdn_audio_eval_silence(modem_info * info)
693 silence_state *s = info->silence_state;
698 if (s->idx > (info->emu.vpar[2] * 800)) {
700 if (!s->state) { /* silence from beginning of rec */
706 if ((what == 's') || (what == 'q')) {
707 printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
708 (what=='s') ? "silence":"quiet");
709 isdn_audio_put_dle_code(info, what);