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 "isdn_audio.h"
16 #include "isdn_common.h"
18 char *isdn_audio_revision = "$Revision: 1.1.2.2 $";
21 * Misc. lookup-tables.
24 /* ulaw -> signed 16-bit */
25 static short isdn_audio_ulaw_to_s16[] =
27 0x8284, 0x8684, 0x8a84, 0x8e84, 0x9284, 0x9684, 0x9a84, 0x9e84,
28 0xa284, 0xa684, 0xaa84, 0xae84, 0xb284, 0xb684, 0xba84, 0xbe84,
29 0xc184, 0xc384, 0xc584, 0xc784, 0xc984, 0xcb84, 0xcd84, 0xcf84,
30 0xd184, 0xd384, 0xd584, 0xd784, 0xd984, 0xdb84, 0xdd84, 0xdf84,
31 0xe104, 0xe204, 0xe304, 0xe404, 0xe504, 0xe604, 0xe704, 0xe804,
32 0xe904, 0xea04, 0xeb04, 0xec04, 0xed04, 0xee04, 0xef04, 0xf004,
33 0xf0c4, 0xf144, 0xf1c4, 0xf244, 0xf2c4, 0xf344, 0xf3c4, 0xf444,
34 0xf4c4, 0xf544, 0xf5c4, 0xf644, 0xf6c4, 0xf744, 0xf7c4, 0xf844,
35 0xf8a4, 0xf8e4, 0xf924, 0xf964, 0xf9a4, 0xf9e4, 0xfa24, 0xfa64,
36 0xfaa4, 0xfae4, 0xfb24, 0xfb64, 0xfba4, 0xfbe4, 0xfc24, 0xfc64,
37 0xfc94, 0xfcb4, 0xfcd4, 0xfcf4, 0xfd14, 0xfd34, 0xfd54, 0xfd74,
38 0xfd94, 0xfdb4, 0xfdd4, 0xfdf4, 0xfe14, 0xfe34, 0xfe54, 0xfe74,
39 0xfe8c, 0xfe9c, 0xfeac, 0xfebc, 0xfecc, 0xfedc, 0xfeec, 0xfefc,
40 0xff0c, 0xff1c, 0xff2c, 0xff3c, 0xff4c, 0xff5c, 0xff6c, 0xff7c,
41 0xff88, 0xff90, 0xff98, 0xffa0, 0xffa8, 0xffb0, 0xffb8, 0xffc0,
42 0xffc8, 0xffd0, 0xffd8, 0xffe0, 0xffe8, 0xfff0, 0xfff8, 0x0000,
43 0x7d7c, 0x797c, 0x757c, 0x717c, 0x6d7c, 0x697c, 0x657c, 0x617c,
44 0x5d7c, 0x597c, 0x557c, 0x517c, 0x4d7c, 0x497c, 0x457c, 0x417c,
45 0x3e7c, 0x3c7c, 0x3a7c, 0x387c, 0x367c, 0x347c, 0x327c, 0x307c,
46 0x2e7c, 0x2c7c, 0x2a7c, 0x287c, 0x267c, 0x247c, 0x227c, 0x207c,
47 0x1efc, 0x1dfc, 0x1cfc, 0x1bfc, 0x1afc, 0x19fc, 0x18fc, 0x17fc,
48 0x16fc, 0x15fc, 0x14fc, 0x13fc, 0x12fc, 0x11fc, 0x10fc, 0x0ffc,
49 0x0f3c, 0x0ebc, 0x0e3c, 0x0dbc, 0x0d3c, 0x0cbc, 0x0c3c, 0x0bbc,
50 0x0b3c, 0x0abc, 0x0a3c, 0x09bc, 0x093c, 0x08bc, 0x083c, 0x07bc,
51 0x075c, 0x071c, 0x06dc, 0x069c, 0x065c, 0x061c, 0x05dc, 0x059c,
52 0x055c, 0x051c, 0x04dc, 0x049c, 0x045c, 0x041c, 0x03dc, 0x039c,
53 0x036c, 0x034c, 0x032c, 0x030c, 0x02ec, 0x02cc, 0x02ac, 0x028c,
54 0x026c, 0x024c, 0x022c, 0x020c, 0x01ec, 0x01cc, 0x01ac, 0x018c,
55 0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
56 0x00f4, 0x00e4, 0x00d4, 0x00c4, 0x00b4, 0x00a4, 0x0094, 0x0084,
57 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
58 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000
61 /* alaw -> signed 16-bit */
62 static short isdn_audio_alaw_to_s16[] =
64 0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4,
65 0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74,
66 0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4,
67 0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64,
68 0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4,
69 0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4,
70 0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4,
71 0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4,
72 0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64,
73 0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34,
74 0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844,
75 0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24,
76 0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64,
77 0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4,
78 0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964,
79 0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4,
80 0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24,
81 0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94,
82 0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924,
83 0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94,
84 0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24,
85 0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14,
86 0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24,
87 0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14,
88 0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4,
89 0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54,
90 0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4,
91 0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64,
92 0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4,
93 0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4,
94 0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4,
95 0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4
99 static char isdn_audio_alaw_to_ulaw[] =
101 0xab, 0x2b, 0xe3, 0x63, 0x8b, 0x0b, 0xc9, 0x49,
102 0xba, 0x3a, 0xf6, 0x76, 0x9b, 0x1b, 0xd7, 0x57,
103 0xa3, 0x23, 0xdd, 0x5d, 0x83, 0x03, 0xc1, 0x41,
104 0xb2, 0x32, 0xeb, 0x6b, 0x93, 0x13, 0xcf, 0x4f,
105 0xaf, 0x2f, 0xe7, 0x67, 0x8f, 0x0f, 0xcd, 0x4d,
106 0xbe, 0x3e, 0xfe, 0x7e, 0x9f, 0x1f, 0xdb, 0x5b,
107 0xa7, 0x27, 0xdf, 0x5f, 0x87, 0x07, 0xc5, 0x45,
108 0xb6, 0x36, 0xef, 0x6f, 0x97, 0x17, 0xd3, 0x53,
109 0xa9, 0x29, 0xe1, 0x61, 0x89, 0x09, 0xc7, 0x47,
110 0xb8, 0x38, 0xf2, 0x72, 0x99, 0x19, 0xd5, 0x55,
111 0xa1, 0x21, 0xdc, 0x5c, 0x81, 0x01, 0xbf, 0x3f,
112 0xb0, 0x30, 0xe9, 0x69, 0x91, 0x11, 0xce, 0x4e,
113 0xad, 0x2d, 0xe5, 0x65, 0x8d, 0x0d, 0xcb, 0x4b,
114 0xbc, 0x3c, 0xfa, 0x7a, 0x9d, 0x1d, 0xd9, 0x59,
115 0xa5, 0x25, 0xde, 0x5e, 0x85, 0x05, 0xc3, 0x43,
116 0xb4, 0x34, 0xed, 0x6d, 0x95, 0x15, 0xd1, 0x51,
117 0xac, 0x2c, 0xe4, 0x64, 0x8c, 0x0c, 0xca, 0x4a,
118 0xbb, 0x3b, 0xf8, 0x78, 0x9c, 0x1c, 0xd8, 0x58,
119 0xa4, 0x24, 0xde, 0x5e, 0x84, 0x04, 0xc2, 0x42,
120 0xb3, 0x33, 0xec, 0x6c, 0x94, 0x14, 0xd0, 0x50,
121 0xb0, 0x30, 0xe8, 0x68, 0x90, 0x10, 0xce, 0x4e,
122 0xbf, 0x3f, 0xfe, 0x7e, 0xa0, 0x20, 0xdc, 0x5c,
123 0xa8, 0x28, 0xe0, 0x60, 0x88, 0x08, 0xc6, 0x46,
124 0xb7, 0x37, 0xf0, 0x70, 0x98, 0x18, 0xd4, 0x54,
125 0xaa, 0x2a, 0xe2, 0x62, 0x8a, 0x0a, 0xc8, 0x48,
126 0xb9, 0x39, 0xf4, 0x74, 0x9a, 0x1a, 0xd6, 0x56,
127 0xa2, 0x22, 0xdd, 0x5d, 0x82, 0x02, 0xc0, 0x40,
128 0xb1, 0x31, 0xea, 0x6a, 0x92, 0x12, 0xcf, 0x4f,
129 0xae, 0x2e, 0xe6, 0x66, 0x8e, 0x0e, 0xcc, 0x4c,
130 0xbd, 0x3d, 0xfc, 0x7c, 0x9e, 0x1e, 0xda, 0x5a,
131 0xa6, 0x26, 0xdf, 0x5f, 0x86, 0x06, 0xc4, 0x44,
132 0xb5, 0x35, 0xee, 0x6e, 0x96, 0x16, 0xd2, 0x52
136 static char isdn_audio_ulaw_to_alaw[] =
138 0xab, 0x55, 0xd5, 0x15, 0x95, 0x75, 0xf5, 0x35,
139 0xb5, 0x45, 0xc5, 0x05, 0x85, 0x65, 0xe5, 0x25,
140 0xa5, 0x5d, 0xdd, 0x1d, 0x9d, 0x7d, 0xfd, 0x3d,
141 0xbd, 0x4d, 0xcd, 0x0d, 0x8d, 0x6d, 0xed, 0x2d,
142 0xad, 0x51, 0xd1, 0x11, 0x91, 0x71, 0xf1, 0x31,
143 0xb1, 0x41, 0xc1, 0x01, 0x81, 0x61, 0xe1, 0x21,
144 0x59, 0xd9, 0x19, 0x99, 0x79, 0xf9, 0x39, 0xb9,
145 0x49, 0xc9, 0x09, 0x89, 0x69, 0xe9, 0x29, 0xa9,
146 0xd7, 0x17, 0x97, 0x77, 0xf7, 0x37, 0xb7, 0x47,
147 0xc7, 0x07, 0x87, 0x67, 0xe7, 0x27, 0xa7, 0xdf,
148 0x9f, 0x7f, 0xff, 0x3f, 0xbf, 0x4f, 0xcf, 0x0f,
149 0x8f, 0x6f, 0xef, 0x2f, 0x53, 0x13, 0x73, 0x33,
150 0xb3, 0x43, 0xc3, 0x03, 0x83, 0x63, 0xe3, 0x23,
151 0xa3, 0x5b, 0xdb, 0x1b, 0x9b, 0x7b, 0xfb, 0x3b,
152 0xbb, 0xbb, 0x4b, 0x4b, 0xcb, 0xcb, 0x0b, 0x0b,
153 0x8b, 0x8b, 0x6b, 0x6b, 0xeb, 0xeb, 0x2b, 0x2b,
154 0xab, 0x54, 0xd4, 0x14, 0x94, 0x74, 0xf4, 0x34,
155 0xb4, 0x44, 0xc4, 0x04, 0x84, 0x64, 0xe4, 0x24,
156 0xa4, 0x5c, 0xdc, 0x1c, 0x9c, 0x7c, 0xfc, 0x3c,
157 0xbc, 0x4c, 0xcc, 0x0c, 0x8c, 0x6c, 0xec, 0x2c,
158 0xac, 0x50, 0xd0, 0x10, 0x90, 0x70, 0xf0, 0x30,
159 0xb0, 0x40, 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x20,
160 0x58, 0xd8, 0x18, 0x98, 0x78, 0xf8, 0x38, 0xb8,
161 0x48, 0xc8, 0x08, 0x88, 0x68, 0xe8, 0x28, 0xa8,
162 0xd6, 0x16, 0x96, 0x76, 0xf6, 0x36, 0xb6, 0x46,
163 0xc6, 0x06, 0x86, 0x66, 0xe6, 0x26, 0xa6, 0xde,
164 0x9e, 0x7e, 0xfe, 0x3e, 0xbe, 0x4e, 0xce, 0x0e,
165 0x8e, 0x6e, 0xee, 0x2e, 0x52, 0x12, 0x72, 0x32,
166 0xb2, 0x42, 0xc2, 0x02, 0x82, 0x62, 0xe2, 0x22,
167 0xa2, 0x5a, 0xda, 0x1a, 0x9a, 0x7a, 0xfa, 0x3a,
168 0xba, 0xba, 0x4a, 0x4a, 0xca, 0xca, 0x0a, 0x0a,
169 0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a
172 #define NCOEFF 8 /* number of frequencies to be analyzed */
173 #define DTMF_TRESH 4000 /* above this is dtmf */
174 #define SILENCE_TRESH 200 /* below this is silence */
175 #define AMP_BITS 9 /* bits per sample, reduced to avoid overflow */
179 /* For DTMF recognition:
180 * 2 * cos(2 * PI * k / N) precalculated for all k
182 static int cos2pik[NCOEFF] =
184 55813, 53604, 51193, 48591, 38114, 33057, 25889, 18332
187 static char dtmf_matrix[4][4] =
189 {'1', '2', '3', 'A'},
190 {'4', '5', '6', 'B'},
191 {'7', '8', '9', 'C'},
196 isdn_audio_tlookup(const u_char *table, u_char *buff, unsigned long n)
199 unsigned long d0, d1, d2, d3;
200 __asm__ __volatile__(
206 : "=&b"(d0), "=&c"(d1), "=&D"(d2), "=&S"(d3)
207 : "0"((long) table), "1"(n), "2"((long) buff), "3"((long) buff)
211 *buff = table[*(unsigned char *)buff], buff++;
216 isdn_audio_ulaw2alaw(unsigned char *buff, unsigned long len)
218 isdn_audio_tlookup(isdn_audio_ulaw_to_alaw, buff, len);
222 isdn_audio_alaw2ulaw(unsigned char *buff, unsigned long len)
224 isdn_audio_tlookup(isdn_audio_alaw_to_ulaw, buff, len);
228 * linear <-> adpcm conversion stuff
229 * Most parts from the mgetty-package.
230 * (C) by Gert Doering and Klaus Weidner
231 * Used by permission of Gert Doering
235 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
237 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
241 isdn_audio_linear2ulaw(int sample)
243 static int exp_lut[256] =
245 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
246 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
247 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
248 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
249 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
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 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
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
265 unsigned char ulawbyte;
267 /* Get the sample into sign-magnitude. */
268 sign = (sample >> 8) & 0x80; /* set aside the sign */
270 sample = -sample; /* get magnitude */
272 sample = CLIP; /* clip the magnitude */
274 /* Convert from 16 bit linear to ulaw. */
275 sample = sample + BIAS;
276 exponent = exp_lut[(sample >> 7) & 0xFF];
277 mantissa = (sample >> (exponent + 3)) & 0x0F;
278 ulawbyte = ~(sign | (exponent << 4) | mantissa);
280 /* optional CCITT trap */
288 static int Mx[3][8] =
290 {0x3800, 0x5600, 0, 0, 0, 0, 0, 0},
291 {0x399a, 0x3a9f, 0x4d14, 0x6607, 0, 0, 0, 0},
292 {0x3556, 0x3556, 0x399A, 0x3A9F, 0x4200, 0x4D14, 0x6607, 0x6607},
295 static int bitmask[9] =
297 0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
301 isdn_audio_get_bits(adpcm_state * s, unsigned char **in, int *len)
303 while (s->nleft < s->nbits) {
306 s->word = (s->word << 8) | d;
309 s->nleft -= s->nbits;
310 return (s->word >> s->nleft) & bitmask[s->nbits];
314 isdn_audio_put_bits(int data, int nbits, adpcm_state * s,
315 unsigned char **out, int *len)
317 s->word = (s->word << nbits) | (data & bitmask[nbits]);
319 while (s->nleft >= 8) {
320 int d = (s->word >> (s->nleft - 8));
321 *(out[0]++) = d & 255;
328 isdn_audio_adpcm_init(adpcm_state * s, int nbits)
331 s = kmalloc(sizeof(adpcm_state), GFP_ATOMIC);
343 isdn_audio_dtmf_init(dtmf_state * s)
346 s = kmalloc(sizeof(dtmf_state), GFP_ATOMIC);
355 * Decompression of adpcm data to a/u-law
360 isdn_audio_adpcm2xlaw(adpcm_state * s, int fmt, unsigned char *in,
361 unsigned char *out, int len)
365 int nbits = s->nbits;
369 int e = isdn_audio_get_bits(s, &in, &len);
372 if (nbits == 4 && e == 0)
374 sign = (e >> (nbits - 1)) ? -1 : 1;
375 e &= bitmask[nbits - 1];
376 a += sign * ((e << 1) + 1) * d >> 1;
380 *out++ = isdn_audio_ulaw_to_alaw[
381 isdn_audio_linear2ulaw(a << 2)];
383 *out++ = isdn_audio_linear2ulaw(a << 2);
385 d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
395 isdn_audio_xlaw2adpcm(adpcm_state * s, int fmt, unsigned char *in,
396 unsigned char *out, int len)
400 int nbits = s->nbits;
405 nmax = 1 << (nbits - 1);
410 delta = (isdn_audio_alaw_to_s16[*in++] >> 2) - a;
412 delta = (isdn_audio_ulaw_to_s16[*in++] >> 2) - a;
417 while (--nmax && delta > d) {
421 if (nbits == 4 && ((e & 0x0f) == 0))
423 isdn_audio_put_bits(e, nbits, s, &out, &olen);
424 sign = (e >> (nbits - 1)) ? -1 : 1;
425 e &= bitmask[nbits - 1];
427 a += sign * ((e << 1) + 1) * d >> 1;
430 d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
440 * Goertzel algorithm.
441 * See http://ptolemy.eecs.berkeley.edu/~pino/Ptolemy/papers/96/dtmf_ict/
443 * Result is stored into an sk_buff and queued up for later
447 isdn_audio_goertzel(int *sample, modem_info * info)
457 skb = dev_alloc_skb(sizeof(int) * NCOEFF);
460 "isdn_audio: Could not alloc DTMF result for ttyI%d\n",
464 result = (int *) skb_put(skb, sizeof(int) * NCOEFF);
465 for (k = 0; k < NCOEFF; k++) {
467 for (n = 0; n < DTMF_NPOINTS; n++) {
468 sk = sample[n] + ((cos2pik[k] * sk1) >> 15) - sk2;
472 /* Avoid overflows */
475 /* compute |X(k)|**2 */
476 /* report overflows. This should not happen. */
477 /* Comment this out if desired */
478 if (sk < -32768 || sk > 32767)
480 "isdn_audio: dtmf goertzel overflow, sk=%d\n", sk);
481 if (sk2 < -32768 || sk2 > 32767)
483 "isdn_audio: dtmf goertzel overflow, sk2=%d\n", sk2);
485 ((sk * sk) >> AMP_BITS) -
486 ((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) +
487 ((sk2 * sk2) >> AMP_BITS);
489 skb_queue_tail(&info->dtmf_queue, skb);
490 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
494 isdn_audio_eval_dtmf(modem_info * info)
508 while ((skb = skb_dequeue(&info->dtmf_queue))) {
509 result = (int *) skb->data;
510 s = info->dtmf_state;
511 grp[LOGRP] = grp[HIGRP] = -1;
514 for (i = 0; i < NCOEFF; i++) {
515 if (result[i] > DTMF_TRESH) {
516 if (result[i] > thresh)
519 else if (result[i] < SILENCE_TRESH)
522 if (silence == NCOEFF)
526 thresh = thresh >> 4; /* touchtones must match within 12 dB */
527 for (i = 0; i < NCOEFF; i++) {
528 if (result[i] < thresh)
529 continue; /* ignore */
530 /* good level found. This is allowed only one time per group */
531 if (i < NCOEFF / 2) {
533 if (grp[LOGRP] >= 0) {
534 // Bad. Another tone found. */
542 if (grp[HIGRP] >= 0) { // Bad. Another tone found. */
547 grp[HIGRP] = i - NCOEFF/2;
550 if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {
551 what = dtmf_matrix[grp[LOGRP]][grp[HIGRP]];
552 if (s->last != ' ' && s->last != '.')
553 s->last = what; /* min. 1 non-DTMF between DTMF */
560 if ((what != s->last) && (what != ' ') && (what != '.')) {
561 printk(KERN_DEBUG "dtmf: tt='%c'\n", what);
566 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
567 ISDN_AUDIO_SKB_LOCK(skb) = 0;
568 di = info->isdn_driver;
569 ch = info->isdn_channel;
570 __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
571 dev->drv[di]->rcvcount[ch] += 2;
572 /* Schedule dequeuing */
573 if ((dev->modempoll) && (info->rcvsched))
574 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
575 wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
583 * Decode DTMF tones, queue result in separate sk_buf for
586 * s = pointer to state-struct.
587 * buf = input audio data
588 * len = size of audio data.
589 * fmt = audio data format (0 = ulaw, 1 = alaw)
592 isdn_audio_calc_dtmf(modem_info * info, unsigned char *buf, int len, int fmt)
594 dtmf_state *s = info->dtmf_state;
599 c = DTMF_NPOINTS - s->idx;
604 for (i = 0; i < c; i++) {
607 isdn_audio_alaw_to_s16[*buf++] >> (15 - AMP_BITS);
610 isdn_audio_ulaw_to_s16[*buf++] >> (15 - AMP_BITS);
612 if (s->idx == DTMF_NPOINTS) {
613 isdn_audio_goertzel(s->buf, info);
621 isdn_audio_silence_init(silence_state * s)
624 s = kmalloc(sizeof(silence_state), GFP_ATOMIC);
633 isdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt)
635 silence_state *s = info->silence_state;
639 if (!info->emu.vpar[1]) return;
641 for (i = 0; i < len; i++) {
643 c = isdn_audio_alaw_to_ulaw[*buf++];
650 if (c > (info->emu.vpar[1] * 4)) {
654 if (s->idx < 210000) s->idx++;
660 isdn_audio_put_dle_code(modem_info * info, u_char code)
667 skb = dev_alloc_skb(2);
670 "isdn_audio: Could not alloc skb for ttyI%d\n",
674 p = (char *) skb_put(skb, 2);
677 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
678 ISDN_AUDIO_SKB_LOCK(skb) = 0;
679 di = info->isdn_driver;
680 ch = info->isdn_channel;
681 __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
682 dev->drv[di]->rcvcount[ch] += 2;
683 /* Schedule dequeuing */
684 if ((dev->modempoll) && (info->rcvsched))
685 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
686 wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
690 isdn_audio_eval_silence(modem_info * info)
692 silence_state *s = info->silence_state;
697 if (s->idx > (info->emu.vpar[2] * 800)) {
699 if (!s->state) { /* silence from beginning of rec */
705 if ((what == 's') || (what == 'q')) {
706 printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
707 (what=='s') ? "silence":"quiet");
708 isdn_audio_put_dle_code(info, what);