Linux-2.6.12-rc2
[linux-flexiantxendom0-natty.git] / drivers / isdn / i4l / isdn_audio.c
1 /* $Id: isdn_audio.c,v 1.1.2.2 2004/01/12 22:37:18 keil 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 software may be used and distributed according to the terms
10  * of the GNU General Public License, incorporated herein by reference.
11  *
12  */
13
14 #include <linux/isdn.h>
15 #include "isdn_audio.h"
16 #include "isdn_common.h"
17
18 char *isdn_audio_revision = "$Revision: 1.1.2.2 $";
19
20 /*
21  * Misc. lookup-tables.
22  */
23
24 /* ulaw -> signed 16-bit */
25 static short isdn_audio_ulaw_to_s16[] =
26 {
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
59 };
60
61 /* alaw -> signed 16-bit */
62 static short isdn_audio_alaw_to_s16[] =
63 {
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
96 };
97
98 /* alaw -> ulaw */
99 static char isdn_audio_alaw_to_ulaw[] =
100 {
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
133 };
134
135 /* ulaw -> alaw */
136 static char isdn_audio_ulaw_to_alaw[] =
137 {
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
170 };
171
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 */
176 #define LOGRP             0
177 #define HIGRP             1
178
179 /* For DTMF recognition:
180  * 2 * cos(2 * PI * k / N) precalculated for all k
181  */
182 static int cos2pik[NCOEFF] =
183 {
184         55813, 53604, 51193, 48591, 38114, 33057, 25889, 18332
185 };
186
187 static char dtmf_matrix[4][4] =
188 {
189         {'1', '2', '3', 'A'},
190         {'4', '5', '6', 'B'},
191         {'7', '8', '9', 'C'},
192         {'*', '0', '#', 'D'}
193 };
194
195 static inline void
196 isdn_audio_tlookup(const u_char *table, u_char *buff, unsigned long n)
197 {
198 #ifdef __i386__
199         unsigned long d0, d1, d2, d3;
200         __asm__ __volatile__(
201                 "cld\n"
202                 "1:\tlodsb\n\t"
203                 "xlatb\n\t"
204                 "stosb\n\t"
205                 "loop 1b\n\t"
206         :       "=&b"(d0), "=&c"(d1), "=&D"(d2), "=&S"(d3)
207         :       "0"((long) table), "1"(n), "2"((long) buff), "3"((long) buff)
208         :       "memory", "ax");
209 #else
210         while (n--)
211                 *buff = table[*(unsigned char *)buff], buff++;
212 #endif
213 }
214
215 void
216 isdn_audio_ulaw2alaw(unsigned char *buff, unsigned long len)
217 {
218         isdn_audio_tlookup(isdn_audio_ulaw_to_alaw, buff, len);
219 }
220
221 void
222 isdn_audio_alaw2ulaw(unsigned char *buff, unsigned long len)
223 {
224         isdn_audio_tlookup(isdn_audio_alaw_to_ulaw, buff, len);
225 }
226
227 /*
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
232  */
233
234
235 #define ZEROTRAP                /* turn on the trap as per the MIL-STD */
236 #undef ZEROTRAP
237 #define BIAS 0x84               /* define the add-in bias for 16 bit samples */
238 #define CLIP 32635
239
240 static unsigned char
241 isdn_audio_linear2ulaw(int sample)
242 {
243         static int exp_lut[256] =
244         {
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
261         };
262         int sign,
263          exponent,
264          mantissa;
265         unsigned char ulawbyte;
266
267         /* Get the sample into sign-magnitude. */
268         sign = (sample >> 8) & 0x80;    /* set aside the sign  */
269         if (sign != 0)
270                 sample = -sample;       /* get magnitude       */
271         if (sample > CLIP)
272                 sample = CLIP;  /* clip the magnitude  */
273
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);
279 #ifdef ZEROTRAP
280         /* optional CCITT trap */
281         if (ulawbyte == 0)
282                 ulawbyte = 0x02;
283 #endif
284         return (ulawbyte);
285 }
286
287
288 static int Mx[3][8] =
289 {
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},
293 };
294
295 static int bitmask[9] =
296 {
297         0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
298 };
299
300 static int
301 isdn_audio_get_bits(adpcm_state * s, unsigned char **in, int *len)
302 {
303         while (s->nleft < s->nbits) {
304                 int d = *((*in)++);
305                 (*len)--;
306                 s->word = (s->word << 8) | d;
307                 s->nleft += 8;
308         }
309         s->nleft -= s->nbits;
310         return (s->word >> s->nleft) & bitmask[s->nbits];
311 }
312
313 static void
314 isdn_audio_put_bits(int data, int nbits, adpcm_state * s,
315                     unsigned char **out, int *len)
316 {
317         s->word = (s->word << nbits) | (data & bitmask[nbits]);
318         s->nleft += nbits;
319         while (s->nleft >= 8) {
320                 int d = (s->word >> (s->nleft - 8));
321                 *(out[0]++) = d & 255;
322                 (*len)++;
323                 s->nleft -= 8;
324         }
325 }
326
327 adpcm_state *
328 isdn_audio_adpcm_init(adpcm_state * s, int nbits)
329 {
330         if (!s)
331                 s = (adpcm_state *) kmalloc(sizeof(adpcm_state), GFP_ATOMIC);
332         if (s) {
333                 s->a = 0;
334                 s->d = 5;
335                 s->word = 0;
336                 s->nleft = 0;
337                 s->nbits = nbits;
338         }
339         return s;
340 }
341
342 dtmf_state *
343 isdn_audio_dtmf_init(dtmf_state * s)
344 {
345         if (!s)
346                 s = (dtmf_state *) kmalloc(sizeof(dtmf_state), GFP_ATOMIC);
347         if (s) {
348                 s->idx = 0;
349                 s->last = ' ';
350         }
351         return s;
352 }
353
354 /*
355  * Decompression of adpcm data to a/u-law
356  *
357  */
358
359 int
360 isdn_audio_adpcm2xlaw(adpcm_state * s, int fmt, unsigned char *in,
361                       unsigned char *out, int len)
362 {
363         int a = s->a;
364         int d = s->d;
365         int nbits = s->nbits;
366         int olen = 0;
367
368         while (len) {
369                 int e = isdn_audio_get_bits(s, &in, &len);
370                 int sign;
371
372                 if (nbits == 4 && e == 0)
373                         d = 4;
374                 sign = (e >> (nbits - 1)) ? -1 : 1;
375                 e &= bitmask[nbits - 1];
376                 a += sign * ((e << 1) + 1) * d >> 1;
377                 if (d & 1)
378                         a++;
379                 if (fmt)
380                         *out++ = isdn_audio_ulaw_to_alaw[
381                                          isdn_audio_linear2ulaw(a << 2)];
382                 else
383                         *out++ = isdn_audio_linear2ulaw(a << 2);
384                 olen++;
385                 d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
386                 if (d < 5)
387                         d = 5;
388         }
389         s->a = a;
390         s->d = d;
391         return olen;
392 }
393
394 int
395 isdn_audio_2adpcm_flush(adpcm_state * s, unsigned char *out)
396 {
397         int olen = 0;
398
399         if (s->nleft)
400                 isdn_audio_put_bits(0, 8 - s->nleft, s, &out, &olen);
401         return olen;
402 }
403
404 int
405 isdn_audio_xlaw2adpcm(adpcm_state * s, int fmt, unsigned char *in,
406                       unsigned char *out, int len)
407 {
408         int a = s->a;
409         int d = s->d;
410         int nbits = s->nbits;
411         int olen = 0;
412
413         while (len--) {
414                 int e = 0,
415                  nmax = 1 << (nbits - 1);
416                 int sign,
417                  delta;
418
419                 if (fmt)
420                         delta = (isdn_audio_alaw_to_s16[*in++] >> 2) - a;
421                 else
422                         delta = (isdn_audio_ulaw_to_s16[*in++] >> 2) - a;
423                 if (delta < 0) {
424                         e = nmax;
425                         delta = -delta;
426                 }
427                 while (--nmax && delta > d) {
428                         delta -= d;
429                         e++;
430                 }
431                 if (nbits == 4 && ((e & 0x0f) == 0))
432                         e = 8;
433                 isdn_audio_put_bits(e, nbits, s, &out, &olen);
434                 sign = (e >> (nbits - 1)) ? -1 : 1;
435                 e &= bitmask[nbits - 1];
436
437                 a += sign * ((e << 1) + 1) * d >> 1;
438                 if (d & 1)
439                         a++;
440                 d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
441                 if (d < 5)
442                         d = 5;
443         }
444         s->a = a;
445         s->d = d;
446         return olen;
447 }
448
449 /*
450  * Goertzel algorithm.
451  * See http://ptolemy.eecs.berkeley.edu/~pino/Ptolemy/papers/96/dtmf_ict/
452  * for more info.
453  * Result is stored into an sk_buff and queued up for later
454  * evaluation.
455  */
456 static void
457 isdn_audio_goertzel(int *sample, modem_info * info)
458 {
459         int sk,
460          sk1,
461          sk2;
462         int k,
463          n;
464         struct sk_buff *skb;
465         int *result;
466
467         skb = dev_alloc_skb(sizeof(int) * NCOEFF);
468         if (!skb) {
469                 printk(KERN_WARNING
470                   "isdn_audio: Could not alloc DTMF result for ttyI%d\n",
471                        info->line);
472                 return;
473         }
474         result = (int *) skb_put(skb, sizeof(int) * NCOEFF);
475         for (k = 0; k < NCOEFF; k++) {
476                 sk = sk1 = sk2 = 0;
477                 for (n = 0; n < DTMF_NPOINTS; n++) {
478                         sk = sample[n] + ((cos2pik[k] * sk1) >> 15) - sk2;
479                         sk2 = sk1;
480                         sk1 = sk;
481                 }
482                 /* Avoid overflows */
483                 sk >>= 1;
484                 sk2 >>= 1;
485                 /* compute |X(k)|**2 */
486                 /* report overflows. This should not happen. */
487                 /* Comment this out if desired */
488                 if (sk < -32768 || sk > 32767)
489                         printk(KERN_DEBUG
490                                "isdn_audio: dtmf goertzel overflow, sk=%d\n", sk);
491                 if (sk2 < -32768 || sk2 > 32767)
492                         printk(KERN_DEBUG
493                                "isdn_audio: dtmf goertzel overflow, sk2=%d\n", sk2);
494                 result[k] =
495                     ((sk * sk) >> AMP_BITS) -
496                     ((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) +
497                     ((sk2 * sk2) >> AMP_BITS);
498         }
499         skb_queue_tail(&info->dtmf_queue, skb);
500         isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
501 }
502
503 void
504 isdn_audio_eval_dtmf(modem_info * info)
505 {
506         struct sk_buff *skb;
507         int *result;
508         dtmf_state *s;
509         int silence;
510         int i;
511         int di;
512         int ch;
513         int grp[2];
514         char what;
515         char *p;
516         int thresh;
517
518         while ((skb = skb_dequeue(&info->dtmf_queue))) {
519                 result = (int *) skb->data;
520                 s = info->dtmf_state;
521                 grp[LOGRP] = grp[HIGRP] = -1;
522                 silence = 0;
523                 thresh = 0;
524                 for (i = 0; i < NCOEFF; i++) {
525                         if (result[i] > DTMF_TRESH) {
526                                 if (result[i] > thresh)
527                                         thresh = result[i];
528                         }
529                         else if (result[i] < SILENCE_TRESH)
530                                 silence++;
531                 }
532                 if (silence == NCOEFF)
533                         what = ' ';
534                 else {
535                         if (thresh > 0) {
536                                 thresh = thresh >> 4;  /* touchtones must match within 12 dB */
537                                 for (i = 0; i < NCOEFF; i++) {
538                                         if (result[i] < thresh)
539                                                 continue;  /* ignore */
540                                         /* good level found. This is allowed only one time per group */
541                                         if (i < NCOEFF / 2) {
542                                                 /* lowgroup*/
543                                                 if (grp[LOGRP] >= 0) {
544                                                         // Bad. Another tone found. */
545                                                         grp[LOGRP] = -1;
546                                                         break;
547                                                 }
548                                                 else
549                                                         grp[LOGRP] = i;
550                                         }
551                                         else { /* higroup */
552                                                 if (grp[HIGRP] >= 0) { // Bad. Another tone found. */
553                                                         grp[HIGRP] = -1;
554                                                         break;
555                                                 }
556                                                 else
557                                                         grp[HIGRP] = i - NCOEFF/2;
558                                         }
559                                 }
560                                 if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {
561                                         what = dtmf_matrix[grp[LOGRP]][grp[HIGRP]];
562                                         if (s->last != ' ' && s->last != '.')
563                                                 s->last = what; /* min. 1 non-DTMF between DTMF */
564                                 } else
565                                         what = '.';
566                         }
567                         else
568                                 what = '.';
569                 }
570                 if ((what != s->last) && (what != ' ') && (what != '.')) {
571                         printk(KERN_DEBUG "dtmf: tt='%c'\n", what);
572                         p = skb->data;
573                         *p++ = 0x10;
574                         *p = what;
575                         skb_trim(skb, 2);
576                         ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
577                         ISDN_AUDIO_SKB_LOCK(skb) = 0;
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                         /* Schedule dequeuing */
583                         if ((dev->modempoll) && (info->rcvsched))
584                                 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
585                         wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
586                 } else
587                         kfree_skb(skb);
588                 s->last = what;
589         }
590 }
591
592 /*
593  * Decode DTMF tones, queue result in separate sk_buf for
594  * later examination.
595  * Parameters:
596  *   s    = pointer to state-struct.
597  *   buf  = input audio data
598  *   len  = size of audio data.
599  *   fmt  = audio data format (0 = ulaw, 1 = alaw)
600  */
601 void
602 isdn_audio_calc_dtmf(modem_info * info, unsigned char *buf, int len, int fmt)
603 {
604         dtmf_state *s = info->dtmf_state;
605         int i;
606         int c;
607
608         while (len) {
609                 c = DTMF_NPOINTS - s->idx;
610                 if (c > len)
611                         c = len;
612                 if (c <= 0)
613                         break;
614                 for (i = 0; i < c; i++) {
615                         if (fmt)
616                                 s->buf[s->idx++] =
617                                     isdn_audio_alaw_to_s16[*buf++] >> (15 - AMP_BITS);
618                         else
619                                 s->buf[s->idx++] =
620                                     isdn_audio_ulaw_to_s16[*buf++] >> (15 - AMP_BITS);
621                 }
622                 if (s->idx == DTMF_NPOINTS) {
623                         isdn_audio_goertzel(s->buf, info);
624                         s->idx = 0;
625                 }
626                 len -= c;
627         }
628 }
629
630 silence_state *
631 isdn_audio_silence_init(silence_state * s)
632 {
633         if (!s)
634                 s = (silence_state *) kmalloc(sizeof(silence_state), GFP_ATOMIC);
635         if (s) {
636                 s->idx = 0;
637                 s->state = 0;
638         }
639         return s;
640 }
641
642 void
643 isdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt)
644 {
645         silence_state *s = info->silence_state;
646         int i;
647         signed char c;
648
649         if (!info->emu.vpar[1]) return;
650
651         for (i = 0; i < len; i++) {
652                 if (fmt)
653                     c = isdn_audio_alaw_to_ulaw[*buf++];
654                         else
655                     c = *buf++;
656
657                 if (c > 0) c -= 128;
658                 c = abs(c);
659
660                 if (c > (info->emu.vpar[1] * 4)) { 
661                         s->idx = 0;
662                         s->state = 1; 
663                 } else {
664                         if (s->idx < 210000) s->idx++; 
665                 }
666         }
667 }
668
669 void
670 isdn_audio_put_dle_code(modem_info * info, u_char code)
671 {
672         struct sk_buff *skb;
673         int di;
674         int ch;
675         char *p;
676
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;
683         }
684         p = (char *) skb_put(skb, 2);
685         p[0] = 0x10;
686         p[1] = code;
687         ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
688         ISDN_AUDIO_SKB_LOCK(skb) = 0;
689         di = info->isdn_driver;
690         ch = info->isdn_channel;
691         __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
692         dev->drv[di]->rcvcount[ch] += 2;
693         /* Schedule dequeuing */
694         if ((dev->modempoll) && (info->rcvsched))
695                 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
696         wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
697 }
698
699 void
700 isdn_audio_eval_silence(modem_info * info)
701 {
702         silence_state *s = info->silence_state;
703         char what;
704
705         what = ' ';
706
707         if (s->idx > (info->emu.vpar[2] * 800)) { 
708                 s->idx = 0;
709                 if (!s->state) {        /* silence from beginning of rec */ 
710                         what = 's';
711                 } else {
712                         what = 'q';
713                 }
714         }
715                 if ((what == 's') || (what == 'q')) {
716                         printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
717                                 (what=='s') ? "silence":"quiet");
718                         isdn_audio_put_dle_code(info, what);
719                 } 
720 }