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)
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
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
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
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 */
261 int grp
; /* low/high group */
263 int k2
; /* k fuer 2. harmonic */
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'},
296 isdn_audio_tlookup(const void *table
, void *buff
, unsigned long n
)
299 unsigned long d0
, d1
, d2
, d3
;
300 __asm__
__volatile__(
306 : "=&b"(d0
), "=&c"(d1
), "=&D"(d2
), "=&S"(d3
)
307 : "0"((long) table
), "1"(n
), "2"((long) buff
), "3"((long) buff
)
310 unsigned char* b
= (unsigned char*) buff
;
311 unsigned char* t
= (unsigned char*) table
;
318 isdn_audio_ulaw2alaw(unsigned char *buff
, unsigned long len
)
320 isdn_audio_tlookup(isdn_audio_ulaw_to_alaw
, buff
, len
);
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 */
339 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
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
367 unsigned char ulawbyte
;
369 /* Get the sample into sign-magnitude. */
370 sign
= (sample
>> 8) & 0x80; /* set aside the sign */
372 sample
= -sample
; /* get magnitude */
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
);
382 /* optional CCITT trap */
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
403 isdn_audio_get_bits(adpcm_state
* s
, unsigned char **in
, int *len
)
405 while (s
->nleft
< s
->nbits
) {
408 s
->word
= (s
->word
<< 8) | d
;
411 s
->nleft
-= s
->nbits
;
412 return (s
->word
>> s
->nleft
) & bitmask
[s
->nbits
];
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
]);
421 while (s
->nleft
>= 8) {
422 int d
= (s
->word
>> (s
->nleft
- 8));
423 *(out
[0]++) = d
& 255;
430 isdn_audio_adpcm_init(adpcm_state
* s
, int nbits
)
433 s
= (adpcm_state
*) kmalloc(sizeof(adpcm_state
), GFP_ATOMIC
);
445 isdn_audio_dtmf_init(dtmf_state
* s
)
448 s
= (dtmf_state
*) kmalloc(sizeof(dtmf_state
), GFP_ATOMIC
);
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
)
467 int nbits
= s
->nbits
;
471 int e
= isdn_audio_get_bits(s
, &in
, &len
);
474 if (nbits
== 4 && e
== 0)
476 sign
= (e
>> (nbits
- 1)) ? -1 : 1;
477 e
&= bitmask
[nbits
- 1];
478 a
+= sign
* ((e
<< 1) + 1) * d
>> 1;
482 *out
++ = isdn_audio_ulaw_to_alaw
[
483 isdn_audio_linear2ulaw(a
<< 2)];
485 *out
++ = isdn_audio_linear2ulaw(a
<< 2);
487 d
= (d
* Mx
[nbits
- 2][e
] + 0x2000) >> 14;
497 isdn_audio_2adpcm_flush(adpcm_state
* s
, unsigned char *out
)
502 isdn_audio_put_bits(0, 8 - s
->nleft
, s
, &out
, &olen
);
507 isdn_audio_xlaw2adpcm(adpcm_state
* s
, int fmt
, unsigned char *in
,
508 unsigned char *out
, int len
)
512 int nbits
= s
->nbits
;
517 nmax
= 1 << (nbits
- 1);
522 delta
= (isdn_audio_alaw_to_s16
[*in
++] >> 2) - a
;
524 delta
= (isdn_audio_ulaw_to_s16
[*in
++] >> 2) - a
;
529 while (--nmax
&& delta
> d
) {
533 if (nbits
== 4 && ((e
& 0x0f) == 0))
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;
542 d
= (d
* Mx
[nbits
- 2][e
] + 0x2000) >> 14;
552 * Goertzel algorithm.
553 * See http://ptolemy.eecs.berkeley.edu/~pino/Ptolemy/papers/96/dtmf_ict/
555 * Result is stored into an sk_buff and queued up for later
559 isdn_audio_goertzel(int *sample
, modem_info
* info
)
569 skb
= dev_alloc_skb(sizeof(int) * NCOEFF
);
572 "isdn_audio: Could not alloc DTMF result for ttyI%d\n",
576 result
= (int *) skb_put(skb
, sizeof(int) * NCOEFF
);
577 for (k
= 0; k
< NCOEFF
; k
++) {
579 for (n
= 0; n
< DTMF_NPOINTS
; n
++) {
580 sk
= sample
[n
] + ((cos2pik
[k
] * sk1
) >> 15) - sk2
;
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);
594 isdn_audio_eval_dtmf(modem_info
* info
)
608 while ((skb
= skb_dequeue(&info
->dtmf_queue
))) {
609 result
= (int *) skb
->data
;
610 s
= info
->dtmf_state
;
611 grp
[LOGRP
] = grp
[HIGRP
] = -2;
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
))
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 */
631 if ((what
!= s
->last
) && (what
!= ' ') && (what
!= '.')) {
632 printk(KERN_DEBUG
"dtmf: tt='%c'\n", what
);
637 if (skb_headroom(skb
) < sizeof(isdn_audio_skb
)) {
639 "isdn_audio: insufficient skb_headroom, dropping\n");
643 ISDN_AUDIO_SKB_DLECOUNT(skb
) = 0;
644 ISDN_AUDIO_SKB_LOCK(skb
) = 0;
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
]);
663 * Decode DTMF tones, queue result in separate sk_buf for
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)
672 isdn_audio_calc_dtmf(modem_info
* info
, unsigned char *buf
, int len
, int fmt
)
674 dtmf_state
*s
= info
->dtmf_state
;
679 c
= MIN(len
, (DTMF_NPOINTS
- s
->idx
));
682 for (i
= 0; i
< c
; i
++) {
685 isdn_audio_alaw_to_s16
[*buf
++] >> (15 - AMP_BITS
);
688 isdn_audio_ulaw_to_s16
[*buf
++] >> (15 - AMP_BITS
);
690 if (s
->idx
== DTMF_NPOINTS
) {
691 isdn_audio_goertzel(s
->buf
, info
);
699 isdn_audio_silence_init(silence_state
* s
)
702 s
= (silence_state
*) kmalloc(sizeof(silence_state
), GFP_ATOMIC
);
711 isdn_audio_calc_silence(modem_info
* info
, unsigned char *buf
, int len
, int fmt
)
713 silence_state
*s
= info
->silence_state
;
717 if (!info
->emu
.vpar
[1]) return;
719 for (i
= 0; i
< len
; i
++) {
721 c
= isdn_audio_alaw_to_ulaw
[*buf
++];
728 if (c
> (info
->emu
.vpar
[1] * 4)) {
732 if (s
->idx
< 210000) s
->idx
++;
738 isdn_audio_put_dle_code(modem_info
* info
, u_char code
)
746 skb
= dev_alloc_skb(2);
749 "isdn_audio: Could not alloc skb for ttyI%d\n",
753 p
= (char *) skb_put(skb
, 2);
756 if (skb_headroom(skb
) < sizeof(isdn_audio_skb
)) {
758 "isdn_audio: insufficient skb_headroom, dropping\n");
762 ISDN_AUDIO_SKB_DLECOUNT(skb
) = 0;
763 ISDN_AUDIO_SKB_LOCK(skb
) = 0;
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
]);
778 isdn_audio_eval_silence(modem_info
* info
)
780 silence_state
*s
= info
->silence_state
;
785 if (s
->idx
> (info
->emu
.vpar
[2] * 800)) {
787 if (!s
->state
) { /* silence from beginning of rec */
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
);