1 /* $Id: isdn_audio.c,v 1.1.4.1 2001/11/20 14:19:33 kai 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.4.1 $";
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
isdn_audio_tlookup(const u_char * table,u_char * buff,unsigned long n)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
isdn_audio_ulaw2alaw(unsigned char * buff,unsigned long len)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
isdn_audio_alaw2ulaw(unsigned char * buff,unsigned long len)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
isdn_audio_linear2ulaw(int sample)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
isdn_audio_get_bits(adpcm_state * s,unsigned char ** in,int * len)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
isdn_audio_put_bits(int data,int nbits,adpcm_state * s,unsigned char ** out,int * len)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 *
isdn_audio_adpcm_init(adpcm_state * s,int nbits)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 *
isdn_audio_dtmf_init(dtmf_state * s)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
isdn_audio_adpcm2xlaw(adpcm_state * s,int fmt,unsigned char * in,unsigned char * out,int len)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
isdn_audio_2adpcm_flush(adpcm_state * s,unsigned char * out)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
isdn_audio_xlaw2adpcm(adpcm_state * s,int fmt,unsigned char * in,unsigned char * out,int len)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
isdn_audio_goertzel(int * sample,modem_info * info)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
isdn_audio_eval_dtmf(modem_info * info)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 	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;  /* touchtones must match within 12 dB */
538 				for (i = 0; i < NCOEFF; i++) {
539 					if (result[i] < thresh)
540 						continue;  /* ignore */
541 					/* good level found. This is allowed only one time per group */
542 					if (i < NCOEFF / 2) {
543 						/* lowgroup*/
544 						if (grp[LOGRP] >= 0) {
545 							// Bad. Another tone found. */
546 							grp[LOGRP] = -1;
547 							break;
548 						}
549 						else
550 							grp[LOGRP] = i;
551 					}
552 					else { /* higroup */
553 						if (grp[HIGRP] >= 0) { // Bad. Another tone found. */
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;	/* min. 1 non-DTMF between DTMF */
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 			/* Schedule dequeuing */
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  * Decode DTMF tones, queue result in separate sk_buf for
604  * later examination.
605  * Parameters:
606  *   s    = pointer to state-struct.
607  *   buf  = input audio data
608  *   len  = size of audio data.
609  *   fmt  = audio data format (0 = ulaw, 1 = alaw)
610  */
611 void
isdn_audio_calc_dtmf(modem_info * info,unsigned char * buf,int len,int fmt)612 isdn_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 
640 silence_state *
isdn_audio_silence_init(silence_state * s)641 isdn_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 
652 void
isdn_audio_calc_silence(modem_info * info,unsigned char * buf,int len,int fmt)653 isdn_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 
679 void
isdn_audio_put_dle_code(modem_info * info,u_char code)680 isdn_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 	/* Schedule dequeuing */
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 
719 void
isdn_audio_eval_silence(modem_info * info)720 isdn_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) {	/* silence from beginning of rec */
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