Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/isdn/i4l/isdn_audio.c
15111 views
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 ([email protected])
6
* DTMF code (c) 1996 by Christian Mock ([email protected])
7
* Silence detection (c) 1998 by Armin Schindler ([email protected])
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
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
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
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
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
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
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 *
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 *
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
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
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
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 = (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
494
void
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
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 *
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
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
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 = (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
690
void
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
713