1/*
2 * Audio support data for mISDN_dsp.
3 *
4 * Copyright 2002/2003 by Andreas Eversberg (jolly@eversberg.eu)
5 * Rewritten by Peter
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#include <linux/delay.h>
13#include <linux/mISDNif.h>
14#include <linux/mISDNdsp.h>
15#include <linux/export.h>
16#include <linux/bitrev.h>
17#include "core.h"
18#include "dsp.h"
19
20/* ulaw[unsigned char] -> signed 16-bit */
21s32 dsp_audio_ulaw_to_s32[256];
22/* alaw[unsigned char] -> signed 16-bit */
23s32 dsp_audio_alaw_to_s32[256];
24
25s32 *dsp_audio_law_to_s32;
26EXPORT_SYMBOL(dsp_audio_law_to_s32);
27
28/* signed 16-bit -> law */
29u8 dsp_audio_s16_to_law[65536];
30EXPORT_SYMBOL(dsp_audio_s16_to_law);
31
32/* alaw -> ulaw */
33u8 dsp_audio_alaw_to_ulaw[256];
34/* ulaw -> alaw */
35static u8 dsp_audio_ulaw_to_alaw[256];
36u8 dsp_silence;
37
38
39/*****************************************************
40 * generate table for conversion of s16 to alaw/ulaw *
41 *****************************************************/
42
43#define AMI_MASK 0x55
44
45static inline unsigned char linear2alaw(short int linear)
46{
47 int mask;
48 int seg;
49 int pcm_val;
50 static int seg_end[8] = {
51 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF
52 };
53
54 pcm_val = linear;
55 if (pcm_val >= 0) {
56 /* Sign (7th) bit = 1 */
57 mask = AMI_MASK | 0x80;
58 } else {
59 /* Sign bit = 0 */
60 mask = AMI_MASK;
61 pcm_val = -pcm_val;
62 }
63
64 /* Convert the scaled magnitude to segment number. */
65 for (seg = 0; seg < 8; seg++) {
66 if (pcm_val <= seg_end[seg])
67 break;
68 }
69 /* Combine the sign, segment, and quantization bits. */
70 return ((seg << 4) |
71 ((pcm_val >> ((seg) ? (seg + 3) : 4)) & 0x0F)) ^ mask;
72}
73
74
75static inline short int alaw2linear(unsigned char alaw)
76{
77 int i;
78 int seg;
79
80 alaw ^= AMI_MASK;
81 i = ((alaw & 0x0F) << 4) + 8 /* rounding error */;
82 seg = (((int) alaw & 0x70) >> 4);
83 if (seg)
84 i = (i + 0x100) << (seg - 1);
85 return (short int) ((alaw & 0x80) ? i : -i);
86}
87
88static inline short int ulaw2linear(unsigned char ulaw)
89{
90 short mu, e, f, y;
91 static short etab[] = {0, 132, 396, 924, 1980, 4092, 8316, 16764};
92
93 mu = 255 - ulaw;
94 e = (mu & 0x70) / 16;
95 f = mu & 0x0f;
96 y = f * (1 << (e + 3));
97 y += etab[e];
98 if (mu & 0x80)
99 y = -y;
100 return y;
101}
102
103#define BIAS 0x84 /*!< define the add-in bias for 16 bit samples */
104
105static unsigned char linear2ulaw(short sample)
106{
107 static int exp_lut[256] = {
108 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
109 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
110 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
111 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
112 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
113 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
114 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
115 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
116 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
117 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
118 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
119 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
120 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
121 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
122 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
123 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
124 int sign, exponent, mantissa;
125 unsigned char ulawbyte;
126
127 /* Get the sample into sign-magnitude. */
128 sign = (sample >> 8) & 0x80; /* set aside the sign */
129 if (sign != 0)
130 sample = -sample; /* get magnitude */
131
132 /* Convert from 16 bit linear to ulaw. */
133 sample = sample + BIAS;
134 exponent = exp_lut[(sample >> 7) & 0xFF];
135 mantissa = (sample >> (exponent + 3)) & 0x0F;
136 ulawbyte = ~(sign | (exponent << 4) | mantissa);
137
138 return ulawbyte;
139}
140
141void dsp_audio_generate_law_tables(void)
142{
143 int i;
144 for (i = 0; i < 256; i++)
145 dsp_audio_alaw_to_s32[i] = alaw2linear(bitrev8((u8)i));
146
147 for (i = 0; i < 256; i++)
148 dsp_audio_ulaw_to_s32[i] = ulaw2linear(bitrev8((u8)i));
149
150 for (i = 0; i < 256; i++) {
151 dsp_audio_alaw_to_ulaw[i] =
152 linear2ulaw(sample: dsp_audio_alaw_to_s32[i]);
153 dsp_audio_ulaw_to_alaw[i] =
154 linear2alaw(linear: dsp_audio_ulaw_to_s32[i]);
155 }
156}
157
158void
159dsp_audio_generate_s2law_table(void)
160{
161 int i;
162
163 if (dsp_options & DSP_OPT_ULAW) {
164 /* generating ulaw-table */
165 for (i = -32768; i < 32768; i++) {
166 dsp_audio_s16_to_law[i & 0xffff] =
167 bitrev8(linear2ulaw(i));
168 }
169 } else {
170 /* generating alaw-table */
171 for (i = -32768; i < 32768; i++) {
172 dsp_audio_s16_to_law[i & 0xffff] =
173 bitrev8(linear2alaw(i));
174 }
175 }
176}
177
178
179/*
180 * the seven bit sample is the number of every second alaw-sample ordered by
181 * aplitude. 0x00 is negative, 0x7f is positive amplitude.
182 */
183u8 dsp_audio_seven2law[128];
184u8 dsp_audio_law2seven[256];
185
186/********************************************************************
187 * generate table for conversion law from/to 7-bit alaw-like sample *
188 ********************************************************************/
189
190void
191dsp_audio_generate_seven(void)
192{
193 int i, j, k;
194 u8 spl;
195 u8 sorted_alaw[256];
196
197 /* generate alaw table, sorted by the linear value */
198 for (i = 0; i < 256; i++) {
199 j = 0;
200 for (k = 0; k < 256; k++) {
201 if (dsp_audio_alaw_to_s32[k]
202 < dsp_audio_alaw_to_s32[i])
203 j++;
204 }
205 sorted_alaw[j] = i;
206 }
207
208 /* generate tabels */
209 for (i = 0; i < 256; i++) {
210 /* spl is the source: the law-sample (converted to alaw) */
211 spl = i;
212 if (dsp_options & DSP_OPT_ULAW)
213 spl = dsp_audio_ulaw_to_alaw[i];
214 /* find the 7-bit-sample */
215 for (j = 0; j < 256; j++) {
216 if (sorted_alaw[j] == spl)
217 break;
218 }
219 /* write 7-bit audio value */
220 dsp_audio_law2seven[i] = j >> 1;
221 }
222 for (i = 0; i < 128; i++) {
223 spl = sorted_alaw[i << 1];
224 if (dsp_options & DSP_OPT_ULAW)
225 spl = dsp_audio_alaw_to_ulaw[spl];
226 dsp_audio_seven2law[i] = spl;
227 }
228}
229
230
231/* mix 2*law -> law */
232u8 dsp_audio_mix_law[65536];
233
234/******************************************************
235 * generate mix table to mix two law samples into one *
236 ******************************************************/
237
238void
239dsp_audio_generate_mix_table(void)
240{
241 int i, j;
242 s32 sample;
243
244 i = 0;
245 while (i < 256) {
246 j = 0;
247 while (j < 256) {
248 sample = dsp_audio_law_to_s32[i];
249 sample += dsp_audio_law_to_s32[j];
250 if (sample > 32767)
251 sample = 32767;
252 if (sample < -32768)
253 sample = -32768;
254 dsp_audio_mix_law[(i << 8) | j] =
255 dsp_audio_s16_to_law[sample & 0xffff];
256 j++;
257 }
258 i++;
259 }
260}
261
262
263/*************************************
264 * generate different volume changes *
265 *************************************/
266
267static u8 dsp_audio_reduce8[256];
268static u8 dsp_audio_reduce7[256];
269static u8 dsp_audio_reduce6[256];
270static u8 dsp_audio_reduce5[256];
271static u8 dsp_audio_reduce4[256];
272static u8 dsp_audio_reduce3[256];
273static u8 dsp_audio_reduce2[256];
274static u8 dsp_audio_reduce1[256];
275static u8 dsp_audio_increase1[256];
276static u8 dsp_audio_increase2[256];
277static u8 dsp_audio_increase3[256];
278static u8 dsp_audio_increase4[256];
279static u8 dsp_audio_increase5[256];
280static u8 dsp_audio_increase6[256];
281static u8 dsp_audio_increase7[256];
282static u8 dsp_audio_increase8[256];
283
284static u8 *dsp_audio_volume_change[16] = {
285 dsp_audio_reduce8,
286 dsp_audio_reduce7,
287 dsp_audio_reduce6,
288 dsp_audio_reduce5,
289 dsp_audio_reduce4,
290 dsp_audio_reduce3,
291 dsp_audio_reduce2,
292 dsp_audio_reduce1,
293 dsp_audio_increase1,
294 dsp_audio_increase2,
295 dsp_audio_increase3,
296 dsp_audio_increase4,
297 dsp_audio_increase5,
298 dsp_audio_increase6,
299 dsp_audio_increase7,
300 dsp_audio_increase8,
301};
302
303void
304dsp_audio_generate_volume_changes(void)
305{
306 register s32 sample;
307 int i;
308 int num[] = { 110, 125, 150, 175, 200, 300, 400, 500 };
309 int denum[] = { 100, 100, 100, 100, 100, 100, 100, 100 };
310
311 i = 0;
312 while (i < 256) {
313 dsp_audio_reduce8[i] = dsp_audio_s16_to_law[
314 (dsp_audio_law_to_s32[i] * denum[7] / num[7]) & 0xffff];
315 dsp_audio_reduce7[i] = dsp_audio_s16_to_law[
316 (dsp_audio_law_to_s32[i] * denum[6] / num[6]) & 0xffff];
317 dsp_audio_reduce6[i] = dsp_audio_s16_to_law[
318 (dsp_audio_law_to_s32[i] * denum[5] / num[5]) & 0xffff];
319 dsp_audio_reduce5[i] = dsp_audio_s16_to_law[
320 (dsp_audio_law_to_s32[i] * denum[4] / num[4]) & 0xffff];
321 dsp_audio_reduce4[i] = dsp_audio_s16_to_law[
322 (dsp_audio_law_to_s32[i] * denum[3] / num[3]) & 0xffff];
323 dsp_audio_reduce3[i] = dsp_audio_s16_to_law[
324 (dsp_audio_law_to_s32[i] * denum[2] / num[2]) & 0xffff];
325 dsp_audio_reduce2[i] = dsp_audio_s16_to_law[
326 (dsp_audio_law_to_s32[i] * denum[1] / num[1]) & 0xffff];
327 dsp_audio_reduce1[i] = dsp_audio_s16_to_law[
328 (dsp_audio_law_to_s32[i] * denum[0] / num[0]) & 0xffff];
329 sample = dsp_audio_law_to_s32[i] * num[0] / denum[0];
330 if (sample < -32768)
331 sample = -32768;
332 else if (sample > 32767)
333 sample = 32767;
334 dsp_audio_increase1[i] = dsp_audio_s16_to_law[sample & 0xffff];
335 sample = dsp_audio_law_to_s32[i] * num[1] / denum[1];
336 if (sample < -32768)
337 sample = -32768;
338 else if (sample > 32767)
339 sample = 32767;
340 dsp_audio_increase2[i] = dsp_audio_s16_to_law[sample & 0xffff];
341 sample = dsp_audio_law_to_s32[i] * num[2] / denum[2];
342 if (sample < -32768)
343 sample = -32768;
344 else if (sample > 32767)
345 sample = 32767;
346 dsp_audio_increase3[i] = dsp_audio_s16_to_law[sample & 0xffff];
347 sample = dsp_audio_law_to_s32[i] * num[3] / denum[3];
348 if (sample < -32768)
349 sample = -32768;
350 else if (sample > 32767)
351 sample = 32767;
352 dsp_audio_increase4[i] = dsp_audio_s16_to_law[sample & 0xffff];
353 sample = dsp_audio_law_to_s32[i] * num[4] / denum[4];
354 if (sample < -32768)
355 sample = -32768;
356 else if (sample > 32767)
357 sample = 32767;
358 dsp_audio_increase5[i] = dsp_audio_s16_to_law[sample & 0xffff];
359 sample = dsp_audio_law_to_s32[i] * num[5] / denum[5];
360 if (sample < -32768)
361 sample = -32768;
362 else if (sample > 32767)
363 sample = 32767;
364 dsp_audio_increase6[i] = dsp_audio_s16_to_law[sample & 0xffff];
365 sample = dsp_audio_law_to_s32[i] * num[6] / denum[6];
366 if (sample < -32768)
367 sample = -32768;
368 else if (sample > 32767)
369 sample = 32767;
370 dsp_audio_increase7[i] = dsp_audio_s16_to_law[sample & 0xffff];
371 sample = dsp_audio_law_to_s32[i] * num[7] / denum[7];
372 if (sample < -32768)
373 sample = -32768;
374 else if (sample > 32767)
375 sample = 32767;
376 dsp_audio_increase8[i] = dsp_audio_s16_to_law[sample & 0xffff];
377
378 i++;
379 }
380}
381
382
383/**************************************
384 * change the volume of the given skb *
385 **************************************/
386
387/* this is a helper function for changing volume of skb. the range may be
388 * -8 to 8, which is a shift to the power of 2. 0 == no volume, 3 == volume*8
389 */
390void
391dsp_change_volume(struct sk_buff *skb, int volume)
392{
393 u8 *volume_change;
394 int i, ii;
395 u8 *p;
396 int shift;
397
398 if (volume == 0)
399 return;
400
401 /* get correct conversion table */
402 if (volume < 0) {
403 shift = volume + 8;
404 if (shift < 0)
405 shift = 0;
406 } else {
407 shift = volume + 7;
408 if (shift > 15)
409 shift = 15;
410 }
411 volume_change = dsp_audio_volume_change[shift];
412 i = 0;
413 ii = skb->len;
414 p = skb->data;
415 /* change volume */
416 while (i < ii) {
417 *p = volume_change[*p];
418 p++;
419 i++;
420 }
421}
422

source code of linux/drivers/isdn/mISDN/dsp_audio.c