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 
19 char *isdn_audio_revision = "$Revision: 1.1.2.2 $";
20 
21 /*
22  * Misc. lookup-tables.
23  */
24 
25 /* ulaw -> signed 16-bit */
26 static 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 */
63 static 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 */
100 static 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 */
137 static 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  */
183 static int cos2pik[NCOEFF] =
184 {
185 	55813, 53604, 51193, 48591, 38114, 33057, 25889, 18332
186 };
187 
188 static 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 
196 static inline void
isdn_audio_tlookup(const u_char * table,u_char * buff,unsigned long n)197 isdn_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 
216 void
isdn_audio_ulaw2alaw(unsigned char * buff,unsigned long len)217 isdn_audio_ulaw2alaw(unsigned char *buff, unsigned long len)
218 {
219 	isdn_audio_tlookup(isdn_audio_ulaw_to_alaw, buff, len);
220 }
221 
222 void
isdn_audio_alaw2ulaw(unsigned char * buff,unsigned long len)223 isdn_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 
241 static unsigned char
isdn_audio_linear2ulaw(int sample)242 isdn_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 
289 static 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 
296 static int bitmask[9] =
297 {
298 	0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
299 };
300 
301 static int
isdn_audio_get_bits(adpcm_state * s,unsigned char ** in,int * len)302 isdn_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 
314 static void
isdn_audio_put_bits(int data,int nbits,adpcm_state * s,unsigned char ** out,int * len)315 isdn_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 
328 adpcm_state *
isdn_audio_adpcm_init(adpcm_state * s,int nbits)329 isdn_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 
343 dtmf_state *
isdn_audio_dtmf_init(dtmf_state * s)344 isdn_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 
360 int
isdn_audio_adpcm2xlaw(adpcm_state * s,int fmt,unsigned char * in,unsigned char * out,int len)361 isdn_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 
395 int
isdn_audio_xlaw2adpcm(adpcm_state * s,int fmt,unsigned char * in,unsigned char * out,int len)396 isdn_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  */
447 static void
isdn_audio_goertzel(int * sample,modem_info * info)448 isdn_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 = 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 
494 void
isdn_audio_eval_dtmf(modem_info * info)495 isdn_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  */
592 void
isdn_audio_calc_dtmf(modem_info * info,unsigned char * buf,int len,int fmt)593 isdn_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 
621 silence_state *
isdn_audio_silence_init(silence_state * s)622 isdn_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 
633 void
isdn_audio_calc_silence(modem_info * info,unsigned char * buf,int len,int fmt)634 isdn_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 
660 void
isdn_audio_put_dle_code(modem_info * info,u_char code)661 isdn_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 = 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 
690 void
isdn_audio_eval_silence(modem_info * info)691 isdn_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