blob: 1dd2da0044c3046ce2849910b74ede2d4fcf191d [file] [log] [blame]
Guido van Rossumb66efa01992-06-01 16:01:24 +00001/***********************************************************
Guido van Rossumf0476351992-06-03 17:07:06 +00002Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The
Guido van Rossumb66efa01992-06-01 16:01:24 +00003Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* audioopmodele - Module to detect peak values in arrays */
26
27#ifdef sun
28#define signed
29#endif
30
31#include "allobjects.h"
32#include "modsupport.h"
33
34/* Code shamelessly stealen from sox,
35** (c) Craig Reese, Joe Campbell and Jeff Poskanzer 1989 */
36
37#define MINLIN -32768
38#define MAXLIN 32767
39#define LINCLIP(x) do { if ( x < MINLIN ) x = MINLIN ; else if ( x > MAXLIN ) x = MAXLIN; } while ( 0 )
40
41unsigned char st_linear_to_ulaw( /* int sample */ );
42
43/*
44** This macro converts from ulaw to 16 bit linear, faster.
45**
46** Jef Poskanzer
47** 23 October 1989
48**
49** Input: 8 bit ulaw sample
50** Output: signed 16 bit linear sample
51*/
52#define st_ulaw_to_linear(ulawbyte) ulaw_table[ulawbyte]
53
54static int ulaw_table[256] = {
55 -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
56 -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
57 -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
58 -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316,
59 -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
60 -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
61 -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
62 -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
63 -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
64 -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
65 -876, -844, -812, -780, -748, -716, -684, -652,
66 -620, -588, -556, -524, -492, -460, -428, -396,
67 -372, -356, -340, -324, -308, -292, -276, -260,
68 -244, -228, -212, -196, -180, -164, -148, -132,
69 -120, -112, -104, -96, -88, -80, -72, -64,
70 -56, -48, -40, -32, -24, -16, -8, 0,
71 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
72 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
73 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
74 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
75 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
76 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
77 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
78 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
79 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
80 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
81 876, 844, 812, 780, 748, 716, 684, 652,
82 620, 588, 556, 524, 492, 460, 428, 396,
83 372, 356, 340, 324, 308, 292, 276, 260,
84 244, 228, 212, 196, 180, 164, 148, 132,
85 120, 112, 104, 96, 88, 80, 72, 64,
86 56, 48, 40, 32, 24, 16, 8, 0 };
87
88#define ZEROTRAP /* turn on the trap as per the MIL-STD */
89#define BIAS 0x84 /* define the add-in bias for 16 bit samples */
90#define CLIP 32635
91
92unsigned char
93st_linear_to_ulaw( sample )
94int sample;
95 {
96 static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
97 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
98 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
99 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
100 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
101 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
102 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
103 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
104 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
105 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
106 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
107 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
108 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
109 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
110 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
111 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
112 int sign, exponent, mantissa;
113 unsigned char ulawbyte;
114
115 /* Get the sample into sign-magnitude. */
116 sign = (sample >> 8) & 0x80; /* set aside the sign */
117 if ( sign != 0 ) sample = -sample; /* get magnitude */
118 if ( sample > CLIP ) sample = CLIP; /* clip the magnitude */
119
120 /* Convert from 16 bit linear to ulaw. */
121 sample = sample + BIAS;
122 exponent = exp_lut[( sample >> 7 ) & 0xFF];
123 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
124 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
125#ifdef ZEROTRAP
126 if ( ulawbyte == 0 ) ulawbyte = 0x02; /* optional CCITT trap */
127#endif
128
129 return ulawbyte;
130 }
131/* End of code taken from sox */
132
133#define CHARP(cp, i) ((signed char *)(cp+i))
134#define SHORTP(cp, i) ((short *)(cp+i))
135#define LONGP(cp, i) ((long *)(cp+i))
136
137
138
139static object *AudioopError;
140
141static object *
142audioop_getsample(self, args)
143 object *self;
144 object *args;
145{
146 signed char *cp;
147 int len, size, val;
148 int i;
149
150 if ( !getargs(args, "(s#ii)", &cp, &len, &size, &i) )
151 return 0;
152 if ( size != 1 && size != 2 && size != 4 ) {
153 err_setstr(AudioopError, "Size should be 1, 2 or 4");
154 return 0;
155 }
156 if ( i < 0 || i >= len/size ) {
157 err_setstr(AudioopError, "Index out of range");
158 return 0;
159 }
160 if ( size == 1 ) val = (int)*CHARP(cp, i);
161 else if ( size == 2 ) val = (int)*SHORTP(cp, i*2);
162 else if ( size == 4 ) val = (int)*LONGP(cp, i*4);
163 return newintobject(val);
164}
165
166static object *
167audioop_max(self, args)
168 object *self;
169 object *args;
170{
171 signed char *cp;
172 int len, size, val;
173 int i;
174 int max = 0;
175
176 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
177 return 0;
178 if ( size != 1 && size != 2 && size != 4 ) {
179 err_setstr(AudioopError, "Size should be 1, 2 or 4");
180 return 0;
181 }
182 for ( i=0; i<len; i+= size) {
183 if ( size == 1 ) val = (int)*CHARP(cp, i);
184 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
185 else if ( size == 4 ) val = (int)*LONGP(cp, i);
186 if ( val < 0 ) val = (-val);
187 if ( val > max ) max = val;
188 }
189 return newintobject(max);
190}
191
192static object *
193audioop_avg(self, args)
194 object *self;
195 object *args;
196{
197 signed char *cp;
198 int len, size, val;
199 int i;
200 float avg = 0.0;
201
202 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
203 return 0;
204 if ( size != 1 && size != 2 && size != 4 ) {
205 err_setstr(AudioopError, "Size should be 1, 2 or 4");
206 return 0;
207 }
208 for ( i=0; i<len; i+= size) {
209 if ( size == 1 ) val = (int)*CHARP(cp, i);
210 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
211 else if ( size == 4 ) val = (int)*LONGP(cp, i);
212 avg += val;
213 }
214 if ( len == 0 )
215 val = 0;
216 else
217 val = (int)(avg / (float)(len/size));
218 return newintobject(val);
219}
220
221static object *
222audioop_cross(self, args)
223 object *self;
224 object *args;
225{
226 signed char *cp;
227 int len, size, val;
228 int i;
229 int cross, prevval, ncross;
230
231 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
232 return 0;
233 if ( size != 1 && size != 2 && size != 4 ) {
234 err_setstr(AudioopError, "Size should be 1, 2 or 4");
235 return 0;
236 }
237 ncross = -1;
238 prevval = 17; /* Anything <> 0,1 */
239 for ( i=0; i<len; i+= size) {
240 if ( size == 1 ) val = ((int)*CHARP(cp, i)) >> 7;
241 else if ( size == 2 ) val = ((int)*SHORTP(cp, i)) >> 15;
242 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 31;
243 val = val & 1;
244 if ( val != prevval ) ncross++;
245 prevval = val;
246 }
247 return newintobject(ncross);
248}
249
250static object *
251audioop_mul(self, args)
252 object *self;
253 object *args;
254{
255 signed char *cp, *ncp;
256 int len, size, val;
257 double factor, fval, maxval;
258 object *rv;
259 int i;
260
261 if ( !getargs(args, "(s#id)", &cp, &len, &size, &factor ) )
262 return 0;
263
264 if ( size == 1 ) maxval = (double) 0x7f;
265 else if ( size == 2 ) maxval = (double) 0x7fff;
266 else if ( size == 4 ) maxval = (double) 0x7fffffff;
267 else {
268 err_setstr(AudioopError, "Size should be 1, 2 or 4");
269 return 0;
270 }
271
272 rv = newsizedstringobject(NULL, len);
273 if ( rv == 0 )
274 return 0;
275 ncp = (signed char *)getstringvalue(rv);
276
277
278 for ( i=0; i < len; i += size ) {
279 if ( size == 1 ) val = (int)*CHARP(cp, i);
280 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
281 else if ( size == 4 ) val = (int)*LONGP(cp, i);
282 fval = (double)val*factor;
283 if ( fval > maxval ) fval = maxval;
284 else if ( fval < -maxval ) fval = -maxval;
285 val = (int)fval;
286 if ( size == 1 ) *CHARP(ncp, i) = (signed char)val;
287 else if ( size == 2 ) *SHORTP(ncp, i) = (short)val;
288 else if ( size == 4 ) *LONGP(ncp, i) = (long)val;
289 }
290 return rv;
291}
292
293static object *
294audioop_tomono(self, args)
295 object *self;
296 object *args;
297{
298 signed char *cp, *ncp;
299 int len, size, val1, val2;
300 double fac1, fac2, fval, maxval;
301 object *rv;
302 int i;
303
304 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
305 return 0;
306
307 if ( size == 1 ) maxval = (double) 0x7f;
308 else if ( size == 2 ) maxval = (double) 0x7fff;
309 else if ( size == 4 ) maxval = (double) 0x7fffffff;
310 else {
311 err_setstr(AudioopError, "Size should be 1, 2 or 4");
312 return 0;
313 }
314
315 rv = newsizedstringobject(NULL, len/2);
316 if ( rv == 0 )
317 return 0;
318 ncp = (signed char *)getstringvalue(rv);
319
320
321 for ( i=0; i < len; i += size*2 ) {
322 if ( size == 1 ) val1 = (int)*CHARP(cp, i);
323 else if ( size == 2 ) val1 = (int)*SHORTP(cp, i);
324 else if ( size == 4 ) val1 = (int)*LONGP(cp, i);
325 if ( size == 1 ) val2 = (int)*CHARP(cp, i+1);
326 else if ( size == 2 ) val2 = (int)*SHORTP(cp, i+2);
327 else if ( size == 4 ) val2 = (int)*LONGP(cp, i+4);
328 fval = (double)val1*fac1 + (double)val2*fac2;
329 if ( fval > maxval ) fval = maxval;
330 else if ( fval < -maxval ) fval = -maxval;
331 val1 = (int)fval;
332 if ( size == 1 ) *CHARP(ncp, i/2) = (signed char)val1;
333 else if ( size == 2 ) *SHORTP(ncp, i/2) = (short)val1;
334 else if ( size == 4 ) *LONGP(ncp, i/2)= (long)val1;
335 }
336 return rv;
337}
338
339static object *
340audioop_tostereo(self, args)
341 object *self;
342 object *args;
343{
344 signed char *cp, *ncp;
345 int len, size, val1, val2, val;
346 double fac1, fac2, fval, maxval;
347 object *rv;
348 int i;
349
350 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
351 return 0;
352
353 if ( size == 1 ) maxval = (double) 0x7f;
354 else if ( size == 2 ) maxval = (double) 0x7fff;
355 else if ( size == 4 ) maxval = (double) 0x7fffffff;
356 else {
357 err_setstr(AudioopError, "Size should be 1, 2 or 4");
358 return 0;
359 }
360
361 rv = newsizedstringobject(NULL, len*2);
362 if ( rv == 0 )
363 return 0;
364 ncp = (signed char *)getstringvalue(rv);
365
366
367 for ( i=0; i < len; i += size ) {
368 if ( size == 1 ) val = (int)*CHARP(cp, i);
369 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
370 else if ( size == 4 ) val = (int)*LONGP(cp, i);
371
372 fval = (double)val*fac1;
373 if ( fval > maxval ) fval = maxval;
374 else if ( fval < -maxval ) fval = -maxval;
375 val1 = (int)fval;
376
377 fval = (double)val*fac2;
378 if ( fval > maxval ) fval = maxval;
379 else if ( fval < -maxval ) fval = -maxval;
380 val2 = (int)fval;
381
382 if ( size == 1 ) *CHARP(ncp, i*2) = (signed char)val1;
383 else if ( size == 2 ) *SHORTP(ncp, i*2) = (short)val1;
384 else if ( size == 4 ) *LONGP(ncp, i*2) = (long)val1;
385
386 if ( size == 1 ) *CHARP(ncp, i*2+1) = (signed char)val2;
387 else if ( size == 2 ) *SHORTP(ncp, i*2+2) = (short)val2;
388 else if ( size == 4 ) *LONGP(ncp, i*2+4) = (long)val2;
389 }
390 return rv;
391}
392
393static object *
394audioop_add(self, args)
395 object *self;
396 object *args;
397{
398 signed char *cp1, *cp2, *ncp;
399 int len1, len2, size, val1, val2;
400 object *rv;
401 int i;
402
403 if ( !getargs(args, "(s#s#i)",
404 &cp1, &len1, &cp2, &len2, &size ) )
405 return 0;
406
407 if ( len1 != len2 ) {
408 err_setstr(AudioopError, "Lengths should be the same");
409 return 0;
410 }
411
412 if ( size != 1 && size != 2 && size != 4) {
413 err_setstr(AudioopError, "Size should be 1, 2 or 4");
414 return 0;
415 }
416
417 rv = newsizedstringobject(NULL, len1);
418 if ( rv == 0 )
419 return 0;
420 ncp = (signed char *)getstringvalue(rv);
421
422
423 for ( i=0; i < len1; i += size ) {
424 if ( size == 1 ) val1 = (int)*CHARP(cp1, i);
425 else if ( size == 2 ) val1 = (int)*SHORTP(cp1, i);
426 else if ( size == 4 ) val1 = (int)*LONGP(cp1, i);
427
428 if ( size == 1 ) val2 = (int)*CHARP(cp2, i);
429 else if ( size == 2 ) val2 = (int)*SHORTP(cp2, i);
430 else if ( size == 4 ) val2 = (int)*LONGP(cp2, i);
431
432 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val1+val2);
433 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val1+val2);
434 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val1+val2);
435 }
436 return rv;
437}
438
439static object *
440audioop_bias(self, args)
441 object *self;
442 object *args;
443{
444 signed char *cp, *ncp;
445 int len, size, val;
446 object *rv;
447 int i;
448 int bias;
449
450 if ( !getargs(args, "(s#ii)",
451 &cp, &len, &size , &bias) )
452 return 0;
453
454 if ( size != 1 && size != 2 && size != 4) {
455 err_setstr(AudioopError, "Size should be 1, 2 or 4");
456 return 0;
457 }
458
459 rv = newsizedstringobject(NULL, len);
460 if ( rv == 0 )
461 return 0;
462 ncp = (signed char *)getstringvalue(rv);
463
464
465 for ( i=0; i < len; i += size ) {
466 if ( size == 1 ) val = (int)*CHARP(cp, i);
467 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
468 else if ( size == 4 ) val = (int)*LONGP(cp, i);
469
470 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val+bias);
471 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val+bias);
472 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val+bias);
473 }
474 return rv;
475}
476
477static object *
478audioop_lin2ulaw(self, args)
479 object *self;
480 object *args;
481{
482 signed char *cp;
483 unsigned char *ncp;
484 int len, size, val;
485 object *rv;
486 int i;
487
488 if ( !getargs(args, "(s#i)",
489 &cp, &len, &size) )
490 return 0;
491
492 if ( size != 1 && size != 2 && size != 4) {
493 err_setstr(AudioopError, "Size should be 1, 2 or 4");
494 return 0;
495 }
496
497 rv = newsizedstringobject(NULL, len/size);
498 if ( rv == 0 )
499 return 0;
500 ncp = (unsigned char *)getstringvalue(rv);
501
502 for ( i=0; i < len; i += size ) {
503 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
504 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
505 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
506
507 *ncp++ = st_linear_to_ulaw(val);
508 }
509 return rv;
510}
511
512static object *
513audioop_ulaw2lin(self, args)
514 object *self;
515 object *args;
516{
517 unsigned char *cp;
518 unsigned char cval;
519 signed char *ncp;
520 int len, size, val;
521 object *rv;
522 int i;
523
524 if ( !getargs(args, "(s#i)",
525 &cp, &len, &size) )
526 return 0;
527
528 if ( size != 1 && size != 2 && size != 4) {
529 err_setstr(AudioopError, "Size should be 1, 2 or 4");
530 return 0;
531 }
532
533 rv = newsizedstringobject(NULL, len*size);
534 if ( rv == 0 )
535 return 0;
536 ncp = (signed char *)getstringvalue(rv);
537
538 for ( i=0; i < len*size; i += size ) {
539 cval = *cp++;
540 val = st_ulaw_to_linear(cval);
541
542 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val >> 8);
543 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val);
Guido van Rossumaad53441992-06-05 15:11:56 +0000544 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val<<16);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000545 }
546 return rv;
547}
548
549static struct methodlist audioop_methods[] = {
550 { "max", audioop_max },
551 { "avg", audioop_avg },
552 { "cross", audioop_cross },
553 { "mul", audioop_mul },
554 { "add", audioop_add },
555 { "bias", audioop_bias },
556 { "ulaw2lin", audioop_ulaw2lin },
557 { "lin2ulaw", audioop_lin2ulaw },
558 { "tomono", audioop_tomono },
559 { "tostereo", audioop_tostereo },
560 { "getsample", audioop_getsample },
561 { 0, 0 }
562};
563
564
565void
566initaudioop()
567{
568 object *m, *d;
569 m = initmodule("audioop", audioop_methods);
570 d = getmoduledict(m);
571 AudioopError = newstringobject("audioop.error");
572 if ( AudioopError == NULL || dictinsert(d,"error",AudioopError) )
573 fatal("can't define audioop.error");
574}