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