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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [isdn/] [isdn_audio.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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