1/* $Id: isdn_audio.c,v 1.1.1.1 2007/08/03 18:52:36 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
18char *isdn_audio_revision = "$Revision: 1.1.1.1 $";
19
20/*
21 * Misc. lookup-tables.
22 */
23
24/* ulaw -> signed 16-bit */
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/* alaw -> signed 16-bit */
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/* alaw -> ulaw */
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/* ulaw -> alaw */
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     /* 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 */
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 * 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
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	/* 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
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 = 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 = 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
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_xlaw2adpcm(adpcm_state * s, int fmt, unsigned char *in,
396		      unsigned char *out, int len)
397{
398	int a = s->a;
399	int d = s->d;
400	int nbits = s->nbits;
401	int olen = 0;
402
403	while (len--) {
404		int e = 0,
405		 nmax = 1 << (nbits - 1);
406		int sign,
407		 delta;
408
409		if (fmt)
410			delta = (isdn_audio_alaw_to_s16[*in++] >> 2) - a;
411		else
412			delta = (isdn_audio_ulaw_to_s16[*in++] >> 2) - a;
413		if (delta < 0) {
414			e = nmax;
415			delta = -delta;
416		}
417		while (--nmax && delta > d) {
418			delta -= d;
419			e++;
420		}
421		if (nbits == 4 && ((e & 0x0f) == 0))
422			e = 8;
423		isdn_audio_put_bits(e, nbits, s, &out, &olen);
424		sign = (e >> (nbits - 1)) ? -1 : 1;
425		e &= bitmask[nbits - 1];
426
427		a += sign * ((e << 1) + 1) * d >> 1;
428		if (d & 1)
429			a++;
430		d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
431		if (d < 5)
432			d = 5;
433	}
434	s->a = a;
435	s->d = d;
436	return olen;
437}
438
439/*
440 * Goertzel algorithm.
441 * See http://ptolemy.eecs.berkeley.edu/~pino/Ptolemy/papers/96/dtmf_ict/
442 * for more info.
443 * Result is stored into an sk_buff and queued up for later
444 * evaluation.
445 */
446static void
447isdn_audio_goertzel(int *sample, modem_info * info)
448{
449	int sk,
450	 sk1,
451	 sk2;
452	int k,
453	 n;
454	struct sk_buff *skb;
455	int *result;
456
457	skb = dev_alloc_skb(sizeof(int) * NCOEFF);
458	if (!skb) {
459		printk(KERN_WARNING
460		  "isdn_audio: Could not alloc DTMF result for ttyI%d\n",
461		       info->line);
462		return;
463	}
464	result = (int *) skb_put(skb, sizeof(int) * NCOEFF);
465	for (k = 0; k < NCOEFF; k++) {
466		sk = sk1 = sk2 = 0;
467		for (n = 0; n < DTMF_NPOINTS; n++) {
468			sk = sample[n] + ((cos2pik[k] * sk1) >> 15) - sk2;
469			sk2 = sk1;
470			sk1 = sk;
471		}
472		/* Avoid overflows */
473		sk >>= 1;
474		sk2 >>= 1;
475		/* compute |X(k)|**2 */
476		/* report overflows. This should not happen. */
477		/* Comment this out if desired */
478		if (sk < -32768 || sk > 32767)
479			printk(KERN_DEBUG
480			       "isdn_audio: dtmf goertzel overflow, sk=%d\n", sk);
481		if (sk2 < -32768 || sk2 > 32767)
482			printk(KERN_DEBUG
483			       "isdn_audio: dtmf goertzel overflow, sk2=%d\n", sk2);
484		result[k] =
485		    ((sk * sk) >> AMP_BITS) -
486		    ((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) +
487		    ((sk2 * sk2) >> AMP_BITS);
488	}
489	skb_queue_tail(&info->dtmf_queue, skb);
490	isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
491}
492
493void
494isdn_audio_eval_dtmf(modem_info * info)
495{
496	struct sk_buff *skb;
497	int *result;
498	dtmf_state *s;
499	int silence;
500	int i;
501	int di;
502	int ch;
503	int grp[2];
504	char what;
505	char *p;
506	int thresh;
507
508	while ((skb = skb_dequeue(&info->dtmf_queue))) {
509		result = (int *) skb->data;
510		s = info->dtmf_state;
511		grp[LOGRP] = grp[HIGRP] = -1;
512		silence = 0;
513		thresh = 0;
514		for (i = 0; i < NCOEFF; i++) {
515			if (result[i] > DTMF_TRESH) {
516				if (result[i] > thresh)
517					thresh = result[i];
518			}
519			else if (result[i] < SILENCE_TRESH)
520				silence++;
521		}
522		if (silence == NCOEFF)
523			what = ' ';
524		else {
525			if (thresh > 0)	{
526				thresh = thresh >> 4;  /* touchtones must match within 12 dB */
527				for (i = 0; i < NCOEFF; i++) {
528					if (result[i] < thresh)
529						continue;  /* ignore */
530					/* good level found. This is allowed only one time per group */
531					if (i < NCOEFF / 2) {
532						/* lowgroup*/
533						if (grp[LOGRP] >= 0) {
534							// Bad. Another tone found. */
535							grp[LOGRP] = -1;
536							break;
537						}
538						else
539							grp[LOGRP] = i;
540					}
541					else { /* higroup */
542						if (grp[HIGRP] >= 0) { // Bad. Another tone found. */
543							grp[HIGRP] = -1;
544							break;
545						}
546						else
547							grp[HIGRP] = i - NCOEFF/2;
548					}
549				}
550				if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {
551					what = dtmf_matrix[grp[LOGRP]][grp[HIGRP]];
552					if (s->last != ' ' && s->last != '.')
553						s->last = what;	/* min. 1 non-DTMF between DTMF */
554				} else
555					what = '.';
556			}
557			else
558				what = '.';
559		}
560		if ((what != s->last) && (what != ' ') && (what != '.')) {
561			printk(KERN_DEBUG "dtmf: tt='%c'\n", what);
562			p = skb->data;
563			*p++ = 0x10;
564			*p = what;
565			skb_trim(skb, 2);
566			ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
567			ISDN_AUDIO_SKB_LOCK(skb) = 0;
568			di = info->isdn_driver;
569			ch = info->isdn_channel;
570			__skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
571			dev->drv[di]->rcvcount[ch] += 2;
572			/* Schedule dequeuing */
573			if ((dev->modempoll) && (info->rcvsched))
574				isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
575			wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
576		} else
577			kfree_skb(skb);
578		s->last = what;
579	}
580}
581
582/*
583 * Decode DTMF tones, queue result in separate sk_buf for
584 * later examination.
585 * Parameters:
586 *   s    = pointer to state-struct.
587 *   buf  = input audio data
588 *   len  = size of audio data.
589 *   fmt  = audio data format (0 = ulaw, 1 = alaw)
590 */
591void
592isdn_audio_calc_dtmf(modem_info * info, unsigned char *buf, int len, int fmt)
593{
594	dtmf_state *s = info->dtmf_state;
595	int i;
596	int c;
597
598	while (len) {
599		c = DTMF_NPOINTS - s->idx;
600		if (c > len)
601			c = len;
602		if (c <= 0)
603			break;
604		for (i = 0; i < c; i++) {
605			if (fmt)
606				s->buf[s->idx++] =
607				    isdn_audio_alaw_to_s16[*buf++] >> (15 - AMP_BITS);
608			else
609				s->buf[s->idx++] =
610				    isdn_audio_ulaw_to_s16[*buf++] >> (15 - AMP_BITS);
611		}
612		if (s->idx == DTMF_NPOINTS) {
613			isdn_audio_goertzel(s->buf, info);
614			s->idx = 0;
615		}
616		len -= c;
617	}
618}
619
620silence_state *
621isdn_audio_silence_init(silence_state * s)
622{
623	if (!s)
624		s = kmalloc(sizeof(silence_state), GFP_ATOMIC);
625	if (s) {
626		s->idx = 0;
627		s->state = 0;
628	}
629	return s;
630}
631
632void
633isdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt)
634{
635	silence_state *s = info->silence_state;
636	int i;
637	signed char c;
638
639	if (!info->emu.vpar[1]) return;
640
641	for (i = 0; i < len; i++) {
642		if (fmt)
643		    c = isdn_audio_alaw_to_ulaw[*buf++];
644			else
645		    c = *buf++;
646
647		if (c > 0) c -= 128;
648		c = abs(c);
649
650		if (c > (info->emu.vpar[1] * 4)) {
651			s->idx = 0;
652			s->state = 1;
653		} else {
654			if (s->idx < 210000) s->idx++;
655		}
656	}
657}
658
659void
660isdn_audio_put_dle_code(modem_info * info, u_char code)
661{
662	struct sk_buff *skb;
663	int di;
664	int ch;
665	char *p;
666
667	skb = dev_alloc_skb(2);
668	if (!skb) {
669		printk(KERN_WARNING
670		  "isdn_audio: Could not alloc skb for ttyI%d\n",
671		       info->line);
672		return;
673	}
674	p = (char *) skb_put(skb, 2);
675	p[0] = 0x10;
676	p[1] = code;
677	ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
678	ISDN_AUDIO_SKB_LOCK(skb) = 0;
679	di = info->isdn_driver;
680	ch = info->isdn_channel;
681	__skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
682	dev->drv[di]->rcvcount[ch] += 2;
683	/* Schedule dequeuing */
684	if ((dev->modempoll) && (info->rcvsched))
685		isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
686	wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
687}
688
689void
690isdn_audio_eval_silence(modem_info * info)
691{
692	silence_state *s = info->silence_state;
693	char what;
694
695	what = ' ';
696
697	if (s->idx > (info->emu.vpar[2] * 800)) {
698		s->idx = 0;
699		if (!s->state) {	/* silence from beginning of rec */
700			what = 's';
701		} else {
702			what = 'q';
703		}
704	}
705		if ((what == 's') || (what == 'q')) {
706			printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
707				(what=='s') ? "silence":"quiet");
708			isdn_audio_put_dle_code(info, what);
709		}
710}
711