Committer: Michael Beasley <mike@snafu.setup>
[mikesnafu-overlay.git] / drivers / isdn / i4l / isdn_audio.c
blobfb350c567c6ba01c768c87845ed37c70db6a79b2
1 /* $Id: isdn_audio.c,v 1.1.2.2 2004/01/12 22:37:18 keil Exp $
3 * Linux ISDN subsystem, audio conversion and compression (linklevel).
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)
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
14 #include <linux/isdn.h>
15 #include "isdn_audio.h"
16 #include "isdn_common.h"
18 char *isdn_audio_revision = "$Revision: 1.1.2.2 $";
21 * Misc. lookup-tables.
24 /* ulaw -> signed 16-bit */
25 static short isdn_audio_ulaw_to_s16[] =
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
61 /* alaw -> signed 16-bit */
62 static short isdn_audio_alaw_to_s16[] =
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
98 /* alaw -> ulaw */
99 static char isdn_audio_alaw_to_ulaw[] =
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
135 /* ulaw -> alaw */
136 static char isdn_audio_ulaw_to_alaw[] =
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
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
179 /* For DTMF recognition:
180 * 2 * cos(2 * PI * k / N) precalculated for all k
182 static int cos2pik[NCOEFF] =
184 55813, 53604, 51193, 48591, 38114, 33057, 25889, 18332
187 static char dtmf_matrix[4][4] =
189 {'1', '2', '3', 'A'},
190 {'4', '5', '6', 'B'},
191 {'7', '8', '9', 'C'},
192 {'*', '0', '#', 'D'}
195 static inline void
196 isdn_audio_tlookup(const u_char *table, u_char *buff, unsigned long n)
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
215 void
216 isdn_audio_ulaw2alaw(unsigned char *buff, unsigned long len)
218 isdn_audio_tlookup(isdn_audio_ulaw_to_alaw, buff, len);
221 void
222 isdn_audio_alaw2ulaw(unsigned char *buff, unsigned long len)
224 isdn_audio_tlookup(isdn_audio_alaw_to_ulaw, buff, len);
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
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
240 static unsigned char
241 isdn_audio_linear2ulaw(int sample)
243 static int exp_lut[256] =
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
262 int sign,
263 exponent,
264 mantissa;
265 unsigned char ulawbyte;
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 */
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);
288 static int Mx[3][8] =
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},
295 static int bitmask[9] =
297 0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
300 static int
301 isdn_audio_get_bits(adpcm_state * s, unsigned char **in, int *len)
303 while (s->nleft < s->nbits) {
304 int d = *((*in)++);
305 (*len)--;
306 s->word = (s->word << 8) | d;
307 s->nleft += 8;
309 s->nleft -= s->nbits;
310 return (s->word >> s->nleft) & bitmask[s->nbits];
313 static void
314 isdn_audio_put_bits(int data, int nbits, adpcm_state * s,
315 unsigned char **out, int *len)
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;
327 adpcm_state *
328 isdn_audio_adpcm_init(adpcm_state * s, int nbits)
330 if (!s)
331 s = 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;
339 return s;
342 dtmf_state *
343 isdn_audio_dtmf_init(dtmf_state * s)
345 if (!s)
346 s = kmalloc(sizeof(dtmf_state), GFP_ATOMIC);
347 if (s) {
348 s->idx = 0;
349 s->last = ' ';
351 return s;
355 * Decompression of adpcm data to a/u-law
360 isdn_audio_adpcm2xlaw(adpcm_state * s, int fmt, unsigned char *in,
361 unsigned char *out, int len)
363 int a = s->a;
364 int d = s->d;
365 int nbits = s->nbits;
366 int olen = 0;
368 while (len) {
369 int e = isdn_audio_get_bits(s, &in, &len);
370 int sign;
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;
389 s->a = a;
390 s->d = d;
391 return olen;
395 isdn_audio_xlaw2adpcm(adpcm_state * s, int fmt, unsigned char *in,
396 unsigned char *out, int len)
398 int a = s->a;
399 int d = s->d;
400 int nbits = s->nbits;
401 int olen = 0;
403 while (len--) {
404 int e = 0,
405 nmax = 1 << (nbits - 1);
406 int sign,
407 delta;
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;
417 while (--nmax && delta > d) {
418 delta -= d;
419 e++;
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];
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;
434 s->a = a;
435 s->d = d;
436 return olen;
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.
446 static void
447 isdn_audio_goertzel(int *sample, modem_info * info)
449 int sk,
450 sk1,
451 sk2;
452 int k,
454 struct sk_buff *skb;
455 int *result;
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;
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;
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);
489 skb_queue_tail(&info->dtmf_queue, skb);
490 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
493 void
494 isdn_audio_eval_dtmf(modem_info * info)
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;
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];
519 else if (result[i] < SILENCE_TRESH)
520 silence++;
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;
538 else
539 grp[LOGRP] = i;
541 else { /* higroup */
542 if (grp[HIGRP] >= 0) { // Bad. Another tone found. */
543 grp[HIGRP] = -1;
544 break;
546 else
547 grp[HIGRP] = i - NCOEFF/2;
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 = '.';
557 else
558 what = '.';
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;
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)
591 void
592 isdn_audio_calc_dtmf(modem_info * info, unsigned char *buf, int len, int fmt)
594 dtmf_state *s = info->dtmf_state;
595 int i;
596 int c;
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);
612 if (s->idx == DTMF_NPOINTS) {
613 isdn_audio_goertzel(s->buf, info);
614 s->idx = 0;
616 len -= c;
620 silence_state *
621 isdn_audio_silence_init(silence_state * s)
623 if (!s)
624 s = kmalloc(sizeof(silence_state), GFP_ATOMIC);
625 if (s) {
626 s->idx = 0;
627 s->state = 0;
629 return s;
632 void
633 isdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt)
635 silence_state *s = info->silence_state;
636 int i;
637 signed char c;
639 if (!info->emu.vpar[1]) return;
641 for (i = 0; i < len; i++) {
642 if (fmt)
643 c = isdn_audio_alaw_to_ulaw[*buf++];
644 else
645 c = *buf++;
647 if (c > 0) c -= 128;
648 c = abs(c);
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++;
659 void
660 isdn_audio_put_dle_code(modem_info * info, u_char code)
662 struct sk_buff *skb;
663 int di;
664 int ch;
665 char *p;
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;
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]);
689 void
690 isdn_audio_eval_silence(modem_info * info)
692 silence_state *s = info->silence_state;
693 char what;
695 what = ' ';
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';
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);