1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <linux/isdn.h>
15#include "isdn_audio.h"
16#include "isdn_common.h"
17
18char *isdn_audio_revision = "$Revision: 1.1.4.1 $";
19
20
21
22
23
24
25static 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
62static 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
99static 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
136static 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
173#define DTMF_TRESH 4000
174#define SILENCE_TRESH 200
175#define AMP_BITS 9
176#define LOGRP 0
177#define HIGRP 1
178
179
180
181
182static int cos2pik[NCOEFF] =
183{
184 55813, 53604, 51193, 48591, 38114, 33057, 25889, 18332
185};
186
187static 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
195static inline void
196isdn_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
215void
216isdn_audio_ulaw2alaw(unsigned char *buff, unsigned long len)
217{
218 isdn_audio_tlookup(isdn_audio_ulaw_to_alaw, buff, len);
219}
220
221void
222isdn_audio_alaw2ulaw(unsigned char *buff, unsigned long len)
223{
224 isdn_audio_tlookup(isdn_audio_alaw_to_ulaw, buff, len);
225}
226
227
228
229
230
231
232
233
234
235#define ZEROTRAP
236#undef ZEROTRAP
237#define BIAS 0x84
238#define CLIP 32635
239
240static unsigned char
241isdn_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
268 sign = (sample >> 8) & 0x80;
269 if (sign != 0)
270 sample = -sample;
271 if (sample > CLIP)
272 sample = CLIP;
273
274
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
281 if (ulawbyte == 0)
282 ulawbyte = 0x02;
283#endif
284 return (ulawbyte);
285}
286
287
288static 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
295static int bitmask[9] =
296{
297 0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
298};
299
300static int
301isdn_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
313static void
314isdn_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
327adpcm_state *
328isdn_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
342dtmf_state *
343isdn_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
356
357
358
359int
360isdn_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
394int
395isdn_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
404int
405isdn_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
451
452
453
454
455
456static void
457isdn_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
483 sk >>= 1;
484 sk2 >>= 1;
485
486
487
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
503void
504isdn_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 unsigned long flags;
514 int grp[2];
515 char what;
516 char *p;
517 int thresh;
518
519 while ((skb = skb_dequeue(&info->dtmf_queue))) {
520 result = (int *) skb->data;
521 s = info->dtmf_state;
522 grp[LOGRP] = grp[HIGRP] = -1;
523 silence = 0;
524 thresh = 0;
525 for (i = 0; i < NCOEFF; i++) {
526 if (result[i] > DTMF_TRESH) {
527 if (result[i] > thresh)
528 thresh = result[i];
529 }
530 else if (result[i] < SILENCE_TRESH)
531 silence++;
532 }
533 if (silence == NCOEFF)
534 what = ' ';
535 else {
536 if (thresh > 0) {
537 thresh = thresh >> 4;
538 for (i = 0; i < NCOEFF; i++) {
539 if (result[i] < thresh)
540 continue;
541
542 if (i < NCOEFF / 2) {
543
544 if (grp[LOGRP] >= 0) {
545
546 grp[LOGRP] = -1;
547 break;
548 }
549 else
550 grp[LOGRP] = i;
551 }
552 else {
553 if (grp[HIGRP] >= 0) {
554 grp[HIGRP] = -1;
555 break;
556 }
557 else
558 grp[HIGRP] = i - NCOEFF/2;
559 }
560 }
561 if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {
562 what = dtmf_matrix[grp[LOGRP]][grp[HIGRP]];
563 if (s->last != ' ' && s->last != '.')
564 s->last = what;
565 } else
566 what = '.';
567 }
568 else
569 what = '.';
570 }
571 if ((what != s->last) && (what != ' ') && (what != '.')) {
572 printk(KERN_DEBUG "dtmf: tt='%c'\n", what);
573 p = skb->data;
574 *p++ = 0x10;
575 *p = what;
576 skb_trim(skb, 2);
577 if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {
578 printk(KERN_WARNING
579 "isdn_audio: insufficient skb_headroom, dropping\n");
580 kfree_skb(skb);
581 return;
582 }
583 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
584 ISDN_AUDIO_SKB_LOCK(skb) = 0;
585 save_flags(flags);
586 cli();
587 di = info->isdn_driver;
588 ch = info->isdn_channel;
589 __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
590 dev->drv[di]->rcvcount[ch] += 2;
591 restore_flags(flags);
592
593 if ((dev->modempoll) && (info->rcvsched))
594 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
595 wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
596 } else
597 kfree_skb(skb);
598 s->last = what;
599 }
600}
601
602
603
604
605
606
607
608
609
610
611void
612isdn_audio_calc_dtmf(modem_info * info, unsigned char *buf, int len, int fmt)
613{
614 dtmf_state *s = info->dtmf_state;
615 int i;
616 int c;
617
618 while (len) {
619 c = DTMF_NPOINTS - s->idx;
620 if (c > len)
621 c = len;
622 if (c <= 0)
623 break;
624 for (i = 0; i < c; i++) {
625 if (fmt)
626 s->buf[s->idx++] =
627 isdn_audio_alaw_to_s16[*buf++] >> (15 - AMP_BITS);
628 else
629 s->buf[s->idx++] =
630 isdn_audio_ulaw_to_s16[*buf++] >> (15 - AMP_BITS);
631 }
632 if (s->idx == DTMF_NPOINTS) {
633 isdn_audio_goertzel(s->buf, info);
634 s->idx = 0;
635 }
636 len -= c;
637 }
638}
639
640silence_state *
641isdn_audio_silence_init(silence_state * s)
642{
643 if (!s)
644 s = (silence_state *) kmalloc(sizeof(silence_state), GFP_ATOMIC);
645 if (s) {
646 s->idx = 0;
647 s->state = 0;
648 }
649 return s;
650}
651
652void
653isdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt)
654{
655 silence_state *s = info->silence_state;
656 int i;
657 signed char c;
658
659 if (!info->emu.vpar[1]) return;
660
661 for (i = 0; i < len; i++) {
662 if (fmt)
663 c = isdn_audio_alaw_to_ulaw[*buf++];
664 else
665 c = *buf++;
666
667 if (c > 0) c -= 128;
668 c = abs(c);
669
670 if (c > (info->emu.vpar[1] * 4)) {
671 s->idx = 0;
672 s->state = 1;
673 } else {
674 if (s->idx < 210000) s->idx++;
675 }
676 }
677}
678
679void
680isdn_audio_put_dle_code(modem_info * info, u_char code)
681{
682 struct sk_buff *skb;
683 unsigned long flags;
684 int di;
685 int ch;
686 char *p;
687
688 skb = dev_alloc_skb(2);
689 if (!skb) {
690 printk(KERN_WARNING
691 "isdn_audio: Could not alloc skb for ttyI%d\n",
692 info->line);
693 return;
694 }
695 p = (char *) skb_put(skb, 2);
696 p[0] = 0x10;
697 p[1] = code;
698 if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {
699 printk(KERN_WARNING
700 "isdn_audio: insufficient skb_headroom, dropping\n");
701 kfree_skb(skb);
702 return;
703 }
704 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
705 ISDN_AUDIO_SKB_LOCK(skb) = 0;
706 save_flags(flags);
707 cli();
708 di = info->isdn_driver;
709 ch = info->isdn_channel;
710 __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
711 dev->drv[di]->rcvcount[ch] += 2;
712 restore_flags(flags);
713
714 if ((dev->modempoll) && (info->rcvsched))
715 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
716 wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
717}
718
719void
720isdn_audio_eval_silence(modem_info * info)
721{
722 silence_state *s = info->silence_state;
723 char what;
724
725 what = ' ';
726
727 if (s->idx > (info->emu.vpar[2] * 800)) {
728 s->idx = 0;
729 if (!s->state) {
730 what = 's';
731 } else {
732 what = 'q';
733 }
734 }
735 if ((what == 's') || (what == 'q')) {
736 printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
737 (what=='s') ? "silence":"quiet");
738 isdn_audio_put_dle_code(info, what);
739 }
740}
741