[PATCH] fix semaphore handling in __unregister_chrdev_region
[linux/fpc-iii.git] / drivers / isdn / i4l / isdn_audio.c
blob5350836a4f987ee3fc428800090008032c5bcad9
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 = (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;
339 return s;
342 dtmf_state *
343 isdn_audio_dtmf_init(dtmf_state * s)
345 if (!s)
346 s = (dtmf_state *) 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_2adpcm_flush(adpcm_state * s, unsigned char *out)
397 int olen = 0;
399 if (s->nleft)
400 isdn_audio_put_bits(0, 8 - s->nleft, s, &out, &olen);
401 return olen;
405 isdn_audio_xlaw2adpcm(adpcm_state * s, int fmt, unsigned char *in,
406 unsigned char *out, int len)
408 int a = s->a;
409 int d = s->d;
410 int nbits = s->nbits;
411 int olen = 0;
413 while (len--) {
414 int e = 0,
415 nmax = 1 << (nbits - 1);
416 int sign,
417 delta;
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;
427 while (--nmax && delta > d) {
428 delta -= d;
429 e++;
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];
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;
444 s->a = a;
445 s->d = d;
446 return olen;
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.
456 static void
457 isdn_audio_goertzel(int *sample, modem_info * info)
459 int sk,
460 sk1,
461 sk2;
462 int k,
464 struct sk_buff *skb;
465 int *result;
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;
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;
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);
499 skb_queue_tail(&info->dtmf_queue, skb);
500 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
503 void
504 isdn_audio_eval_dtmf(modem_info * info)
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 int grp[2];
514 char what;
515 char *p;
516 int thresh;
518 while ((skb = skb_dequeue(&info->dtmf_queue))) {
519 result = (int *) skb->data;
520 s = info->dtmf_state;
521 grp[LOGRP] = grp[HIGRP] = -1;
522 silence = 0;
523 thresh = 0;
524 for (i = 0; i < NCOEFF; i++) {
525 if (result[i] > DTMF_TRESH) {
526 if (result[i] > thresh)
527 thresh = result[i];
529 else if (result[i] < SILENCE_TRESH)
530 silence++;
532 if (silence == NCOEFF)
533 what = ' ';
534 else {
535 if (thresh > 0) {
536 thresh = thresh >> 4; /* touchtones must match within 12 dB */
537 for (i = 0; i < NCOEFF; i++) {
538 if (result[i] < thresh)
539 continue; /* ignore */
540 /* good level found. This is allowed only one time per group */
541 if (i < NCOEFF / 2) {
542 /* lowgroup*/
543 if (grp[LOGRP] >= 0) {
544 // Bad. Another tone found. */
545 grp[LOGRP] = -1;
546 break;
548 else
549 grp[LOGRP] = i;
551 else { /* higroup */
552 if (grp[HIGRP] >= 0) { // Bad. Another tone found. */
553 grp[HIGRP] = -1;
554 break;
556 else
557 grp[HIGRP] = i - NCOEFF/2;
560 if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {
561 what = dtmf_matrix[grp[LOGRP]][grp[HIGRP]];
562 if (s->last != ' ' && s->last != '.')
563 s->last = what; /* min. 1 non-DTMF between DTMF */
564 } else
565 what = '.';
567 else
568 what = '.';
570 if ((what != s->last) && (what != ' ') && (what != '.')) {
571 printk(KERN_DEBUG "dtmf: tt='%c'\n", what);
572 p = skb->data;
573 *p++ = 0x10;
574 *p = what;
575 skb_trim(skb, 2);
576 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
577 ISDN_AUDIO_SKB_LOCK(skb) = 0;
578 di = info->isdn_driver;
579 ch = info->isdn_channel;
580 __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
581 dev->drv[di]->rcvcount[ch] += 2;
582 /* Schedule dequeuing */
583 if ((dev->modempoll) && (info->rcvsched))
584 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
585 wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
586 } else
587 kfree_skb(skb);
588 s->last = what;
593 * Decode DTMF tones, queue result in separate sk_buf for
594 * later examination.
595 * Parameters:
596 * s = pointer to state-struct.
597 * buf = input audio data
598 * len = size of audio data.
599 * fmt = audio data format (0 = ulaw, 1 = alaw)
601 void
602 isdn_audio_calc_dtmf(modem_info * info, unsigned char *buf, int len, int fmt)
604 dtmf_state *s = info->dtmf_state;
605 int i;
606 int c;
608 while (len) {
609 c = DTMF_NPOINTS - s->idx;
610 if (c > len)
611 c = len;
612 if (c <= 0)
613 break;
614 for (i = 0; i < c; i++) {
615 if (fmt)
616 s->buf[s->idx++] =
617 isdn_audio_alaw_to_s16[*buf++] >> (15 - AMP_BITS);
618 else
619 s->buf[s->idx++] =
620 isdn_audio_ulaw_to_s16[*buf++] >> (15 - AMP_BITS);
622 if (s->idx == DTMF_NPOINTS) {
623 isdn_audio_goertzel(s->buf, info);
624 s->idx = 0;
626 len -= c;
630 silence_state *
631 isdn_audio_silence_init(silence_state * s)
633 if (!s)
634 s = (silence_state *) kmalloc(sizeof(silence_state), GFP_ATOMIC);
635 if (s) {
636 s->idx = 0;
637 s->state = 0;
639 return s;
642 void
643 isdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt)
645 silence_state *s = info->silence_state;
646 int i;
647 signed char c;
649 if (!info->emu.vpar[1]) return;
651 for (i = 0; i < len; i++) {
652 if (fmt)
653 c = isdn_audio_alaw_to_ulaw[*buf++];
654 else
655 c = *buf++;
657 if (c > 0) c -= 128;
658 c = abs(c);
660 if (c > (info->emu.vpar[1] * 4)) {
661 s->idx = 0;
662 s->state = 1;
663 } else {
664 if (s->idx < 210000) s->idx++;
669 void
670 isdn_audio_put_dle_code(modem_info * info, u_char code)
672 struct sk_buff *skb;
673 int di;
674 int ch;
675 char *p;
677 skb = dev_alloc_skb(2);
678 if (!skb) {
679 printk(KERN_WARNING
680 "isdn_audio: Could not alloc skb for ttyI%d\n",
681 info->line);
682 return;
684 p = (char *) skb_put(skb, 2);
685 p[0] = 0x10;
686 p[1] = code;
687 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
688 ISDN_AUDIO_SKB_LOCK(skb) = 0;
689 di = info->isdn_driver;
690 ch = info->isdn_channel;
691 __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
692 dev->drv[di]->rcvcount[ch] += 2;
693 /* Schedule dequeuing */
694 if ((dev->modempoll) && (info->rcvsched))
695 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
696 wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
699 void
700 isdn_audio_eval_silence(modem_info * info)
702 silence_state *s = info->silence_state;
703 char what;
705 what = ' ';
707 if (s->idx > (info->emu.vpar[2] * 800)) {
708 s->idx = 0;
709 if (!s->state) { /* silence from beginning of rec */
710 what = 's';
711 } else {
712 what = 'q';
715 if ((what == 's') || (what == 'q')) {
716 printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
717 (what=='s') ? "silence":"quiet");
718 isdn_audio_put_dle_code(info, what);