Kill st_fstype member.
[linux-2.6/linux-mips.git] / drivers / isdn / isdn_audio.c
blobe8850ee95107e87b383dc12de8179a25a7cd623d
1 /* $Id: isdn_audio.c,v 1.21 2000/06/20 18:01:55 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 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.
25 #define __NO_VERSION__
26 #include <linux/module.h>
27 #include <linux/isdn.h>
28 #include "isdn_audio.h"
29 #include "isdn_common.h"
31 char *isdn_audio_revision = "$Revision: 1.21 $";
34 * Misc. lookup-tables.
37 /* ulaw -> signed 16-bit */
38 static short isdn_audio_ulaw_to_s16[] =
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
74 /* alaw -> signed 16-bit */
75 static short isdn_audio_alaw_to_s16[] =
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
111 /* alaw -> ulaw */
112 static char isdn_audio_alaw_to_ulaw[] =
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
148 /* ulaw -> alaw */
149 static char isdn_audio_ulaw_to_alaw[] =
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
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
193 typedef struct {
194 int grp; /* low/high group */
195 int k; /* k */
196 int k2; /* k fuer 2. harmonic */
197 } dtmf_t;
199 /* For DTMF recognition:
200 * 2 * cos(2 * PI * k / N) precalculated for all k
202 static int cos2pik[NCOEFF] =
204 55812, 29528, 53603, 24032, 51193, 14443, 48590, 6517,
205 38113, -21204, 33057, -32186, 25889, -45081, 18332, -55279
208 static dtmf_t dtmf_tones[8] =
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 */
220 static char dtmf_matrix[4][4] =
222 {'1', '2', '3', 'A'},
223 {'4', '5', '6', 'B'},
224 {'7', '8', '9', 'C'},
225 {'*', '0', '#', 'D'}
228 static inline void
229 isdn_audio_tlookup(const u_char *table, u_char *buff, unsigned long n)
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
248 void
249 isdn_audio_ulaw2alaw(unsigned char *buff, unsigned long len)
251 isdn_audio_tlookup(isdn_audio_ulaw_to_alaw, buff, len);
254 void
255 isdn_audio_alaw2ulaw(unsigned char *buff, unsigned long len)
257 isdn_audio_tlookup(isdn_audio_alaw_to_ulaw, buff, len);
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
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
273 static unsigned char
274 isdn_audio_linear2ulaw(int sample)
276 static int exp_lut[256] =
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
295 int sign,
296 exponent,
297 mantissa;
298 unsigned char ulawbyte;
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 */
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);
321 static int Mx[3][8] =
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},
328 static int bitmask[9] =
330 0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
333 static int
334 isdn_audio_get_bits(adpcm_state * s, unsigned char **in, int *len)
336 while (s->nleft < s->nbits) {
337 int d = *((*in)++);
338 (*len)--;
339 s->word = (s->word << 8) | d;
340 s->nleft += 8;
342 s->nleft -= s->nbits;
343 return (s->word >> s->nleft) & bitmask[s->nbits];
346 static void
347 isdn_audio_put_bits(int data, int nbits, adpcm_state * s,
348 unsigned char **out, int *len)
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;
360 adpcm_state *
361 isdn_audio_adpcm_init(adpcm_state * s, int nbits)
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;
372 return s;
375 dtmf_state *
376 isdn_audio_dtmf_init(dtmf_state * s)
378 if (!s)
379 s = (dtmf_state *) kmalloc(sizeof(dtmf_state), GFP_ATOMIC);
380 if (s) {
381 s->idx = 0;
382 s->last = ' ';
384 return s;
388 * Decompression of adpcm data to a/u-law
393 isdn_audio_adpcm2xlaw(adpcm_state * s, int fmt, unsigned char *in,
394 unsigned char *out, int len)
396 int a = s->a;
397 int d = s->d;
398 int nbits = s->nbits;
399 int olen = 0;
401 while (len) {
402 int e = isdn_audio_get_bits(s, &in, &len);
403 int sign;
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;
422 s->a = a;
423 s->d = d;
424 return olen;
428 isdn_audio_2adpcm_flush(adpcm_state * s, unsigned char *out)
430 int olen = 0;
432 if (s->nleft)
433 isdn_audio_put_bits(0, 8 - s->nleft, s, &out, &olen);
434 return olen;
438 isdn_audio_xlaw2adpcm(adpcm_state * s, int fmt, unsigned char *in,
439 unsigned char *out, int len)
441 int a = s->a;
442 int d = s->d;
443 int nbits = s->nbits;
444 int olen = 0;
446 while (len--) {
447 int e = 0,
448 nmax = 1 << (nbits - 1);
449 int sign,
450 delta;
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;
460 while (--nmax && delta > d) {
461 delta -= d;
462 e++;
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];
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;
477 s->a = a;
478 s->d = d;
479 return olen;
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.
489 static void
490 isdn_audio_goertzel(int *sample, modem_info * info)
492 int sk,
493 sk1,
494 sk2;
495 int k,
497 struct sk_buff *skb;
498 int *result;
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;
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;
515 result[k] =
516 ((sk * sk) >> AMP_BITS) -
517 ((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) +
518 ((sk2 * sk2) >> AMP_BITS);
520 skb_queue_tail(&info->dtmf_queue, skb);
521 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
524 void
525 isdn_audio_eval_dtmf(modem_info * info)
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;
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++;
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 = '.';
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;
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;
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)
602 void
603 isdn_audio_calc_dtmf(modem_info * info, unsigned char *buf, int len, int fmt)
605 dtmf_state *s = info->dtmf_state;
606 int i;
607 int c;
609 while (len) {
610 c = MIN(len, (DTMF_NPOINTS - s->idx));
611 if (c <= 0)
612 break;
613 for (i = 0; i < c; i++) {
614 if (fmt)
615 s->buf[s->idx++] =
616 isdn_audio_alaw_to_s16[*buf++] >> (15 - AMP_BITS);
617 else
618 s->buf[s->idx++] =
619 isdn_audio_ulaw_to_s16[*buf++] >> (15 - AMP_BITS);
621 if (s->idx == DTMF_NPOINTS) {
622 isdn_audio_goertzel(s->buf, info);
623 s->idx = 0;
625 len -= c;
629 silence_state *
630 isdn_audio_silence_init(silence_state * s)
632 if (!s)
633 s = (silence_state *) kmalloc(sizeof(silence_state), GFP_ATOMIC);
634 if (s) {
635 s->idx = 0;
636 s->state = 0;
638 return s;
641 void
642 isdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt)
644 silence_state *s = info->silence_state;
645 int i;
646 signed char c;
648 if (!info->emu.vpar[1]) return;
650 for (i = 0; i < len; i++) {
651 if (fmt)
652 c = isdn_audio_alaw_to_ulaw[*buf++];
653 else
654 c = *buf++;
656 if (c > 0) c -= 128;
657 c = abs(c);
659 if (c > (info->emu.vpar[1] * 4)) {
660 s->idx = 0;
661 s->state = 1;
662 } else {
663 if (s->idx < 210000) s->idx++;
668 void
669 isdn_audio_put_dle_code(modem_info * info, u_char code)
671 struct sk_buff *skb;
672 unsigned long flags;
673 int di;
674 int ch;
675 char *p;
677 skb = dev_alloc_skb(2);
678 if (!skb) {
679 printk(KERN_WARNING
680 "isdn_audio: Could not alloc skb for ttyI%d\n",
681 info->line);
682 return;
684 p = (char *) skb_put(skb, 2);
685 p[0] = 0x10;
686 p[1] = code;
687 if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {
688 printk(KERN_WARNING
689 "isdn_audio: insufficient skb_headroom, dropping\n");
690 kfree_skb(skb);
691 return;
693 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
694 ISDN_AUDIO_SKB_LOCK(skb) = 0;
695 save_flags(flags);
696 cli();
697 di = info->isdn_driver;
698 ch = info->isdn_channel;
699 __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
700 dev->drv[di]->rcvcount[ch] += 2;
701 restore_flags(flags);
702 /* Schedule dequeuing */
703 if ((dev->modempoll) && (info->rcvsched))
704 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
705 wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
708 void
709 isdn_audio_eval_silence(modem_info * info)
711 silence_state *s = info->silence_state;
712 char what;
714 what = ' ';
716 if (s->idx > (info->emu.vpar[2] * 800)) {
717 s->idx = 0;
718 if (!s->state) { /* silence from beginning of rec */
719 what = 's';
720 } else {
721 what = 'q';
724 if ((what == 's') || (what == 'q')) {
725 printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
726 (what=='s') ? "silence":"quiet");
727 isdn_audio_put_dle_code(info, what);