OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [isdn/] [isdn_audio.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.