File: /usr/src/linux/drivers/isdn/isdn_audio.c
1 /* $Id: isdn_audio.c,v 1.21.6.1 2001/08/17 12:34:25 kai Exp $
2
3 * Linux ISDN subsystem, audio conversion and compression (linklevel).
4 *
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)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25 #define __NO_VERSION__
26 #include <linux/module.h>
27 #include <linux/isdn.h>
28 #include "isdn_audio.h"
29 #include "isdn_common.h"
30
31 char *isdn_audio_revision = "$Revision: 1.21.6.1 $";
32
33 /*
34 * Misc. lookup-tables.
35 */
36
37 /* ulaw -> signed 16-bit */
38 static short isdn_audio_ulaw_to_s16[] =
39 {
40 0x8284, 0x8684, 0x8a84, 0x8e84, 0x9284, 0x9684, 0x9a84, 0x9e84,
41 0xa284, 0xa684, 0xaa84, 0xae84, 0xb284, 0xb684, 0xba84, 0xbe84,
42 0xc184, 0xc384, 0xc584, 0xc784, 0xc984, 0xcb84, 0xcd84, 0xcf84,
43 0xd184, 0xd384, 0xd584, 0xd784, 0xd984, 0xdb84, 0xdd84, 0xdf84,
44 0xe104, 0xe204, 0xe304, 0xe404, 0xe504, 0xe604, 0xe704, 0xe804,
45 0xe904, 0xea04, 0xeb04, 0xec04, 0xed04, 0xee04, 0xef04, 0xf004,
46 0xf0c4, 0xf144, 0xf1c4, 0xf244, 0xf2c4, 0xf344, 0xf3c4, 0xf444,
47 0xf4c4, 0xf544, 0xf5c4, 0xf644, 0xf6c4, 0xf744, 0xf7c4, 0xf844,
48 0xf8a4, 0xf8e4, 0xf924, 0xf964, 0xf9a4, 0xf9e4, 0xfa24, 0xfa64,
49 0xfaa4, 0xfae4, 0xfb24, 0xfb64, 0xfba4, 0xfbe4, 0xfc24, 0xfc64,
50 0xfc94, 0xfcb4, 0xfcd4, 0xfcf4, 0xfd14, 0xfd34, 0xfd54, 0xfd74,
51 0xfd94, 0xfdb4, 0xfdd4, 0xfdf4, 0xfe14, 0xfe34, 0xfe54, 0xfe74,
52 0xfe8c, 0xfe9c, 0xfeac, 0xfebc, 0xfecc, 0xfedc, 0xfeec, 0xfefc,
53 0xff0c, 0xff1c, 0xff2c, 0xff3c, 0xff4c, 0xff5c, 0xff6c, 0xff7c,
54 0xff88, 0xff90, 0xff98, 0xffa0, 0xffa8, 0xffb0, 0xffb8, 0xffc0,
55 0xffc8, 0xffd0, 0xffd8, 0xffe0, 0xffe8, 0xfff0, 0xfff8, 0x0000,
56 0x7d7c, 0x797c, 0x757c, 0x717c, 0x6d7c, 0x697c, 0x657c, 0x617c,
57 0x5d7c, 0x597c, 0x557c, 0x517c, 0x4d7c, 0x497c, 0x457c, 0x417c,
58 0x3e7c, 0x3c7c, 0x3a7c, 0x387c, 0x367c, 0x347c, 0x327c, 0x307c,
59 0x2e7c, 0x2c7c, 0x2a7c, 0x287c, 0x267c, 0x247c, 0x227c, 0x207c,
60 0x1efc, 0x1dfc, 0x1cfc, 0x1bfc, 0x1afc, 0x19fc, 0x18fc, 0x17fc,
61 0x16fc, 0x15fc, 0x14fc, 0x13fc, 0x12fc, 0x11fc, 0x10fc, 0x0ffc,
62 0x0f3c, 0x0ebc, 0x0e3c, 0x0dbc, 0x0d3c, 0x0cbc, 0x0c3c, 0x0bbc,
63 0x0b3c, 0x0abc, 0x0a3c, 0x09bc, 0x093c, 0x08bc, 0x083c, 0x07bc,
64 0x075c, 0x071c, 0x06dc, 0x069c, 0x065c, 0x061c, 0x05dc, 0x059c,
65 0x055c, 0x051c, 0x04dc, 0x049c, 0x045c, 0x041c, 0x03dc, 0x039c,
66 0x036c, 0x034c, 0x032c, 0x030c, 0x02ec, 0x02cc, 0x02ac, 0x028c,
67 0x026c, 0x024c, 0x022c, 0x020c, 0x01ec, 0x01cc, 0x01ac, 0x018c,
68 0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
69 0x00f4, 0x00e4, 0x00d4, 0x00c4, 0x00b4, 0x00a4, 0x0094, 0x0084,
70 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
71 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000
72 };
73
74 /* alaw -> signed 16-bit */
75 static short isdn_audio_alaw_to_s16[] =
76 {
77 0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4,
78 0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74,
79 0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4,
80 0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64,
81 0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4,
82 0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4,
83 0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4,
84 0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4,
85 0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64,
86 0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34,
87 0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844,
88 0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24,
89 0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64,
90 0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4,
91 0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964,
92 0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4,
93 0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24,
94 0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94,
95 0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924,
96 0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94,
97 0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24,
98 0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14,
99 0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24,
100 0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14,
101 0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4,
102 0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54,
103 0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4,
104 0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64,
105 0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4,
106 0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4,
107 0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4,
108 0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4
109 };
110
111 /* alaw -> ulaw */
112 static char isdn_audio_alaw_to_ulaw[] =
113 {
114 0xab, 0x2b, 0xe3, 0x63, 0x8b, 0x0b, 0xc9, 0x49,
115 0xba, 0x3a, 0xf6, 0x76, 0x9b, 0x1b, 0xd7, 0x57,
116 0xa3, 0x23, 0xdd, 0x5d, 0x83, 0x03, 0xc1, 0x41,
117 0xb2, 0x32, 0xeb, 0x6b, 0x93, 0x13, 0xcf, 0x4f,
118 0xaf, 0x2f, 0xe7, 0x67, 0x8f, 0x0f, 0xcd, 0x4d,
119 0xbe, 0x3e, 0xfe, 0x7e, 0x9f, 0x1f, 0xdb, 0x5b,
120 0xa7, 0x27, 0xdf, 0x5f, 0x87, 0x07, 0xc5, 0x45,
121 0xb6, 0x36, 0xef, 0x6f, 0x97, 0x17, 0xd3, 0x53,
122 0xa9, 0x29, 0xe1, 0x61, 0x89, 0x09, 0xc7, 0x47,
123 0xb8, 0x38, 0xf2, 0x72, 0x99, 0x19, 0xd5, 0x55,
124 0xa1, 0x21, 0xdc, 0x5c, 0x81, 0x01, 0xbf, 0x3f,
125 0xb0, 0x30, 0xe9, 0x69, 0x91, 0x11, 0xce, 0x4e,
126 0xad, 0x2d, 0xe5, 0x65, 0x8d, 0x0d, 0xcb, 0x4b,
127 0xbc, 0x3c, 0xfa, 0x7a, 0x9d, 0x1d, 0xd9, 0x59,
128 0xa5, 0x25, 0xde, 0x5e, 0x85, 0x05, 0xc3, 0x43,
129 0xb4, 0x34, 0xed, 0x6d, 0x95, 0x15, 0xd1, 0x51,
130 0xac, 0x2c, 0xe4, 0x64, 0x8c, 0x0c, 0xca, 0x4a,
131 0xbb, 0x3b, 0xf8, 0x78, 0x9c, 0x1c, 0xd8, 0x58,
132 0xa4, 0x24, 0xde, 0x5e, 0x84, 0x04, 0xc2, 0x42,
133 0xb3, 0x33, 0xec, 0x6c, 0x94, 0x14, 0xd0, 0x50,
134 0xb0, 0x30, 0xe8, 0x68, 0x90, 0x10, 0xce, 0x4e,
135 0xbf, 0x3f, 0xfe, 0x7e, 0xa0, 0x20, 0xdc, 0x5c,
136 0xa8, 0x28, 0xe0, 0x60, 0x88, 0x08, 0xc6, 0x46,
137 0xb7, 0x37, 0xf0, 0x70, 0x98, 0x18, 0xd4, 0x54,
138 0xaa, 0x2a, 0xe2, 0x62, 0x8a, 0x0a, 0xc8, 0x48,
139 0xb9, 0x39, 0xf4, 0x74, 0x9a, 0x1a, 0xd6, 0x56,
140 0xa2, 0x22, 0xdd, 0x5d, 0x82, 0x02, 0xc0, 0x40,
141 0xb1, 0x31, 0xea, 0x6a, 0x92, 0x12, 0xcf, 0x4f,
142 0xae, 0x2e, 0xe6, 0x66, 0x8e, 0x0e, 0xcc, 0x4c,
143 0xbd, 0x3d, 0xfc, 0x7c, 0x9e, 0x1e, 0xda, 0x5a,
144 0xa6, 0x26, 0xdf, 0x5f, 0x86, 0x06, 0xc4, 0x44,
145 0xb5, 0x35, 0xee, 0x6e, 0x96, 0x16, 0xd2, 0x52
146 };
147
148 /* ulaw -> alaw */
149 static char isdn_audio_ulaw_to_alaw[] =
150 {
151 0xab, 0x55, 0xd5, 0x15, 0x95, 0x75, 0xf5, 0x35,
152 0xb5, 0x45, 0xc5, 0x05, 0x85, 0x65, 0xe5, 0x25,
153 0xa5, 0x5d, 0xdd, 0x1d, 0x9d, 0x7d, 0xfd, 0x3d,
154 0xbd, 0x4d, 0xcd, 0x0d, 0x8d, 0x6d, 0xed, 0x2d,
155 0xad, 0x51, 0xd1, 0x11, 0x91, 0x71, 0xf1, 0x31,
156 0xb1, 0x41, 0xc1, 0x01, 0x81, 0x61, 0xe1, 0x21,
157 0x59, 0xd9, 0x19, 0x99, 0x79, 0xf9, 0x39, 0xb9,
158 0x49, 0xc9, 0x09, 0x89, 0x69, 0xe9, 0x29, 0xa9,
159 0xd7, 0x17, 0x97, 0x77, 0xf7, 0x37, 0xb7, 0x47,
160 0xc7, 0x07, 0x87, 0x67, 0xe7, 0x27, 0xa7, 0xdf,
161 0x9f, 0x7f, 0xff, 0x3f, 0xbf, 0x4f, 0xcf, 0x0f,
162 0x8f, 0x6f, 0xef, 0x2f, 0x53, 0x13, 0x73, 0x33,
163 0xb3, 0x43, 0xc3, 0x03, 0x83, 0x63, 0xe3, 0x23,
164 0xa3, 0x5b, 0xdb, 0x1b, 0x9b, 0x7b, 0xfb, 0x3b,
165 0xbb, 0xbb, 0x4b, 0x4b, 0xcb, 0xcb, 0x0b, 0x0b,
166 0x8b, 0x8b, 0x6b, 0x6b, 0xeb, 0xeb, 0x2b, 0x2b,
167 0xab, 0x54, 0xd4, 0x14, 0x94, 0x74, 0xf4, 0x34,
168 0xb4, 0x44, 0xc4, 0x04, 0x84, 0x64, 0xe4, 0x24,
169 0xa4, 0x5c, 0xdc, 0x1c, 0x9c, 0x7c, 0xfc, 0x3c,
170 0xbc, 0x4c, 0xcc, 0x0c, 0x8c, 0x6c, 0xec, 0x2c,
171 0xac, 0x50, 0xd0, 0x10, 0x90, 0x70, 0xf0, 0x30,
172 0xb0, 0x40, 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x20,
173 0x58, 0xd8, 0x18, 0x98, 0x78, 0xf8, 0x38, 0xb8,
174 0x48, 0xc8, 0x08, 0x88, 0x68, 0xe8, 0x28, 0xa8,
175 0xd6, 0x16, 0x96, 0x76, 0xf6, 0x36, 0xb6, 0x46,
176 0xc6, 0x06, 0x86, 0x66, 0xe6, 0x26, 0xa6, 0xde,
177 0x9e, 0x7e, 0xfe, 0x3e, 0xbe, 0x4e, 0xce, 0x0e,
178 0x8e, 0x6e, 0xee, 0x2e, 0x52, 0x12, 0x72, 0x32,
179 0xb2, 0x42, 0xc2, 0x02, 0x82, 0x62, 0xe2, 0x22,
180 0xa2, 0x5a, 0xda, 0x1a, 0x9a, 0x7a, 0xfa, 0x3a,
181 0xba, 0xba, 0x4a, 0x4a, 0xca, 0xca, 0x0a, 0x0a,
182 0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a
183 };
184
185 #define NCOEFF 16 /* number of frequencies to be analyzed */
186 #define DTMF_TRESH 25000 /* above this is dtmf */
187 #define SILENCE_TRESH 200 /* below this is silence */
188 #define H2_TRESH 20000 /* 2nd harmonic */
189 #define AMP_BITS 9 /* bits per sample, reduced to avoid overflow */
190 #define LOGRP 0
191 #define HIGRP 1
192
193 typedef struct {
194 int grp; /* low/high group */
195 int k; /* k */
196 int k2; /* k fuer 2. harmonic */
197 } dtmf_t;
198
199 /* For DTMF recognition:
200 * 2 * cos(2 * PI * k / N) precalculated for all k
201 */
202 static int cos2pik[NCOEFF] =
203 {
204 55812, 29528, 53603, 24032, 51193, 14443, 48590, 6517,
205 38113, -21204, 33057, -32186, 25889, -45081, 18332, -55279
206 };
207
208 static dtmf_t dtmf_tones[8] =
209 {
210 {LOGRP, 0, 1}, /* 697 Hz */
211 {LOGRP, 2, 3}, /* 770 Hz */
212 {LOGRP, 4, 5}, /* 852 Hz */
213 {LOGRP, 6, 7}, /* 941 Hz */
214 {HIGRP, 8, 9}, /* 1209 Hz */
215 {HIGRP, 10, 11}, /* 1336 Hz */
216 {HIGRP, 12, 13}, /* 1477 Hz */
217 {HIGRP, 14, 15} /* 1633 Hz */
218 };
219
220 static char dtmf_matrix[4][4] =
221 {
222 {'1', '2', '3', 'A'},
223 {'4', '5', '6', 'B'},
224 {'7', '8', '9', 'C'},
225 {'*', '0', '#', 'D'}
226 };
227
228 static inline void
229 isdn_audio_tlookup(const u_char *table, u_char *buff, unsigned long n)
230 {
231 #ifdef __i386__
232 unsigned long d0, d1, d2, d3;
233 __asm__ __volatile__(
234 "cld\n"
235 "1:\tlodsb\n\t"
236 "xlatb\n\t"
237 "stosb\n\t"
238 "loop 1b\n\t"
239 : "=&b"(d0), "=&c"(d1), "=&D"(d2), "=&S"(d3)
240 : "0"((long) table), "1"(n), "2"((long) buff), "3"((long) buff)
241 : "memory", "ax");
242 #else
243 while (n--)
244 *buff++ = table[*(unsigned char *)buff];
245 #endif
246 }
247
248 void
249 isdn_audio_ulaw2alaw(unsigned char *buff, unsigned long len)
250 {
251 isdn_audio_tlookup(isdn_audio_ulaw_to_alaw, buff, len);
252 }
253
254 void
255 isdn_audio_alaw2ulaw(unsigned char *buff, unsigned long len)
256 {
257 isdn_audio_tlookup(isdn_audio_alaw_to_ulaw, buff, len);
258 }
259
260 /*
261 * linear <-> adpcm conversion stuff
262 * Most parts from the mgetty-package.
263 * (C) by Gert Doering and Klaus Weidner
264 * Used by permission of Gert Doering
265 */
266
267
268 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
269 #undef ZEROTRAP
270 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
271 #define CLIP 32635
272
273 static unsigned char
274 isdn_audio_linear2ulaw(int sample)
275 {
276 static int exp_lut[256] =
277 {
278 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
279 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
280 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
281 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
282 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
283 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
284 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
285 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
286 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
287 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
288 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
289 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
290 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
291 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
292 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
293 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
294 };
295 int sign,
296 exponent,
297 mantissa;
298 unsigned char ulawbyte;
299
300 /* Get the sample into sign-magnitude. */
301 sign = (sample >> 8) & 0x80; /* set aside the sign */
302 if (sign != 0)
303 sample = -sample; /* get magnitude */
304 if (sample > CLIP)
305 sample = CLIP; /* clip the magnitude */
306
307 /* Convert from 16 bit linear to ulaw. */
308 sample = sample + BIAS;
309 exponent = exp_lut[(sample >> 7) & 0xFF];
310 mantissa = (sample >> (exponent + 3)) & 0x0F;
311 ulawbyte = ~(sign | (exponent << 4) | mantissa);
312 #ifdef ZEROTRAP
313 /* optional CCITT trap */
314 if (ulawbyte == 0)
315 ulawbyte = 0x02;
316 #endif
317 return (ulawbyte);
318 }
319
320
321 static int Mx[3][8] =
322 {
323 {0x3800, 0x5600, 0, 0, 0, 0, 0, 0},
324 {0x399a, 0x3a9f, 0x4d14, 0x6607, 0, 0, 0, 0},
325 {0x3556, 0x3556, 0x399A, 0x3A9F, 0x4200, 0x4D14, 0x6607, 0x6607},
326 };
327
328 static int bitmask[9] =
329 {
330 0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
331 };
332
333 static int
334 isdn_audio_get_bits(adpcm_state * s, unsigned char **in, int *len)
335 {
336 while (s->nleft < s->nbits) {
337 int d = *((*in)++);
338 (*len)--;
339 s->word = (s->word << 8) | d;
340 s->nleft += 8;
341 }
342 s->nleft -= s->nbits;
343 return (s->word >> s->nleft) & bitmask[s->nbits];
344 }
345
346 static void
347 isdn_audio_put_bits(int data, int nbits, adpcm_state * s,
348 unsigned char **out, int *len)
349 {
350 s->word = (s->word << nbits) | (data & bitmask[nbits]);
351 s->nleft += nbits;
352 while (s->nleft >= 8) {
353 int d = (s->word >> (s->nleft - 8));
354 *(out[0]++) = d & 255;
355 (*len)++;
356 s->nleft -= 8;
357 }
358 }
359
360 adpcm_state *
361 isdn_audio_adpcm_init(adpcm_state * s, int nbits)
362 {
363 if (!s)
364 s = (adpcm_state *) kmalloc(sizeof(adpcm_state), GFP_ATOMIC);
365 if (s) {
366 s->a = 0;
367 s->d = 5;
368 s->word = 0;
369 s->nleft = 0;
370 s->nbits = nbits;
371 }
372 return s;
373 }
374
375 dtmf_state *
376 isdn_audio_dtmf_init(dtmf_state * s)
377 {
378 if (!s)
379 s = (dtmf_state *) kmalloc(sizeof(dtmf_state), GFP_ATOMIC);
380 if (s) {
381 s->idx = 0;
382 s->last = ' ';
383 }
384 return s;
385 }
386
387 /*
388 * Decompression of adpcm data to a/u-law
389 *
390 */
391
392 int
393 isdn_audio_adpcm2xlaw(adpcm_state * s, int fmt, unsigned char *in,
394 unsigned char *out, int len)
395 {
396 int a = s->a;
397 int d = s->d;
398 int nbits = s->nbits;
399 int olen = 0;
400
401 while (len) {
402 int e = isdn_audio_get_bits(s, &in, &len);
403 int sign;
404
405 if (nbits == 4 && e == 0)
406 d = 4;
407 sign = (e >> (nbits - 1)) ? -1 : 1;
408 e &= bitmask[nbits - 1];
409 a += sign * ((e << 1) + 1) * d >> 1;
410 if (d & 1)
411 a++;
412 if (fmt)
413 *out++ = isdn_audio_ulaw_to_alaw[
414 isdn_audio_linear2ulaw(a << 2)];
415 else
416 *out++ = isdn_audio_linear2ulaw(a << 2);
417 olen++;
418 d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
419 if (d < 5)
420 d = 5;
421 }
422 s->a = a;
423 s->d = d;
424 return olen;
425 }
426
427 int
428 isdn_audio_2adpcm_flush(adpcm_state * s, unsigned char *out)
429 {
430 int olen = 0;
431
432 if (s->nleft)
433 isdn_audio_put_bits(0, 8 - s->nleft, s, &out, &olen);
434 return olen;
435 }
436
437 int
438 isdn_audio_xlaw2adpcm(adpcm_state * s, int fmt, unsigned char *in,
439 unsigned char *out, int len)
440 {
441 int a = s->a;
442 int d = s->d;
443 int nbits = s->nbits;
444 int olen = 0;
445
446 while (len--) {
447 int e = 0,
448 nmax = 1 << (nbits - 1);
449 int sign,
450 delta;
451
452 if (fmt)
453 delta = (isdn_audio_alaw_to_s16[*in++] >> 2) - a;
454 else
455 delta = (isdn_audio_ulaw_to_s16[*in++] >> 2) - a;
456 if (delta < 0) {
457 e = nmax;
458 delta = -delta;
459 }
460 while (--nmax && delta > d) {
461 delta -= d;
462 e++;
463 }
464 if (nbits == 4 && ((e & 0x0f) == 0))
465 e = 8;
466 isdn_audio_put_bits(e, nbits, s, &out, &olen);
467 sign = (e >> (nbits - 1)) ? -1 : 1;
468 e &= bitmask[nbits - 1];
469
470 a += sign * ((e << 1) + 1) * d >> 1;
471 if (d & 1)
472 a++;
473 d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
474 if (d < 5)
475 d = 5;
476 }
477 s->a = a;
478 s->d = d;
479 return olen;
480 }
481
482 /*
483 * Goertzel algorithm.
484 * See http://ptolemy.eecs.berkeley.edu/~pino/Ptolemy/papers/96/dtmf_ict/
485 * for more info.
486 * Result is stored into an sk_buff and queued up for later
487 * evaluation.
488 */
489 static void
490 isdn_audio_goertzel(int *sample, modem_info * info)
491 {
492 int sk,
493 sk1,
494 sk2;
495 int k,
496 n;
497 struct sk_buff *skb;
498 int *result;
499
500 skb = dev_alloc_skb(sizeof(int) * NCOEFF);
501 if (!skb) {
502 printk(KERN_WARNING
503 "isdn_audio: Could not alloc DTMF result for ttyI%d\n",
504 info->line);
505 return;
506 }
507 result = (int *) skb_put(skb, sizeof(int) * NCOEFF);
508 for (k = 0; k < NCOEFF; k++) {
509 sk = sk1 = sk2 = 0;
510 for (n = 0; n < DTMF_NPOINTS; n++) {
511 sk = sample[n] + ((cos2pik[k] * sk1) >> 15) - sk2;
512 sk2 = sk1;
513 sk1 = sk;
514 }
515 result[k] =
516 ((sk * sk) >> AMP_BITS) -
517 ((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) +
518 ((sk2 * sk2) >> AMP_BITS);
519 }
520 skb_queue_tail(&info->dtmf_queue, skb);
521 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
522 }
523
524 void
525 isdn_audio_eval_dtmf(modem_info * info)
526 {
527 struct sk_buff *skb;
528 int *result;
529 dtmf_state *s;
530 int silence;
531 int i;
532 int di;
533 int ch;
534 unsigned long flags;
535 int grp[2];
536 char what;
537 char *p;
538
539 while ((skb = skb_dequeue(&info->dtmf_queue))) {
540 result = (int *) skb->data;
541 s = info->dtmf_state;
542 grp[LOGRP] = grp[HIGRP] = -2;
543 silence = 0;
544 for (i = 0; i < 8; i++) {
545 if ((result[dtmf_tones[i].k] > DTMF_TRESH) &&
546 (result[dtmf_tones[i].k2] < H2_TRESH))
547 grp[dtmf_tones[i].grp] = (grp[dtmf_tones[i].grp] == -2) ? i : -1;
548 else if ((result[dtmf_tones[i].k] < SILENCE_TRESH) &&
549 (result[dtmf_tones[i].k2] < SILENCE_TRESH))
550 silence++;
551 }
552 if (silence == 8)
553 what = ' ';
554 else {
555 if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {
556 what = dtmf_matrix[grp[LOGRP]][grp[HIGRP] - 4];
557 if (s->last != ' ' && s->last != '.')
558 s->last = what; /* min. 1 non-DTMF between DTMF */
559 } else
560 what = '.';
561 }
562 if ((what != s->last) && (what != ' ') && (what != '.')) {
563 printk(KERN_DEBUG "dtmf: tt='%c'\n", what);
564 p = skb->data;
565 *p++ = 0x10;
566 *p = what;
567 skb_trim(skb, 2);
568 if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {
569 printk(KERN_WARNING
570 "isdn_audio: insufficient skb_headroom, dropping\n");
571 kfree_skb(skb);
572 return;
573 }
574 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
575 ISDN_AUDIO_SKB_LOCK(skb) = 0;
576 save_flags(flags);
577 cli();
578 di = info->isdn_driver;
579 ch = info->isdn_channel;
580 __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
581 dev->drv[di]->rcvcount[ch] += 2;
582 restore_flags(flags);
583 /* Schedule dequeuing */
584 if ((dev->modempoll) && (info->rcvsched))
585 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
586 wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
587 } else
588 kfree_skb(skb);
589 s->last = what;
590 }
591 }
592
593 /*
594 * Decode DTMF tones, queue result in separate sk_buf for
595 * later examination.
596 * Parameters:
597 * s = pointer to state-struct.
598 * buf = input audio data
599 * len = size of audio data.
600 * fmt = audio data format (0 = ulaw, 1 = alaw)
601 */
602 void
603 isdn_audio_calc_dtmf(modem_info * info, unsigned char *buf, int len, int fmt)
604 {
605 dtmf_state *s = info->dtmf_state;
606 int i;
607 int c;
608
609 while (len) {
610 c = DTMF_NPOINTS - s->idx;
611 if (c > len)
612 c = len;
613 if (c <= 0)
614 break;
615 for (i = 0; i < c; i++) {
616 if (fmt)
617 s->buf[s->idx++] =
618 isdn_audio_alaw_to_s16[*buf++] >> (15 - AMP_BITS);
619 else
620 s->buf[s->idx++] =
621 isdn_audio_ulaw_to_s16[*buf++] >> (15 - AMP_BITS);
622 }
623 if (s->idx == DTMF_NPOINTS) {
624 isdn_audio_goertzel(s->buf, info);
625 s->idx = 0;
626 }
627 len -= c;
628 }
629 }
630
631 silence_state *
632 isdn_audio_silence_init(silence_state * s)
633 {
634 if (!s)
635 s = (silence_state *) kmalloc(sizeof(silence_state), GFP_ATOMIC);
636 if (s) {
637 s->idx = 0;
638 s->state = 0;
639 }
640 return s;
641 }
642
643 void
644 isdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt)
645 {
646 silence_state *s = info->silence_state;
647 int i;
648 signed char c;
649
650 if (!info->emu.vpar[1]) return;
651
652 for (i = 0; i < len; i++) {
653 if (fmt)
654 c = isdn_audio_alaw_to_ulaw[*buf++];
655 else
656 c = *buf++;
657
658 if (c > 0) c -= 128;
659 c = abs(c);
660
661 if (c > (info->emu.vpar[1] * 4)) {
662 s->idx = 0;
663 s->state = 1;
664 } else {
665 if (s->idx < 210000) s->idx++;
666 }
667 }
668 }
669
670 void
671 isdn_audio_put_dle_code(modem_info * info, u_char code)
672 {
673 struct sk_buff *skb;
674 unsigned long flags;
675 int di;
676 int ch;
677 char *p;
678
679 skb = dev_alloc_skb(2);
680 if (!skb) {
681 printk(KERN_WARNING
682 "isdn_audio: Could not alloc skb for ttyI%d\n",
683 info->line);
684 return;
685 }
686 p = (char *) skb_put(skb, 2);
687 p[0] = 0x10;
688 p[1] = code;
689 if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {
690 printk(KERN_WARNING
691 "isdn_audio: insufficient skb_headroom, dropping\n");
692 kfree_skb(skb);
693 return;
694 }
695 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
696 ISDN_AUDIO_SKB_LOCK(skb) = 0;
697 save_flags(flags);
698 cli();
699 di = info->isdn_driver;
700 ch = info->isdn_channel;
701 __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
702 dev->drv[di]->rcvcount[ch] += 2;
703 restore_flags(flags);
704 /* Schedule dequeuing */
705 if ((dev->modempoll) && (info->rcvsched))
706 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
707 wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
708 }
709
710 void
711 isdn_audio_eval_silence(modem_info * info)
712 {
713 silence_state *s = info->silence_state;
714 char what;
715
716 what = ' ';
717
718 if (s->idx > (info->emu.vpar[2] * 800)) {
719 s->idx = 0;
720 if (!s->state) { /* silence from beginning of rec */
721 what = 's';
722 } else {
723 what = 'q';
724 }
725 }
726 if ((what == 's') || (what == 'q')) {
727 printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
728 (what=='s') ? "silence":"quiet");
729 isdn_audio_put_dle_code(info, what);
730 }
731 }
732