Linux-2.4.0-test2
[davej-history.git] / drivers / isdn / isdn_audio.c
blob9bc7a08b04ea82dbb4274a85b031bca8a97d18f7
1 /* $Id: isdn_audio.c,v 1.17 1999/08/17 11:10:52 paul 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 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.
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.
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.
23 * $Log: isdn_audio.c,v $
24 * Revision 1.17 1999/08/17 11:10:52 paul
25 * don't try to use x86 assembler on non-x86!
27 * Revision 1.16 1999/08/06 12:47:35 calle
28 * Using __GNUC__ == 2 && __GNUC_MINOR__ < 95 how to define
29 * ISDN_AUDIO_OPTIMIZE_ON_X386_WITH_ASM_IF_GCC_ALLOW_IT
31 * Revision 1.15 1999/08/06 12:02:52 calle
32 * egcs 2.95 complain about invalid asm statement:
33 * "fixed or forbidden register 2 (cx) was spilled for class CREG."
34 * Using ISDN_AUDIO_OPTIMIZE_ON_X386_WITH_ASM_IF_GCC_ALLOW_IT and not
35 * define it at the moment.
37 * Revision 1.14 1999/07/11 17:14:06 armin
38 * Added new layer 2 and 3 protocols for Fax and DSP functions.
39 * Moved "Add CPN to RING message" to new register S23,
40 * "Display message" is now correct on register S13 bit 7.
41 * New audio command AT+VDD implemented (deactivate DTMF decoder and
42 * activate possible existing hardware/DSP decoder).
43 * Moved some tty defines to .h file.
44 * Made whitespace possible in AT command line.
45 * Some AT-emulator output bugfixes.
46 * First Fax G3 implementations.
48 * Revision 1.13 1999/04/12 12:33:09 fritz
49 * Changes from 2.0 tree.
51 * Revision 1.12 1998/07/26 18:48:43 armin
52 * Added silence detection in voice receive mode.
54 * Revision 1.11 1998/04/10 10:35:10 paul
55 * fixed (silly?) warnings from egcs on Alpha.
57 * Revision 1.10 1998/02/20 17:09:40 fritz
58 * Changes for recent kernels.
60 * Revision 1.9 1997/10/01 09:20:25 fritz
61 * Removed old compatibility stuff for 2.0.X kernels.
62 * From now on, this code is for 2.1.X ONLY!
63 * Old stuff is still in the separate branch.
65 * Revision 1.8 1997/03/02 14:29:16 fritz
66 * More ttyI related cleanup.
68 * Revision 1.7 1997/02/03 22:44:11 fritz
69 * Reformatted according CodingStyle
71 * Revision 1.6 1996/06/06 14:43:31 fritz
72 * Changed to support DTMF decoding on audio playback also.
74 * Revision 1.5 1996/06/05 02:24:08 fritz
75 * Added DTMF decoder for audio mode.
77 * Revision 1.4 1996/05/17 03:48:01 fritz
78 * Removed some test statements.
79 * Added revision string.
81 * Revision 1.3 1996/05/10 08:48:11 fritz
82 * Corrected adpcm bugs.
84 * Revision 1.2 1996/04/30 09:31:17 fritz
85 * General rewrite.
87 * Revision 1.1.1.1 1996/04/28 12:25:40 fritz
88 * Taken under CVS control
92 #define __NO_VERSION__
93 #include <linux/module.h>
94 #include <linux/isdn.h>
95 #include "isdn_audio.h"
96 #include "isdn_common.h"
98 char *isdn_audio_revision = "$Revision: 1.17 $";
101 * Misc. lookup-tables.
104 /* ulaw -> signed 16-bit */
105 static short isdn_audio_ulaw_to_s16[] =
107 0x8284, 0x8684, 0x8a84, 0x8e84, 0x9284, 0x9684, 0x9a84, 0x9e84,
108 0xa284, 0xa684, 0xaa84, 0xae84, 0xb284, 0xb684, 0xba84, 0xbe84,
109 0xc184, 0xc384, 0xc584, 0xc784, 0xc984, 0xcb84, 0xcd84, 0xcf84,
110 0xd184, 0xd384, 0xd584, 0xd784, 0xd984, 0xdb84, 0xdd84, 0xdf84,
111 0xe104, 0xe204, 0xe304, 0xe404, 0xe504, 0xe604, 0xe704, 0xe804,
112 0xe904, 0xea04, 0xeb04, 0xec04, 0xed04, 0xee04, 0xef04, 0xf004,
113 0xf0c4, 0xf144, 0xf1c4, 0xf244, 0xf2c4, 0xf344, 0xf3c4, 0xf444,
114 0xf4c4, 0xf544, 0xf5c4, 0xf644, 0xf6c4, 0xf744, 0xf7c4, 0xf844,
115 0xf8a4, 0xf8e4, 0xf924, 0xf964, 0xf9a4, 0xf9e4, 0xfa24, 0xfa64,
116 0xfaa4, 0xfae4, 0xfb24, 0xfb64, 0xfba4, 0xfbe4, 0xfc24, 0xfc64,
117 0xfc94, 0xfcb4, 0xfcd4, 0xfcf4, 0xfd14, 0xfd34, 0xfd54, 0xfd74,
118 0xfd94, 0xfdb4, 0xfdd4, 0xfdf4, 0xfe14, 0xfe34, 0xfe54, 0xfe74,
119 0xfe8c, 0xfe9c, 0xfeac, 0xfebc, 0xfecc, 0xfedc, 0xfeec, 0xfefc,
120 0xff0c, 0xff1c, 0xff2c, 0xff3c, 0xff4c, 0xff5c, 0xff6c, 0xff7c,
121 0xff88, 0xff90, 0xff98, 0xffa0, 0xffa8, 0xffb0, 0xffb8, 0xffc0,
122 0xffc8, 0xffd0, 0xffd8, 0xffe0, 0xffe8, 0xfff0, 0xfff8, 0x0000,
123 0x7d7c, 0x797c, 0x757c, 0x717c, 0x6d7c, 0x697c, 0x657c, 0x617c,
124 0x5d7c, 0x597c, 0x557c, 0x517c, 0x4d7c, 0x497c, 0x457c, 0x417c,
125 0x3e7c, 0x3c7c, 0x3a7c, 0x387c, 0x367c, 0x347c, 0x327c, 0x307c,
126 0x2e7c, 0x2c7c, 0x2a7c, 0x287c, 0x267c, 0x247c, 0x227c, 0x207c,
127 0x1efc, 0x1dfc, 0x1cfc, 0x1bfc, 0x1afc, 0x19fc, 0x18fc, 0x17fc,
128 0x16fc, 0x15fc, 0x14fc, 0x13fc, 0x12fc, 0x11fc, 0x10fc, 0x0ffc,
129 0x0f3c, 0x0ebc, 0x0e3c, 0x0dbc, 0x0d3c, 0x0cbc, 0x0c3c, 0x0bbc,
130 0x0b3c, 0x0abc, 0x0a3c, 0x09bc, 0x093c, 0x08bc, 0x083c, 0x07bc,
131 0x075c, 0x071c, 0x06dc, 0x069c, 0x065c, 0x061c, 0x05dc, 0x059c,
132 0x055c, 0x051c, 0x04dc, 0x049c, 0x045c, 0x041c, 0x03dc, 0x039c,
133 0x036c, 0x034c, 0x032c, 0x030c, 0x02ec, 0x02cc, 0x02ac, 0x028c,
134 0x026c, 0x024c, 0x022c, 0x020c, 0x01ec, 0x01cc, 0x01ac, 0x018c,
135 0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
136 0x00f4, 0x00e4, 0x00d4, 0x00c4, 0x00b4, 0x00a4, 0x0094, 0x0084,
137 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
138 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000
141 /* alaw -> signed 16-bit */
142 static short isdn_audio_alaw_to_s16[] =
144 0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4,
145 0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74,
146 0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4,
147 0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64,
148 0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4,
149 0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4,
150 0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4,
151 0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4,
152 0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64,
153 0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34,
154 0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844,
155 0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24,
156 0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64,
157 0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4,
158 0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964,
159 0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4,
160 0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24,
161 0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94,
162 0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924,
163 0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94,
164 0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24,
165 0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14,
166 0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24,
167 0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14,
168 0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4,
169 0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54,
170 0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4,
171 0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64,
172 0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4,
173 0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4,
174 0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4,
175 0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4
178 /* alaw -> ulaw */
179 static char isdn_audio_alaw_to_ulaw[] =
181 0xab, 0x2b, 0xe3, 0x63, 0x8b, 0x0b, 0xc9, 0x49,
182 0xba, 0x3a, 0xf6, 0x76, 0x9b, 0x1b, 0xd7, 0x57,
183 0xa3, 0x23, 0xdd, 0x5d, 0x83, 0x03, 0xc1, 0x41,
184 0xb2, 0x32, 0xeb, 0x6b, 0x93, 0x13, 0xcf, 0x4f,
185 0xaf, 0x2f, 0xe7, 0x67, 0x8f, 0x0f, 0xcd, 0x4d,
186 0xbe, 0x3e, 0xfe, 0x7e, 0x9f, 0x1f, 0xdb, 0x5b,
187 0xa7, 0x27, 0xdf, 0x5f, 0x87, 0x07, 0xc5, 0x45,
188 0xb6, 0x36, 0xef, 0x6f, 0x97, 0x17, 0xd3, 0x53,
189 0xa9, 0x29, 0xe1, 0x61, 0x89, 0x09, 0xc7, 0x47,
190 0xb8, 0x38, 0xf2, 0x72, 0x99, 0x19, 0xd5, 0x55,
191 0xa1, 0x21, 0xdc, 0x5c, 0x81, 0x01, 0xbf, 0x3f,
192 0xb0, 0x30, 0xe9, 0x69, 0x91, 0x11, 0xce, 0x4e,
193 0xad, 0x2d, 0xe5, 0x65, 0x8d, 0x0d, 0xcb, 0x4b,
194 0xbc, 0x3c, 0xfa, 0x7a, 0x9d, 0x1d, 0xd9, 0x59,
195 0xa5, 0x25, 0xde, 0x5e, 0x85, 0x05, 0xc3, 0x43,
196 0xb4, 0x34, 0xed, 0x6d, 0x95, 0x15, 0xd1, 0x51,
197 0xac, 0x2c, 0xe4, 0x64, 0x8c, 0x0c, 0xca, 0x4a,
198 0xbb, 0x3b, 0xf8, 0x78, 0x9c, 0x1c, 0xd8, 0x58,
199 0xa4, 0x24, 0xde, 0x5e, 0x84, 0x04, 0xc2, 0x42,
200 0xb3, 0x33, 0xec, 0x6c, 0x94, 0x14, 0xd0, 0x50,
201 0xb0, 0x30, 0xe8, 0x68, 0x90, 0x10, 0xce, 0x4e,
202 0xbf, 0x3f, 0xfe, 0x7e, 0xa0, 0x20, 0xdc, 0x5c,
203 0xa8, 0x28, 0xe0, 0x60, 0x88, 0x08, 0xc6, 0x46,
204 0xb7, 0x37, 0xf0, 0x70, 0x98, 0x18, 0xd4, 0x54,
205 0xaa, 0x2a, 0xe2, 0x62, 0x8a, 0x0a, 0xc8, 0x48,
206 0xb9, 0x39, 0xf4, 0x74, 0x9a, 0x1a, 0xd6, 0x56,
207 0xa2, 0x22, 0xdd, 0x5d, 0x82, 0x02, 0xc0, 0x40,
208 0xb1, 0x31, 0xea, 0x6a, 0x92, 0x12, 0xcf, 0x4f,
209 0xae, 0x2e, 0xe6, 0x66, 0x8e, 0x0e, 0xcc, 0x4c,
210 0xbd, 0x3d, 0xfc, 0x7c, 0x9e, 0x1e, 0xda, 0x5a,
211 0xa6, 0x26, 0xdf, 0x5f, 0x86, 0x06, 0xc4, 0x44,
212 0xb5, 0x35, 0xee, 0x6e, 0x96, 0x16, 0xd2, 0x52
215 /* ulaw -> alaw */
216 static char isdn_audio_ulaw_to_alaw[] =
218 0xab, 0x55, 0xd5, 0x15, 0x95, 0x75, 0xf5, 0x35,
219 0xb5, 0x45, 0xc5, 0x05, 0x85, 0x65, 0xe5, 0x25,
220 0xa5, 0x5d, 0xdd, 0x1d, 0x9d, 0x7d, 0xfd, 0x3d,
221 0xbd, 0x4d, 0xcd, 0x0d, 0x8d, 0x6d, 0xed, 0x2d,
222 0xad, 0x51, 0xd1, 0x11, 0x91, 0x71, 0xf1, 0x31,
223 0xb1, 0x41, 0xc1, 0x01, 0x81, 0x61, 0xe1, 0x21,
224 0x59, 0xd9, 0x19, 0x99, 0x79, 0xf9, 0x39, 0xb9,
225 0x49, 0xc9, 0x09, 0x89, 0x69, 0xe9, 0x29, 0xa9,
226 0xd7, 0x17, 0x97, 0x77, 0xf7, 0x37, 0xb7, 0x47,
227 0xc7, 0x07, 0x87, 0x67, 0xe7, 0x27, 0xa7, 0xdf,
228 0x9f, 0x7f, 0xff, 0x3f, 0xbf, 0x4f, 0xcf, 0x0f,
229 0x8f, 0x6f, 0xef, 0x2f, 0x53, 0x13, 0x73, 0x33,
230 0xb3, 0x43, 0xc3, 0x03, 0x83, 0x63, 0xe3, 0x23,
231 0xa3, 0x5b, 0xdb, 0x1b, 0x9b, 0x7b, 0xfb, 0x3b,
232 0xbb, 0xbb, 0x4b, 0x4b, 0xcb, 0xcb, 0x0b, 0x0b,
233 0x8b, 0x8b, 0x6b, 0x6b, 0xeb, 0xeb, 0x2b, 0x2b,
234 0xab, 0x54, 0xd4, 0x14, 0x94, 0x74, 0xf4, 0x34,
235 0xb4, 0x44, 0xc4, 0x04, 0x84, 0x64, 0xe4, 0x24,
236 0xa4, 0x5c, 0xdc, 0x1c, 0x9c, 0x7c, 0xfc, 0x3c,
237 0xbc, 0x4c, 0xcc, 0x0c, 0x8c, 0x6c, 0xec, 0x2c,
238 0xac, 0x50, 0xd0, 0x10, 0x90, 0x70, 0xf0, 0x30,
239 0xb0, 0x40, 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x20,
240 0x58, 0xd8, 0x18, 0x98, 0x78, 0xf8, 0x38, 0xb8,
241 0x48, 0xc8, 0x08, 0x88, 0x68, 0xe8, 0x28, 0xa8,
242 0xd6, 0x16, 0x96, 0x76, 0xf6, 0x36, 0xb6, 0x46,
243 0xc6, 0x06, 0x86, 0x66, 0xe6, 0x26, 0xa6, 0xde,
244 0x9e, 0x7e, 0xfe, 0x3e, 0xbe, 0x4e, 0xce, 0x0e,
245 0x8e, 0x6e, 0xee, 0x2e, 0x52, 0x12, 0x72, 0x32,
246 0xb2, 0x42, 0xc2, 0x02, 0x82, 0x62, 0xe2, 0x22,
247 0xa2, 0x5a, 0xda, 0x1a, 0x9a, 0x7a, 0xfa, 0x3a,
248 0xba, 0xba, 0x4a, 0x4a, 0xca, 0xca, 0x0a, 0x0a,
249 0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a
252 #define NCOEFF 16 /* number of frequencies to be analyzed */
253 #define DTMF_TRESH 50000 /* above this is dtmf */
254 #define SILENCE_TRESH 100 /* below this is silence */
255 #define H2_TRESH 10000 /* 2nd harmonic */
256 #define AMP_BITS 9 /* bits per sample, reduced to avoid overflow */
257 #define LOGRP 0
258 #define HIGRP 1
260 typedef struct {
261 int grp; /* low/high group */
262 int k; /* k */
263 int k2; /* k fuer 2. harmonic */
264 } dtmf_t;
266 /* For DTMF recognition:
267 * 2 * cos(2 * PI * k / N) precalculated for all k
269 static int cos2pik[NCOEFF] =
271 55812, 29528, 53603, 24032, 51193, 14443, 48590, 6517,
272 38113, -21204, 33057, -32186, 25889, -45081, 18332, -55279
275 static dtmf_t dtmf_tones[8] =
277 {LOGRP, 0, 1}, /* 697 Hz */
278 {LOGRP, 2, 3}, /* 770 Hz */
279 {LOGRP, 4, 5}, /* 852 Hz */
280 {LOGRP, 6, 7}, /* 941 Hz */
281 {HIGRP, 8, 9}, /* 1209 Hz */
282 {HIGRP, 10, 11}, /* 1336 Hz */
283 {HIGRP, 12, 13}, /* 1477 Hz */
284 {HIGRP, 14, 15} /* 1633 Hz */
287 static char dtmf_matrix[4][4] =
289 {'1', '2', '3', 'A'},
290 {'4', '5', '6', 'B'},
291 {'7', '8', '9', 'C'},
292 {'*', '0', '#', 'D'}
295 static inline void
296 isdn_audio_tlookup(const void *table, void *buff, unsigned long n)
298 #ifdef __i386__
299 unsigned long d0, d1, d2, d3;
300 __asm__ __volatile__(
301 "cld\n"
302 "1:\tlodsb\n\t"
303 "xlatb\n\t"
304 "stosb\n\t"
305 "loop 1b\n\t"
306 : "=&b"(d0), "=&c"(d1), "=&D"(d2), "=&S"(d3)
307 : "0"((long) table), "1"(n), "2"((long) buff), "3"((long) buff)
308 : "memory", "ax");
309 #else
310 unsigned char* b = (unsigned char*) buff;
311 unsigned char* t = (unsigned char*) table;
312 while (n--)
313 *b++ = t[*b];
314 #endif
317 void
318 isdn_audio_ulaw2alaw(unsigned char *buff, unsigned long len)
320 isdn_audio_tlookup(isdn_audio_ulaw_to_alaw, buff, len);
323 void
324 isdn_audio_alaw2ulaw(unsigned char *buff, unsigned long len)
326 isdn_audio_tlookup(isdn_audio_alaw_to_ulaw, buff, len);
330 * linear <-> adpcm conversion stuff
331 * Most parts from the mgetty-package.
332 * (C) by Gert Doering and Klaus Weidner
333 * Used by permission of Gert Doering
337 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
338 #undef ZEROTRAP
339 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
340 #define CLIP 32635
342 static unsigned char
343 isdn_audio_linear2ulaw(int sample)
345 static int exp_lut[256] =
347 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
348 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
349 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
350 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
351 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
352 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
353 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
354 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
355 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
356 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
357 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
358 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
359 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
360 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
361 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
362 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
364 int sign,
365 exponent,
366 mantissa;
367 unsigned char ulawbyte;
369 /* Get the sample into sign-magnitude. */
370 sign = (sample >> 8) & 0x80; /* set aside the sign */
371 if (sign != 0)
372 sample = -sample; /* get magnitude */
373 if (sample > CLIP)
374 sample = CLIP; /* clip the magnitude */
376 /* Convert from 16 bit linear to ulaw. */
377 sample = sample + BIAS;
378 exponent = exp_lut[(sample >> 7) & 0xFF];
379 mantissa = (sample >> (exponent + 3)) & 0x0F;
380 ulawbyte = ~(sign | (exponent << 4) | mantissa);
381 #ifdef ZEROTRAP
382 /* optional CCITT trap */
383 if (ulawbyte == 0)
384 ulawbyte = 0x02;
385 #endif
386 return (ulawbyte);
390 static int Mx[3][8] =
392 {0x3800, 0x5600, 0, 0, 0, 0, 0, 0},
393 {0x399a, 0x3a9f, 0x4d14, 0x6607, 0, 0, 0, 0},
394 {0x3556, 0x3556, 0x399A, 0x3A9F, 0x4200, 0x4D14, 0x6607, 0x6607},
397 static int bitmask[9] =
399 0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
402 static int
403 isdn_audio_get_bits(adpcm_state * s, unsigned char **in, int *len)
405 while (s->nleft < s->nbits) {
406 int d = *((*in)++);
407 (*len)--;
408 s->word = (s->word << 8) | d;
409 s->nleft += 8;
411 s->nleft -= s->nbits;
412 return (s->word >> s->nleft) & bitmask[s->nbits];
415 static void
416 isdn_audio_put_bits(int data, int nbits, adpcm_state * s,
417 unsigned char **out, int *len)
419 s->word = (s->word << nbits) | (data & bitmask[nbits]);
420 s->nleft += nbits;
421 while (s->nleft >= 8) {
422 int d = (s->word >> (s->nleft - 8));
423 *(out[0]++) = d & 255;
424 (*len)++;
425 s->nleft -= 8;
429 adpcm_state *
430 isdn_audio_adpcm_init(adpcm_state * s, int nbits)
432 if (!s)
433 s = (adpcm_state *) kmalloc(sizeof(adpcm_state), GFP_ATOMIC);
434 if (s) {
435 s->a = 0;
436 s->d = 5;
437 s->word = 0;
438 s->nleft = 0;
439 s->nbits = nbits;
441 return s;
444 dtmf_state *
445 isdn_audio_dtmf_init(dtmf_state * s)
447 if (!s)
448 s = (dtmf_state *) kmalloc(sizeof(dtmf_state), GFP_ATOMIC);
449 if (s) {
450 s->idx = 0;
451 s->last = ' ';
453 return s;
457 * Decompression of adpcm data to a/u-law
462 isdn_audio_adpcm2xlaw(adpcm_state * s, int fmt, unsigned char *in,
463 unsigned char *out, int len)
465 int a = s->a;
466 int d = s->d;
467 int nbits = s->nbits;
468 int olen = 0;
470 while (len) {
471 int e = isdn_audio_get_bits(s, &in, &len);
472 int sign;
474 if (nbits == 4 && e == 0)
475 d = 4;
476 sign = (e >> (nbits - 1)) ? -1 : 1;
477 e &= bitmask[nbits - 1];
478 a += sign * ((e << 1) + 1) * d >> 1;
479 if (d & 1)
480 a++;
481 if (fmt)
482 *out++ = isdn_audio_ulaw_to_alaw[
483 isdn_audio_linear2ulaw(a << 2)];
484 else
485 *out++ = isdn_audio_linear2ulaw(a << 2);
486 olen++;
487 d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
488 if (d < 5)
489 d = 5;
491 s->a = a;
492 s->d = d;
493 return olen;
497 isdn_audio_2adpcm_flush(adpcm_state * s, unsigned char *out)
499 int olen = 0;
501 if (s->nleft)
502 isdn_audio_put_bits(0, 8 - s->nleft, s, &out, &olen);
503 return olen;
507 isdn_audio_xlaw2adpcm(adpcm_state * s, int fmt, unsigned char *in,
508 unsigned char *out, int len)
510 int a = s->a;
511 int d = s->d;
512 int nbits = s->nbits;
513 int olen = 0;
515 while (len--) {
516 int e = 0,
517 nmax = 1 << (nbits - 1);
518 int sign,
519 delta;
521 if (fmt)
522 delta = (isdn_audio_alaw_to_s16[*in++] >> 2) - a;
523 else
524 delta = (isdn_audio_ulaw_to_s16[*in++] >> 2) - a;
525 if (delta < 0) {
526 e = nmax;
527 delta = -delta;
529 while (--nmax && delta > d) {
530 delta -= d;
531 e++;
533 if (nbits == 4 && ((e & 0x0f) == 0))
534 e = 8;
535 isdn_audio_put_bits(e, nbits, s, &out, &olen);
536 sign = (e >> (nbits - 1)) ? -1 : 1;
537 e &= bitmask[nbits - 1];
539 a += sign * ((e << 1) + 1) * d >> 1;
540 if (d & 1)
541 a++;
542 d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
543 if (d < 5)
544 d = 5;
546 s->a = a;
547 s->d = d;
548 return olen;
552 * Goertzel algorithm.
553 * See http://ptolemy.eecs.berkeley.edu/~pino/Ptolemy/papers/96/dtmf_ict/
554 * for more info.
555 * Result is stored into an sk_buff and queued up for later
556 * evaluation.
558 static void
559 isdn_audio_goertzel(int *sample, modem_info * info)
561 int sk,
562 sk1,
563 sk2;
564 int k,
566 struct sk_buff *skb;
567 int *result;
569 skb = dev_alloc_skb(sizeof(int) * NCOEFF);
570 if (!skb) {
571 printk(KERN_WARNING
572 "isdn_audio: Could not alloc DTMF result for ttyI%d\n",
573 info->line);
574 return;
576 result = (int *) skb_put(skb, sizeof(int) * NCOEFF);
577 for (k = 0; k < NCOEFF; k++) {
578 sk = sk1 = sk2 = 0;
579 for (n = 0; n < DTMF_NPOINTS; n++) {
580 sk = sample[n] + ((cos2pik[k] * sk1) >> 15) - sk2;
581 sk2 = sk1;
582 sk1 = sk;
584 result[k] =
585 ((sk * sk) >> AMP_BITS) -
586 ((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) +
587 ((sk2 * sk2) >> AMP_BITS);
589 skb_queue_tail(&info->dtmf_queue, skb);
590 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
593 void
594 isdn_audio_eval_dtmf(modem_info * info)
596 struct sk_buff *skb;
597 int *result;
598 dtmf_state *s;
599 int silence;
600 int i;
601 int di;
602 int ch;
603 unsigned long flags;
604 int grp[2];
605 char what;
606 char *p;
608 while ((skb = skb_dequeue(&info->dtmf_queue))) {
609 result = (int *) skb->data;
610 s = info->dtmf_state;
611 grp[LOGRP] = grp[HIGRP] = -2;
612 silence = 0;
613 for (i = 0; i < 8; i++) {
614 if ((result[dtmf_tones[i].k] > DTMF_TRESH) &&
615 (result[dtmf_tones[i].k2] < H2_TRESH))
616 grp[dtmf_tones[i].grp] = (grp[dtmf_tones[i].grp] == -2) ? i : -1;
617 else if ((result[dtmf_tones[i].k] < SILENCE_TRESH) &&
618 (result[dtmf_tones[i].k2] < SILENCE_TRESH))
619 silence++;
621 if (silence == 8)
622 what = ' ';
623 else {
624 if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {
625 what = dtmf_matrix[grp[LOGRP]][grp[HIGRP] - 4];
626 if (s->last != ' ' && s->last != '.')
627 s->last = what; /* min. 1 non-DTMF between DTMF */
628 } else
629 what = '.';
631 if ((what != s->last) && (what != ' ') && (what != '.')) {
632 printk(KERN_DEBUG "dtmf: tt='%c'\n", what);
633 p = skb->data;
634 *p++ = 0x10;
635 *p = what;
636 skb_trim(skb, 2);
637 if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {
638 printk(KERN_WARNING
639 "isdn_audio: insufficient skb_headroom, dropping\n");
640 kfree_skb(skb);
641 return;
643 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
644 ISDN_AUDIO_SKB_LOCK(skb) = 0;
645 save_flags(flags);
646 cli();
647 di = info->isdn_driver;
648 ch = info->isdn_channel;
649 __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
650 dev->drv[di]->rcvcount[ch] += 2;
651 restore_flags(flags);
652 /* Schedule dequeuing */
653 if ((dev->modempoll) && (info->rcvsched))
654 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
655 wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
656 } else
657 kfree_skb(skb);
658 s->last = what;
663 * Decode DTMF tones, queue result in separate sk_buf for
664 * later examination.
665 * Parameters:
666 * s = pointer to state-struct.
667 * buf = input audio data
668 * len = size of audio data.
669 * fmt = audio data format (0 = ulaw, 1 = alaw)
671 void
672 isdn_audio_calc_dtmf(modem_info * info, unsigned char *buf, int len, int fmt)
674 dtmf_state *s = info->dtmf_state;
675 int i;
676 int c;
678 while (len) {
679 c = MIN(len, (DTMF_NPOINTS - s->idx));
680 if (c <= 0)
681 break;
682 for (i = 0; i < c; i++) {
683 if (fmt)
684 s->buf[s->idx++] =
685 isdn_audio_alaw_to_s16[*buf++] >> (15 - AMP_BITS);
686 else
687 s->buf[s->idx++] =
688 isdn_audio_ulaw_to_s16[*buf++] >> (15 - AMP_BITS);
690 if (s->idx == DTMF_NPOINTS) {
691 isdn_audio_goertzel(s->buf, info);
692 s->idx = 0;
694 len -= c;
698 silence_state *
699 isdn_audio_silence_init(silence_state * s)
701 if (!s)
702 s = (silence_state *) kmalloc(sizeof(silence_state), GFP_ATOMIC);
703 if (s) {
704 s->idx = 0;
705 s->state = 0;
707 return s;
710 void
711 isdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt)
713 silence_state *s = info->silence_state;
714 int i;
715 signed char c;
717 if (!info->emu.vpar[1]) return;
719 for (i = 0; i < len; i++) {
720 if (fmt)
721 c = isdn_audio_alaw_to_ulaw[*buf++];
722 else
723 c = *buf++;
725 if (c > 0) c -= 128;
726 c = abs(c);
728 if (c > (info->emu.vpar[1] * 4)) {
729 s->idx = 0;
730 s->state = 1;
731 } else {
732 if (s->idx < 210000) s->idx++;
737 void
738 isdn_audio_put_dle_code(modem_info * info, u_char code)
740 struct sk_buff *skb;
741 unsigned long flags;
742 int di;
743 int ch;
744 char *p;
746 skb = dev_alloc_skb(2);
747 if (!skb) {
748 printk(KERN_WARNING
749 "isdn_audio: Could not alloc skb for ttyI%d\n",
750 info->line);
751 return;
753 p = (char *) skb_put(skb, 2);
754 p[0] = 0x10;
755 p[1] = code;
756 if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {
757 printk(KERN_WARNING
758 "isdn_audio: insufficient skb_headroom, dropping\n");
759 kfree_skb(skb);
760 return;
762 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
763 ISDN_AUDIO_SKB_LOCK(skb) = 0;
764 save_flags(flags);
765 cli();
766 di = info->isdn_driver;
767 ch = info->isdn_channel;
768 __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
769 dev->drv[di]->rcvcount[ch] += 2;
770 restore_flags(flags);
771 /* Schedule dequeuing */
772 if ((dev->modempoll) && (info->rcvsched))
773 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
774 wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
777 void
778 isdn_audio_eval_silence(modem_info * info)
780 silence_state *s = info->silence_state;
781 char what;
783 what = ' ';
785 if (s->idx > (info->emu.vpar[2] * 800)) {
786 s->idx = 0;
787 if (!s->state) { /* silence from beginning of rec */
788 what = 's';
789 } else {
790 what = 'q';
793 if ((what == 's') || (what == 'q')) {
794 printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
795 (what=='s') ? "silence":"quiet");
796 isdn_audio_put_dle_code(info, what);