File: /usr/src/linux/drivers/isdn/isdn_audio.c

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