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 <linux/slab.h>
16#include "isdn_audio.h"
17#include "isdn_common.h"
18
19char *isdn_audio_revision = "$Revision: 1.1.2.2 $";
20
21/*
22 * Misc. lookup-tables.
23 */
24
25/* ulaw -> signed 16-bit */
26static short isdn_audio_ulaw_to_s16[] =
27{
28	0x8284, 0x8684, 0x8a84, 0x8e84, 0x9284, 0x9684, 0x9a84, 0x9e84,
29	0xa284, 0xa684, 0xaa84, 0xae84, 0xb284, 0xb684, 0xba84, 0xbe84,
30	0xc184, 0xc384, 0xc584, 0xc784, 0xc984, 0xcb84, 0xcd84, 0xcf84,
31	0xd184, 0xd384, 0xd584, 0xd784, 0xd984, 0xdb84, 0xdd84, 0xdf84,
32	0xe104, 0xe204, 0xe304, 0xe404, 0xe504, 0xe604, 0xe704, 0xe804,
33	0xe904, 0xea04, 0xeb04, 0xec04, 0xed04, 0xee04, 0xef04, 0xf004,
34	0xf0c4, 0xf144, 0xf1c4, 0xf244, 0xf2c4, 0xf344, 0xf3c4, 0xf444,
35	0xf4c4, 0xf544, 0xf5c4, 0xf644, 0xf6c4, 0xf744, 0xf7c4, 0xf844,
36	0xf8a4, 0xf8e4, 0xf924, 0xf964, 0xf9a4, 0xf9e4, 0xfa24, 0xfa64,
37	0xfaa4, 0xfae4, 0xfb24, 0xfb64, 0xfba4, 0xfbe4, 0xfc24, 0xfc64,
38	0xfc94, 0xfcb4, 0xfcd4, 0xfcf4, 0xfd14, 0xfd34, 0xfd54, 0xfd74,
39	0xfd94, 0xfdb4, 0xfdd4, 0xfdf4, 0xfe14, 0xfe34, 0xfe54, 0xfe74,
40	0xfe8c, 0xfe9c, 0xfeac, 0xfebc, 0xfecc, 0xfedc, 0xfeec, 0xfefc,
41	0xff0c, 0xff1c, 0xff2c, 0xff3c, 0xff4c, 0xff5c, 0xff6c, 0xff7c,
42	0xff88, 0xff90, 0xff98, 0xffa0, 0xffa8, 0xffb0, 0xffb8, 0xffc0,
43	0xffc8, 0xffd0, 0xffd8, 0xffe0, 0xffe8, 0xfff0, 0xfff8, 0x0000,
44	0x7d7c, 0x797c, 0x757c, 0x717c, 0x6d7c, 0x697c, 0x657c, 0x617c,
45	0x5d7c, 0x597c, 0x557c, 0x517c, 0x4d7c, 0x497c, 0x457c, 0x417c,
46	0x3e7c, 0x3c7c, 0x3a7c, 0x387c, 0x367c, 0x347c, 0x327c, 0x307c,
47	0x2e7c, 0x2c7c, 0x2a7c, 0x287c, 0x267c, 0x247c, 0x227c, 0x207c,
48	0x1efc, 0x1dfc, 0x1cfc, 0x1bfc, 0x1afc, 0x19fc, 0x18fc, 0x17fc,
49	0x16fc, 0x15fc, 0x14fc, 0x13fc, 0x12fc, 0x11fc, 0x10fc, 0x0ffc,
50	0x0f3c, 0x0ebc, 0x0e3c, 0x0dbc, 0x0d3c, 0x0cbc, 0x0c3c, 0x0bbc,
51	0x0b3c, 0x0abc, 0x0a3c, 0x09bc, 0x093c, 0x08bc, 0x083c, 0x07bc,
52	0x075c, 0x071c, 0x06dc, 0x069c, 0x065c, 0x061c, 0x05dc, 0x059c,
53	0x055c, 0x051c, 0x04dc, 0x049c, 0x045c, 0x041c, 0x03dc, 0x039c,
54	0x036c, 0x034c, 0x032c, 0x030c, 0x02ec, 0x02cc, 0x02ac, 0x028c,
55	0x026c, 0x024c, 0x022c, 0x020c, 0x01ec, 0x01cc, 0x01ac, 0x018c,
56	0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
57	0x00f4, 0x00e4, 0x00d4, 0x00c4, 0x00b4, 0x00a4, 0x0094, 0x0084,
58	0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
59	0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000
60};
61
62/* alaw -> signed 16-bit */
63static short isdn_audio_alaw_to_s16[] =
64{
65	0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4,
66	0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74,
67	0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4,
68	0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64,
69	0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4,
70	0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4,
71	0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4,
72	0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4,
73	0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64,
74	0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34,
75	0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844,
76	0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24,
77	0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64,
78	0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4,
79	0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964,
80	0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4,
81	0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24,
82	0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94,
83	0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924,
84	0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94,
85	0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24,
86	0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14,
87	0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24,
88	0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14,
89	0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4,
90	0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54,
91	0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4,
92	0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64,
93	0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4,
94	0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4,
95	0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4,
96	0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4
97};
98
99/* alaw -> ulaw */
100static char isdn_audio_alaw_to_ulaw[] =
101{
102	0xab, 0x2b, 0xe3, 0x63, 0x8b, 0x0b, 0xc9, 0x49,
103	0xba, 0x3a, 0xf6, 0x76, 0x9b, 0x1b, 0xd7, 0x57,
104	0xa3, 0x23, 0xdd, 0x5d, 0x83, 0x03, 0xc1, 0x41,
105	0xb2, 0x32, 0xeb, 0x6b, 0x93, 0x13, 0xcf, 0x4f,
106	0xaf, 0x2f, 0xe7, 0x67, 0x8f, 0x0f, 0xcd, 0x4d,
107	0xbe, 0x3e, 0xfe, 0x7e, 0x9f, 0x1f, 0xdb, 0x5b,
108	0xa7, 0x27, 0xdf, 0x5f, 0x87, 0x07, 0xc5, 0x45,
109	0xb6, 0x36, 0xef, 0x6f, 0x97, 0x17, 0xd3, 0x53,
110	0xa9, 0x29, 0xe1, 0x61, 0x89, 0x09, 0xc7, 0x47,
111	0xb8, 0x38, 0xf2, 0x72, 0x99, 0x19, 0xd5, 0x55,
112	0xa1, 0x21, 0xdc, 0x5c, 0x81, 0x01, 0xbf, 0x3f,
113	0xb0, 0x30, 0xe9, 0x69, 0x91, 0x11, 0xce, 0x4e,
114	0xad, 0x2d, 0xe5, 0x65, 0x8d, 0x0d, 0xcb, 0x4b,
115	0xbc, 0x3c, 0xfa, 0x7a, 0x9d, 0x1d, 0xd9, 0x59,
116	0xa5, 0x25, 0xde, 0x5e, 0x85, 0x05, 0xc3, 0x43,
117	0xb4, 0x34, 0xed, 0x6d, 0x95, 0x15, 0xd1, 0x51,
118	0xac, 0x2c, 0xe4, 0x64, 0x8c, 0x0c, 0xca, 0x4a,
119	0xbb, 0x3b, 0xf8, 0x78, 0x9c, 0x1c, 0xd8, 0x58,
120	0xa4, 0x24, 0xde, 0x5e, 0x84, 0x04, 0xc2, 0x42,
121	0xb3, 0x33, 0xec, 0x6c, 0x94, 0x14, 0xd0, 0x50,
122	0xb0, 0x30, 0xe8, 0x68, 0x90, 0x10, 0xce, 0x4e,
123	0xbf, 0x3f, 0xfe, 0x7e, 0xa0, 0x20, 0xdc, 0x5c,
124	0xa8, 0x28, 0xe0, 0x60, 0x88, 0x08, 0xc6, 0x46,
125	0xb7, 0x37, 0xf0, 0x70, 0x98, 0x18, 0xd4, 0x54,
126	0xaa, 0x2a, 0xe2, 0x62, 0x8a, 0x0a, 0xc8, 0x48,
127	0xb9, 0x39, 0xf4, 0x74, 0x9a, 0x1a, 0xd6, 0x56,
128	0xa2, 0x22, 0xdd, 0x5d, 0x82, 0x02, 0xc0, 0x40,
129	0xb1, 0x31, 0xea, 0x6a, 0x92, 0x12, 0xcf, 0x4f,
130	0xae, 0x2e, 0xe6, 0x66, 0x8e, 0x0e, 0xcc, 0x4c,
131	0xbd, 0x3d, 0xfc, 0x7c, 0x9e, 0x1e, 0xda, 0x5a,
132	0xa6, 0x26, 0xdf, 0x5f, 0x86, 0x06, 0xc4, 0x44,
133	0xb5, 0x35, 0xee, 0x6e, 0x96, 0x16, 0xd2, 0x52
134};
135
136/* ulaw -> alaw */
137static char isdn_audio_ulaw_to_alaw[] =
138{
139	0xab, 0x55, 0xd5, 0x15, 0x95, 0x75, 0xf5, 0x35,
140	0xb5, 0x45, 0xc5, 0x05, 0x85, 0x65, 0xe5, 0x25,
141	0xa5, 0x5d, 0xdd, 0x1d, 0x9d, 0x7d, 0xfd, 0x3d,
142	0xbd, 0x4d, 0xcd, 0x0d, 0x8d, 0x6d, 0xed, 0x2d,
143	0xad, 0x51, 0xd1, 0x11, 0x91, 0x71, 0xf1, 0x31,
144	0xb1, 0x41, 0xc1, 0x01, 0x81, 0x61, 0xe1, 0x21,
145	0x59, 0xd9, 0x19, 0x99, 0x79, 0xf9, 0x39, 0xb9,
146	0x49, 0xc9, 0x09, 0x89, 0x69, 0xe9, 0x29, 0xa9,
147	0xd7, 0x17, 0x97, 0x77, 0xf7, 0x37, 0xb7, 0x47,
148	0xc7, 0x07, 0x87, 0x67, 0xe7, 0x27, 0xa7, 0xdf,
149	0x9f, 0x7f, 0xff, 0x3f, 0xbf, 0x4f, 0xcf, 0x0f,
150	0x8f, 0x6f, 0xef, 0x2f, 0x53, 0x13, 0x73, 0x33,
151	0xb3, 0x43, 0xc3, 0x03, 0x83, 0x63, 0xe3, 0x23,
152	0xa3, 0x5b, 0xdb, 0x1b, 0x9b, 0x7b, 0xfb, 0x3b,
153	0xbb, 0xbb, 0x4b, 0x4b, 0xcb, 0xcb, 0x0b, 0x0b,
154	0x8b, 0x8b, 0x6b, 0x6b, 0xeb, 0xeb, 0x2b, 0x2b,
155	0xab, 0x54, 0xd4, 0x14, 0x94, 0x74, 0xf4, 0x34,
156	0xb4, 0x44, 0xc4, 0x04, 0x84, 0x64, 0xe4, 0x24,
157	0xa4, 0x5c, 0xdc, 0x1c, 0x9c, 0x7c, 0xfc, 0x3c,
158	0xbc, 0x4c, 0xcc, 0x0c, 0x8c, 0x6c, 0xec, 0x2c,
159	0xac, 0x50, 0xd0, 0x10, 0x90, 0x70, 0xf0, 0x30,
160	0xb0, 0x40, 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x20,
161	0x58, 0xd8, 0x18, 0x98, 0x78, 0xf8, 0x38, 0xb8,
162	0x48, 0xc8, 0x08, 0x88, 0x68, 0xe8, 0x28, 0xa8,
163	0xd6, 0x16, 0x96, 0x76, 0xf6, 0x36, 0xb6, 0x46,
164	0xc6, 0x06, 0x86, 0x66, 0xe6, 0x26, 0xa6, 0xde,
165	0x9e, 0x7e, 0xfe, 0x3e, 0xbe, 0x4e, 0xce, 0x0e,
166	0x8e, 0x6e, 0xee, 0x2e, 0x52, 0x12, 0x72, 0x32,
167	0xb2, 0x42, 0xc2, 0x02, 0x82, 0x62, 0xe2, 0x22,
168	0xa2, 0x5a, 0xda, 0x1a, 0x9a, 0x7a, 0xfa, 0x3a,
169	0xba, 0xba, 0x4a, 0x4a, 0xca, 0xca, 0x0a, 0x0a,
170	0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a
171};
172
173#define NCOEFF            8     /* number of frequencies to be analyzed       */
174#define DTMF_TRESH     4000     /* above this is dtmf                         */
175#define SILENCE_TRESH   200     /* below this is silence                      */
176#define AMP_BITS          9     /* bits per sample, reduced to avoid overflow */
177#define LOGRP             0
178#define HIGRP             1
179
180/* For DTMF recognition:
181 * 2 * cos(2 * PI * k / N) precalculated for all k
182 */
183static int cos2pik[NCOEFF] =
184{
185	55813, 53604, 51193, 48591, 38114, 33057, 25889, 18332
186};
187
188static char dtmf_matrix[4][4] =
189{
190	{'1', '2', '3', 'A'},
191	{'4', '5', '6', 'B'},
192	{'7', '8', '9', 'C'},
193	{'*', '0', '#', 'D'}
194};
195
196static inline void
197isdn_audio_tlookup(const u_char *table, u_char *buff, unsigned long n)
198{
199#ifdef __i386__
200	unsigned long d0, d1, d2, d3;
201	__asm__ __volatile__(
202		"cld\n"
203		"1:\tlodsb\n\t"
204		"xlatb\n\t"
205		"stosb\n\t"
206		"loop 1b\n\t"
207		:	"=&b"(d0), "=&c"(d1), "=&D"(d2), "=&S"(d3)
208		:	"0"((long) table), "1"(n), "2"((long) buff), "3"((long) buff)
209		:	"memory", "ax");
210#else
211	while (n--)
212		*buff = table[*(unsigned char *)buff], buff++;
213#endif
214}
215
216void
217isdn_audio_ulaw2alaw(unsigned char *buff, unsigned long len)
218{
219	isdn_audio_tlookup(isdn_audio_ulaw_to_alaw, buff, len);
220}
221
222void
223isdn_audio_alaw2ulaw(unsigned char *buff, unsigned long len)
224{
225	isdn_audio_tlookup(isdn_audio_alaw_to_ulaw, buff, len);
226}
227
228/*
229 * linear <-> adpcm conversion stuff
230 * Most parts from the mgetty-package.
231 * (C) by Gert Doering and Klaus Weidner
232 * Used by permission of Gert Doering
233 */
234
235
236#define ZEROTRAP                /* turn on the trap as per the MIL-STD */
237#undef ZEROTRAP
238#define BIAS 0x84               /* define the add-in bias for 16 bit samples */
239#define CLIP 32635
240
241static unsigned char
242isdn_audio_linear2ulaw(int sample)
243{
244	static int exp_lut[256] =
245		{
246			0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
247			4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
248			5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
249			5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
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			6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
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			7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
262		};
263	int sign,
264		exponent,
265		mantissa;
266	unsigned char ulawbyte;
267
268	/* Get the sample into sign-magnitude. */
269	sign = (sample >> 8) & 0x80;	/* set aside the sign  */
270	if (sign != 0)
271		sample = -sample;	/* get magnitude       */
272	if (sample > CLIP)
273		sample = CLIP;  /* clip the magnitude  */
274
275	/* Convert from 16 bit linear to ulaw. */
276	sample = sample + BIAS;
277	exponent = exp_lut[(sample >> 7) & 0xFF];
278	mantissa = (sample >> (exponent + 3)) & 0x0F;
279	ulawbyte = ~(sign | (exponent << 4) | mantissa);
280#ifdef ZEROTRAP
281	/* optional CCITT trap */
282	if (ulawbyte == 0)
283		ulawbyte = 0x02;
284#endif
285	return (ulawbyte);
286}
287
288
289static int Mx[3][8] =
290{
291	{0x3800, 0x5600, 0, 0, 0, 0, 0, 0},
292	{0x399a, 0x3a9f, 0x4d14, 0x6607, 0, 0, 0, 0},
293	{0x3556, 0x3556, 0x399A, 0x3A9F, 0x4200, 0x4D14, 0x6607, 0x6607},
294};
295
296static int bitmask[9] =
297{
298	0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
299};
300
301static int
302isdn_audio_get_bits(adpcm_state *s, unsigned char **in, int *len)
303{
304	while (s->nleft < s->nbits) {
305		int d = *((*in)++);
306		(*len)--;
307		s->word = (s->word << 8) | d;
308		s->nleft += 8;
309	}
310	s->nleft -= s->nbits;
311	return (s->word >> s->nleft) & bitmask[s->nbits];
312}
313
314static void
315isdn_audio_put_bits(int data, int nbits, adpcm_state *s,
316		    unsigned char **out, int *len)
317{
318	s->word = (s->word << nbits) | (data & bitmask[nbits]);
319	s->nleft += nbits;
320	while (s->nleft >= 8) {
321		int d = (s->word >> (s->nleft - 8));
322		*(out[0]++) = d & 255;
323		(*len)++;
324		s->nleft -= 8;
325	}
326}
327
328adpcm_state *
329isdn_audio_adpcm_init(adpcm_state *s, int nbits)
330{
331	if (!s)
332		s = kmalloc(sizeof(adpcm_state), GFP_ATOMIC);
333	if (s) {
334		s->a = 0;
335		s->d = 5;
336		s->word = 0;
337		s->nleft = 0;
338		s->nbits = nbits;
339	}
340	return s;
341}
342
343dtmf_state *
344isdn_audio_dtmf_init(dtmf_state *s)
345{
346	if (!s)
347		s = kmalloc(sizeof(dtmf_state), GFP_ATOMIC);
348	if (s) {
349		s->idx = 0;
350		s->last = ' ';
351	}
352	return s;
353}
354
355/*
356 * Decompression of adpcm data to a/u-law
357 *
358 */
359
360int
361isdn_audio_adpcm2xlaw(adpcm_state *s, int fmt, unsigned char *in,
362		      unsigned char *out, int len)
363{
364	int a = s->a;
365	int d = s->d;
366	int nbits = s->nbits;
367	int olen = 0;
368
369	while (len) {
370		int e = isdn_audio_get_bits(s, &in, &len);
371		int sign;
372
373		if (nbits == 4 && e == 0)
374			d = 4;
375		sign = (e >> (nbits - 1)) ? -1 : 1;
376		e &= bitmask[nbits - 1];
377		a += sign * ((e << 1) + 1) * d >> 1;
378		if (d & 1)
379			a++;
380		if (fmt)
381			*out++ = isdn_audio_ulaw_to_alaw[
382				isdn_audio_linear2ulaw(a << 2)];
383		else
384			*out++ = isdn_audio_linear2ulaw(a << 2);
385		olen++;
386		d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
387		if (d < 5)
388			d = 5;
389	}
390	s->a = a;
391	s->d = d;
392	return olen;
393}
394
395int
396isdn_audio_xlaw2adpcm(adpcm_state *s, int fmt, unsigned char *in,
397		      unsigned char *out, int len)
398{
399	int a = s->a;
400	int d = s->d;
401	int nbits = s->nbits;
402	int olen = 0;
403
404	while (len--) {
405		int e = 0,
406			nmax = 1 << (nbits - 1);
407		int sign,
408			delta;
409
410		if (fmt)
411			delta = (isdn_audio_alaw_to_s16[*in++] >> 2) - a;
412		else
413			delta = (isdn_audio_ulaw_to_s16[*in++] >> 2) - a;
414		if (delta < 0) {
415			e = nmax;
416			delta = -delta;
417		}
418		while (--nmax && delta > d) {
419			delta -= d;
420			e++;
421		}
422		if (nbits == 4 && ((e & 0x0f) == 0))
423			e = 8;
424		isdn_audio_put_bits(e, nbits, s, &out, &olen);
425		sign = (e >> (nbits - 1)) ? -1 : 1;
426		e &= bitmask[nbits - 1];
427
428		a += sign * ((e << 1) + 1) * d >> 1;
429		if (d & 1)
430			a++;
431		d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
432		if (d < 5)
433			d = 5;
434	}
435	s->a = a;
436	s->d = d;
437	return olen;
438}
439
440/*
441 * Goertzel algorithm.
442 * See http://ptolemy.eecs.berkeley.edu/papers/96/dtmf_ict/
443 * for more info.
444 * Result is stored into an sk_buff and queued up for later
445 * evaluation.
446 */
447static void
448isdn_audio_goertzel(int *sample, modem_info *info)
449{
450	int sk,
451		sk1,
452		sk2;
453	int k,
454		n;
455	struct sk_buff *skb;
456	int *result;
457
458	skb = dev_alloc_skb(sizeof(int) * NCOEFF);
459	if (!skb) {
460		printk(KERN_WARNING
461		       "isdn_audio: Could not alloc DTMF result for ttyI%d\n",
462		       info->line);
463		return;
464	}
465	result = (int *) skb_put(skb, sizeof(int) * NCOEFF);
466	for (k = 0; k < NCOEFF; k++) {
467		sk = sk1 = sk2 = 0;
468		for (n = 0; n < DTMF_NPOINTS; n++) {
469			sk = sample[n] + ((cos2pik[k] * sk1) >> 15) - sk2;
470			sk2 = sk1;
471			sk1 = sk;
472		}
473		/* Avoid overflows */
474		sk >>= 1;
475		sk2 >>= 1;
476		/* compute |X(k)|**2 */
477		/* report overflows. This should not happen. */
478		/* Comment this out if desired */
479		if (sk < -32768 || sk > 32767)
480			printk(KERN_DEBUG
481			       "isdn_audio: dtmf goertzel overflow, sk=%d\n", sk);
482		if (sk2 < -32768 || sk2 > 32767)
483			printk(KERN_DEBUG
484			       "isdn_audio: dtmf goertzel overflow, sk2=%d\n", sk2);
485		result[k] =
486			((sk * sk) >> AMP_BITS) -
487			((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) +
488			((sk2 * sk2) >> AMP_BITS);
489	}
490	skb_queue_tail(&info->dtmf_queue, skb);
491	isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
492}
493
494void
495isdn_audio_eval_dtmf(modem_info *info)
496{
497	struct sk_buff *skb;
498	int *result;
499	dtmf_state *s;
500	int silence;
501	int i;
502	int di;
503	int ch;
504	int grp[2];
505	char what;
506	char *p;
507	int thresh;
508
509	while ((skb = skb_dequeue(&info->dtmf_queue))) {
510		result = (int *) skb->data;
511		s = info->dtmf_state;
512		grp[LOGRP] = grp[HIGRP] = -1;
513		silence = 0;
514		thresh = 0;
515		for (i = 0; i < NCOEFF; i++) {
516			if (result[i] > DTMF_TRESH) {
517				if (result[i] > thresh)
518					thresh = result[i];
519			}
520			else if (result[i] < SILENCE_TRESH)
521				silence++;
522		}
523		if (silence == NCOEFF)
524			what = ' ';
525		else {
526			if (thresh > 0)	{
527				thresh = thresh >> 4;  /* touchtones must match within 12 dB */
528				for (i = 0; i < NCOEFF; i++) {
529					if (result[i] < thresh)
530						continue;  /* ignore */
531					/* good level found. This is allowed only one time per group */
532					if (i < NCOEFF / 2) {
533						/* lowgroup*/
534						if (grp[LOGRP] >= 0) {
535							// Bad. Another tone found. */
536							grp[LOGRP] = -1;
537							break;
538						}
539						else
540							grp[LOGRP] = i;
541					}
542					else { /* higroup */
543						if (grp[HIGRP] >= 0) { // Bad. Another tone found. */
544							grp[HIGRP] = -1;
545							break;
546						}
547						else
548							grp[HIGRP] = i - NCOEFF/2;
549					}
550				}
551				if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {
552					what = dtmf_matrix[grp[LOGRP]][grp[HIGRP]];
553					if (s->last != ' ' && s->last != '.')
554						s->last = what;	/* min. 1 non-DTMF between DTMF */
555				} else
556					what = '.';
557			}
558			else
559				what = '.';
560		}
561		if ((what != s->last) && (what != ' ') && (what != '.')) {
562			printk(KERN_DEBUG "dtmf: tt='%c'\n", what);
563			p = skb->data;
564			*p++ = 0x10;
565			*p = what;
566			skb_trim(skb, 2);
567			ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
568			ISDN_AUDIO_SKB_LOCK(skb) = 0;
569			di = info->isdn_driver;
570			ch = info->isdn_channel;
571			__skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
572			dev->drv[di]->rcvcount[ch] += 2;
573			/* Schedule dequeuing */
574			if ((dev->modempoll) && (info->rcvsched))
575				isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
576			wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
577		} else
578			kfree_skb(skb);
579		s->last = what;
580	}
581}
582
583/*
584 * Decode DTMF tones, queue result in separate sk_buf for
585 * later examination.
586 * Parameters:
587 *   s    = pointer to state-struct.
588 *   buf  = input audio data
589 *   len  = size of audio data.
590 *   fmt  = audio data format (0 = ulaw, 1 = alaw)
591 */
592void
593isdn_audio_calc_dtmf(modem_info *info, unsigned char *buf, int len, int fmt)
594{
595	dtmf_state *s = info->dtmf_state;
596	int i;
597	int c;
598
599	while (len) {
600		c = DTMF_NPOINTS - s->idx;
601		if (c > len)
602			c = len;
603		if (c <= 0)
604			break;
605		for (i = 0; i < c; i++) {
606			if (fmt)
607				s->buf[s->idx++] =
608					isdn_audio_alaw_to_s16[*buf++] >> (15 - AMP_BITS);
609			else
610				s->buf[s->idx++] =
611					isdn_audio_ulaw_to_s16[*buf++] >> (15 - AMP_BITS);
612		}
613		if (s->idx == DTMF_NPOINTS) {
614			isdn_audio_goertzel(s->buf, info);
615			s->idx = 0;
616		}
617		len -= c;
618	}
619}
620
621silence_state *
622isdn_audio_silence_init(silence_state *s)
623{
624	if (!s)
625		s = kmalloc(sizeof(silence_state), GFP_ATOMIC);
626	if (s) {
627		s->idx = 0;
628		s->state = 0;
629	}
630	return s;
631}
632
633void
634isdn_audio_calc_silence(modem_info *info, unsigned char *buf, int len, int fmt)
635{
636	silence_state *s = info->silence_state;
637	int i;
638	signed char c;
639
640	if (!info->emu.vpar[1]) return;
641
642	for (i = 0; i < len; i++) {
643		if (fmt)
644			c = isdn_audio_alaw_to_ulaw[*buf++];
645		else
646			c = *buf++;
647
648		if (c > 0) c -= 128;
649		c = abs(c);
650
651		if (c > (info->emu.vpar[1] * 4)) {
652			s->idx = 0;
653			s->state = 1;
654		} else {
655			if (s->idx < 210000) s->idx++;
656		}
657	}
658}
659
660void
661isdn_audio_put_dle_code(modem_info *info, u_char code)
662{
663	struct sk_buff *skb;
664	int di;
665	int ch;
666	char *p;
667
668	skb = dev_alloc_skb(2);
669	if (!skb) {
670		printk(KERN_WARNING
671		       "isdn_audio: Could not alloc skb for ttyI%d\n",
672		       info->line);
673		return;
674	}
675	p = (char *) skb_put(skb, 2);
676	p[0] = 0x10;
677	p[1] = code;
678	ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
679	ISDN_AUDIO_SKB_LOCK(skb) = 0;
680	di = info->isdn_driver;
681	ch = info->isdn_channel;
682	__skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
683	dev->drv[di]->rcvcount[ch] += 2;
684	/* Schedule dequeuing */
685	if ((dev->modempoll) && (info->rcvsched))
686		isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
687	wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
688}
689
690void
691isdn_audio_eval_silence(modem_info *info)
692{
693	silence_state *s = info->silence_state;
694	char what;
695
696	what = ' ';
697
698	if (s->idx > (info->emu.vpar[2] * 800)) {
699		s->idx = 0;
700		if (!s->state) {	/* silence from beginning of rec */
701			what = 's';
702		} else {
703			what = 'q';
704		}
705	}
706	if ((what == 's') || (what == 'q')) {
707		printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
708		       (what == 's') ? "silence" : "quiet");
709		isdn_audio_put_dle_code(info, what);
710	}
711}
712