blob: 301b4940077f1b44bf9b931b6b87dc75f0fe8c0f [file] [log] [blame]
Guido van Rossumb66efa01992-06-01 16:01:24 +00001/***********************************************************
Guido van Rossum34679b71993-01-26 13:33:44 +00002Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3Amsterdam, The Netherlands.
Guido van Rossumb66efa01992-06-01 16:01:24 +00004
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
Jack Jansene1b4d7c1992-08-24 14:36:31 +000031#include <math.h>
32
Guido van Rossumb66efa01992-06-01 16:01:24 +000033#include "allobjects.h"
34#include "modsupport.h"
35
36/* Code shamelessly stealen from sox,
37** (c) Craig Reese, Joe Campbell and Jeff Poskanzer 1989 */
38
39#define MINLIN -32768
40#define MAXLIN 32767
41#define LINCLIP(x) do { if ( x < MINLIN ) x = MINLIN ; else if ( x > MAXLIN ) x = MAXLIN; } while ( 0 )
42
43unsigned char st_linear_to_ulaw( /* int sample */ );
44
45/*
46** This macro converts from ulaw to 16 bit linear, faster.
47**
48** Jef Poskanzer
49** 23 October 1989
50**
51** Input: 8 bit ulaw sample
52** Output: signed 16 bit linear sample
53*/
54#define st_ulaw_to_linear(ulawbyte) ulaw_table[ulawbyte]
55
56static int ulaw_table[256] = {
57 -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
58 -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
59 -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
60 -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316,
61 -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
62 -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
63 -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
64 -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
65 -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
66 -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
67 -876, -844, -812, -780, -748, -716, -684, -652,
68 -620, -588, -556, -524, -492, -460, -428, -396,
69 -372, -356, -340, -324, -308, -292, -276, -260,
70 -244, -228, -212, -196, -180, -164, -148, -132,
71 -120, -112, -104, -96, -88, -80, -72, -64,
72 -56, -48, -40, -32, -24, -16, -8, 0,
73 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
74 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
75 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
76 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
77 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
78 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
79 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
80 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
81 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
82 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
83 876, 844, 812, 780, 748, 716, 684, 652,
84 620, 588, 556, 524, 492, 460, 428, 396,
85 372, 356, 340, 324, 308, 292, 276, 260,
86 244, 228, 212, 196, 180, 164, 148, 132,
87 120, 112, 104, 96, 88, 80, 72, 64,
88 56, 48, 40, 32, 24, 16, 8, 0 };
89
90#define ZEROTRAP /* turn on the trap as per the MIL-STD */
91#define BIAS 0x84 /* define the add-in bias for 16 bit samples */
92#define CLIP 32635
93
94unsigned char
95st_linear_to_ulaw( sample )
96int sample;
97 {
98 static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
99 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
100 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
101 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
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 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
105 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
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 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
113 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
114 int sign, exponent, mantissa;
115 unsigned char ulawbyte;
116
117 /* Get the sample into sign-magnitude. */
118 sign = (sample >> 8) & 0x80; /* set aside the sign */
119 if ( sign != 0 ) sample = -sample; /* get magnitude */
120 if ( sample > CLIP ) sample = CLIP; /* clip the magnitude */
121
122 /* Convert from 16 bit linear to ulaw. */
123 sample = sample + BIAS;
124 exponent = exp_lut[( sample >> 7 ) & 0xFF];
125 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
126 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
127#ifdef ZEROTRAP
128 if ( ulawbyte == 0 ) ulawbyte = 0x02; /* optional CCITT trap */
129#endif
130
131 return ulawbyte;
132 }
133/* End of code taken from sox */
134
Guido van Rossumb64e6351992-07-06 14:21:56 +0000135/* ADPCM-3 step variation table */
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000136static float newstep[5] = { 0.8, 0.9, 1.0, 1.75, 1.75 };
137
Guido van Rossumb64e6351992-07-06 14:21:56 +0000138/* Intel ADPCM step variation table */
139static int indexTable[16] = {
140 -1, -1, -1, -1, 2, 4, 6, 8,
141 -1, -1, -1, -1, 2, 4, 6, 8,
142};
143
144static int stepsizeTable[89] = {
145 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
146 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
147 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
148 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
149 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
150 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
151 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
152 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
153 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
154};
155
Guido van Rossumb66efa01992-06-01 16:01:24 +0000156#define CHARP(cp, i) ((signed char *)(cp+i))
157#define SHORTP(cp, i) ((short *)(cp+i))
158#define LONGP(cp, i) ((long *)(cp+i))
159
160
161
162static object *AudioopError;
163
164static object *
165audioop_getsample(self, args)
166 object *self;
167 object *args;
168{
169 signed char *cp;
170 int len, size, val;
171 int i;
172
173 if ( !getargs(args, "(s#ii)", &cp, &len, &size, &i) )
174 return 0;
175 if ( size != 1 && size != 2 && size != 4 ) {
176 err_setstr(AudioopError, "Size should be 1, 2 or 4");
177 return 0;
178 }
179 if ( i < 0 || i >= len/size ) {
180 err_setstr(AudioopError, "Index out of range");
181 return 0;
182 }
183 if ( size == 1 ) val = (int)*CHARP(cp, i);
184 else if ( size == 2 ) val = (int)*SHORTP(cp, i*2);
185 else if ( size == 4 ) val = (int)*LONGP(cp, i*4);
186 return newintobject(val);
187}
188
189static object *
190audioop_max(self, args)
191 object *self;
192 object *args;
193{
194 signed char *cp;
195 int len, size, val;
196 int i;
197 int max = 0;
198
199 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
200 return 0;
201 if ( size != 1 && size != 2 && size != 4 ) {
202 err_setstr(AudioopError, "Size should be 1, 2 or 4");
203 return 0;
204 }
205 for ( i=0; i<len; i+= size) {
206 if ( size == 1 ) val = (int)*CHARP(cp, i);
207 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
208 else if ( size == 4 ) val = (int)*LONGP(cp, i);
209 if ( val < 0 ) val = (-val);
210 if ( val > max ) max = val;
211 }
212 return newintobject(max);
213}
214
215static object *
216audioop_avg(self, args)
217 object *self;
218 object *args;
219{
220 signed char *cp;
221 int len, size, val;
222 int i;
223 float avg = 0.0;
224
225 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
226 return 0;
227 if ( size != 1 && size != 2 && size != 4 ) {
228 err_setstr(AudioopError, "Size should be 1, 2 or 4");
229 return 0;
230 }
231 for ( i=0; i<len; i+= size) {
232 if ( size == 1 ) val = (int)*CHARP(cp, i);
233 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
234 else if ( size == 4 ) val = (int)*LONGP(cp, i);
235 avg += val;
236 }
237 if ( len == 0 )
238 val = 0;
239 else
240 val = (int)(avg / (float)(len/size));
241 return newintobject(val);
242}
243
244static object *
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000245audioop_rms(self, args)
246 object *self;
247 object *args;
248{
249 signed char *cp;
250 int len, size, val;
251 int i;
252 float sum_squares = 0.0;
253
254 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
255 return 0;
256 if ( size != 1 && size != 2 && size != 4 ) {
257 err_setstr(AudioopError, "Size should be 1, 2 or 4");
258 return 0;
259 }
260 for ( i=0; i<len; i+= size) {
261 if ( size == 1 ) val = (int)*CHARP(cp, i);
262 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
263 else if ( size == 4 ) val = (int)*LONGP(cp, i);
264 sum_squares += (float)val*(float)val;
265 }
266 if ( len == 0 )
267 val = 0;
268 else
269 val = (int)sqrt(sum_squares / (float)(len/size));
270 return newintobject(val);
271}
272
273static object *
274audioop_avgpp(self, args)
275 object *self;
276 object *args;
277{
278 signed char *cp;
279 int len, size, val, prevval, prevextremevalid = 0, prevextreme;
280 int i;
281 float avg = 0.0;
282 int diff, prevdiff, extremediff, nextreme = 0;
283
284 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
285 return 0;
286 if ( size != 1 && size != 2 && size != 4 ) {
287 err_setstr(AudioopError, "Size should be 1, 2 or 4");
288 return 0;
289 }
290 /* Compute first delta value ahead. Also automatically makes us
291 ** skip the first extreme value
292 */
293 if ( size == 1 ) prevval = (int)*CHARP(cp, 0);
294 else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
295 else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
296 if ( size == 1 ) val = (int)*CHARP(cp, size);
297 else if ( size == 2 ) val = (int)*SHORTP(cp, size);
298 else if ( size == 4 ) val = (int)*LONGP(cp, size);
299 prevdiff = val - prevval;
300
301 for ( i=size; i<len; i+= size) {
302 if ( size == 1 ) val = (int)*CHARP(cp, i);
303 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
304 else if ( size == 4 ) val = (int)*LONGP(cp, i);
305 diff = val - prevval;
306 if ( diff*prevdiff < 0 ) {
307 /* Derivative changed sign. Compute difference to last extreme
308 ** value and remember.
309 */
310 if ( prevextremevalid ) {
311 extremediff = prevval - prevextreme;
312 if ( extremediff < 0 )
313 extremediff = -extremediff;
314 avg += extremediff;
315 nextreme++;
316 }
317 prevextremevalid = 1;
318 prevextreme = prevval;
319 }
320 prevval = val;
321 if ( diff != 0 )
322 prevdiff = diff;
323 }
324 if ( nextreme == 0 )
325 val = 0;
326 else
327 val = (int)(avg / (float)nextreme);
328 return newintobject(val);
329}
330
331static object *
332audioop_maxpp(self, args)
333 object *self;
334 object *args;
335{
336 signed char *cp;
337 int len, size, val, prevval, prevextremevalid = 0, prevextreme;
338 int i;
339 int max = 0;
340 int diff, prevdiff, extremediff;
341
342 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
343 return 0;
344 if ( size != 1 && size != 2 && size != 4 ) {
345 err_setstr(AudioopError, "Size should be 1, 2 or 4");
346 return 0;
347 }
348 /* Compute first delta value ahead. Also automatically makes us
349 ** skip the first extreme value
350 */
351 if ( size == 1 ) prevval = (int)*CHARP(cp, 0);
352 else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
353 else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
354 if ( size == 1 ) val = (int)*CHARP(cp, size);
355 else if ( size == 2 ) val = (int)*SHORTP(cp, size);
356 else if ( size == 4 ) val = (int)*LONGP(cp, size);
357 prevdiff = val - prevval;
358
359 for ( i=size; i<len; i+= size) {
360 if ( size == 1 ) val = (int)*CHARP(cp, i);
361 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
362 else if ( size == 4 ) val = (int)*LONGP(cp, i);
363 diff = val - prevval;
364 if ( diff*prevdiff < 0 ) {
365 /* Derivative changed sign. Compute difference to last extreme
366 ** value and remember.
367 */
368 if ( prevextremevalid ) {
369 extremediff = prevval - prevextreme;
370 if ( extremediff < 0 )
371 extremediff = -extremediff;
372 if ( extremediff > max )
373 max = extremediff;
374 }
375 prevextremevalid = 1;
376 prevextreme = prevval;
377 }
378 prevval = val;
379 if ( diff != 0 )
380 prevdiff = diff;
381 }
382 return newintobject(max);
383}
384
385static object *
Guido van Rossumb66efa01992-06-01 16:01:24 +0000386audioop_cross(self, args)
387 object *self;
388 object *args;
389{
390 signed char *cp;
391 int len, size, val;
392 int i;
393 int cross, prevval, ncross;
394
395 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
396 return 0;
397 if ( size != 1 && size != 2 && size != 4 ) {
398 err_setstr(AudioopError, "Size should be 1, 2 or 4");
399 return 0;
400 }
401 ncross = -1;
402 prevval = 17; /* Anything <> 0,1 */
403 for ( i=0; i<len; i+= size) {
404 if ( size == 1 ) val = ((int)*CHARP(cp, i)) >> 7;
405 else if ( size == 2 ) val = ((int)*SHORTP(cp, i)) >> 15;
406 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 31;
407 val = val & 1;
408 if ( val != prevval ) ncross++;
409 prevval = val;
410 }
411 return newintobject(ncross);
412}
413
414static object *
415audioop_mul(self, args)
416 object *self;
417 object *args;
418{
419 signed char *cp, *ncp;
420 int len, size, val;
421 double factor, fval, maxval;
422 object *rv;
423 int i;
424
425 if ( !getargs(args, "(s#id)", &cp, &len, &size, &factor ) )
426 return 0;
427
428 if ( size == 1 ) maxval = (double) 0x7f;
429 else if ( size == 2 ) maxval = (double) 0x7fff;
430 else if ( size == 4 ) maxval = (double) 0x7fffffff;
431 else {
432 err_setstr(AudioopError, "Size should be 1, 2 or 4");
433 return 0;
434 }
435
436 rv = newsizedstringobject(NULL, len);
437 if ( rv == 0 )
438 return 0;
439 ncp = (signed char *)getstringvalue(rv);
440
441
442 for ( i=0; i < len; i += size ) {
443 if ( size == 1 ) val = (int)*CHARP(cp, i);
444 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
445 else if ( size == 4 ) val = (int)*LONGP(cp, i);
446 fval = (double)val*factor;
447 if ( fval > maxval ) fval = maxval;
448 else if ( fval < -maxval ) fval = -maxval;
449 val = (int)fval;
450 if ( size == 1 ) *CHARP(ncp, i) = (signed char)val;
451 else if ( size == 2 ) *SHORTP(ncp, i) = (short)val;
452 else if ( size == 4 ) *LONGP(ncp, i) = (long)val;
453 }
454 return rv;
455}
456
457static object *
458audioop_tomono(self, args)
459 object *self;
460 object *args;
461{
462 signed char *cp, *ncp;
463 int len, size, val1, val2;
464 double fac1, fac2, fval, maxval;
465 object *rv;
466 int i;
467
468 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
469 return 0;
470
471 if ( size == 1 ) maxval = (double) 0x7f;
472 else if ( size == 2 ) maxval = (double) 0x7fff;
473 else if ( size == 4 ) maxval = (double) 0x7fffffff;
474 else {
475 err_setstr(AudioopError, "Size should be 1, 2 or 4");
476 return 0;
477 }
478
479 rv = newsizedstringobject(NULL, len/2);
480 if ( rv == 0 )
481 return 0;
482 ncp = (signed char *)getstringvalue(rv);
483
484
485 for ( i=0; i < len; i += size*2 ) {
486 if ( size == 1 ) val1 = (int)*CHARP(cp, i);
487 else if ( size == 2 ) val1 = (int)*SHORTP(cp, i);
488 else if ( size == 4 ) val1 = (int)*LONGP(cp, i);
489 if ( size == 1 ) val2 = (int)*CHARP(cp, i+1);
490 else if ( size == 2 ) val2 = (int)*SHORTP(cp, i+2);
491 else if ( size == 4 ) val2 = (int)*LONGP(cp, i+4);
492 fval = (double)val1*fac1 + (double)val2*fac2;
493 if ( fval > maxval ) fval = maxval;
494 else if ( fval < -maxval ) fval = -maxval;
495 val1 = (int)fval;
496 if ( size == 1 ) *CHARP(ncp, i/2) = (signed char)val1;
497 else if ( size == 2 ) *SHORTP(ncp, i/2) = (short)val1;
498 else if ( size == 4 ) *LONGP(ncp, i/2)= (long)val1;
499 }
500 return rv;
501}
502
503static object *
504audioop_tostereo(self, args)
505 object *self;
506 object *args;
507{
508 signed char *cp, *ncp;
509 int len, size, val1, val2, val;
510 double fac1, fac2, fval, maxval;
511 object *rv;
512 int i;
513
514 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
515 return 0;
516
517 if ( size == 1 ) maxval = (double) 0x7f;
518 else if ( size == 2 ) maxval = (double) 0x7fff;
519 else if ( size == 4 ) maxval = (double) 0x7fffffff;
520 else {
521 err_setstr(AudioopError, "Size should be 1, 2 or 4");
522 return 0;
523 }
524
525 rv = newsizedstringobject(NULL, len*2);
526 if ( rv == 0 )
527 return 0;
528 ncp = (signed char *)getstringvalue(rv);
529
530
531 for ( i=0; i < len; i += size ) {
532 if ( size == 1 ) val = (int)*CHARP(cp, i);
533 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
534 else if ( size == 4 ) val = (int)*LONGP(cp, i);
535
536 fval = (double)val*fac1;
537 if ( fval > maxval ) fval = maxval;
538 else if ( fval < -maxval ) fval = -maxval;
539 val1 = (int)fval;
540
541 fval = (double)val*fac2;
542 if ( fval > maxval ) fval = maxval;
543 else if ( fval < -maxval ) fval = -maxval;
544 val2 = (int)fval;
545
546 if ( size == 1 ) *CHARP(ncp, i*2) = (signed char)val1;
547 else if ( size == 2 ) *SHORTP(ncp, i*2) = (short)val1;
548 else if ( size == 4 ) *LONGP(ncp, i*2) = (long)val1;
549
550 if ( size == 1 ) *CHARP(ncp, i*2+1) = (signed char)val2;
551 else if ( size == 2 ) *SHORTP(ncp, i*2+2) = (short)val2;
552 else if ( size == 4 ) *LONGP(ncp, i*2+4) = (long)val2;
553 }
554 return rv;
555}
556
557static object *
558audioop_add(self, args)
559 object *self;
560 object *args;
561{
562 signed char *cp1, *cp2, *ncp;
563 int len1, len2, size, val1, val2;
564 object *rv;
565 int i;
566
567 if ( !getargs(args, "(s#s#i)",
568 &cp1, &len1, &cp2, &len2, &size ) )
569 return 0;
570
571 if ( len1 != len2 ) {
572 err_setstr(AudioopError, "Lengths should be the same");
573 return 0;
574 }
575
576 if ( size != 1 && size != 2 && size != 4) {
577 err_setstr(AudioopError, "Size should be 1, 2 or 4");
578 return 0;
579 }
580
581 rv = newsizedstringobject(NULL, len1);
582 if ( rv == 0 )
583 return 0;
584 ncp = (signed char *)getstringvalue(rv);
585
586
587 for ( i=0; i < len1; i += size ) {
588 if ( size == 1 ) val1 = (int)*CHARP(cp1, i);
589 else if ( size == 2 ) val1 = (int)*SHORTP(cp1, i);
590 else if ( size == 4 ) val1 = (int)*LONGP(cp1, i);
591
592 if ( size == 1 ) val2 = (int)*CHARP(cp2, i);
593 else if ( size == 2 ) val2 = (int)*SHORTP(cp2, i);
594 else if ( size == 4 ) val2 = (int)*LONGP(cp2, i);
595
596 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val1+val2);
597 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val1+val2);
598 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val1+val2);
599 }
600 return rv;
601}
602
603static object *
604audioop_bias(self, args)
605 object *self;
606 object *args;
607{
608 signed char *cp, *ncp;
609 int len, size, val;
610 object *rv;
611 int i;
612 int bias;
613
614 if ( !getargs(args, "(s#ii)",
615 &cp, &len, &size , &bias) )
616 return 0;
617
618 if ( size != 1 && size != 2 && size != 4) {
619 err_setstr(AudioopError, "Size should be 1, 2 or 4");
620 return 0;
621 }
622
623 rv = newsizedstringobject(NULL, len);
624 if ( rv == 0 )
625 return 0;
626 ncp = (signed char *)getstringvalue(rv);
627
628
629 for ( i=0; i < len; i += size ) {
630 if ( size == 1 ) val = (int)*CHARP(cp, i);
631 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
632 else if ( size == 4 ) val = (int)*LONGP(cp, i);
633
634 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val+bias);
635 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val+bias);
636 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val+bias);
637 }
638 return rv;
639}
640
641static object *
642audioop_lin2ulaw(self, args)
643 object *self;
644 object *args;
645{
646 signed char *cp;
647 unsigned char *ncp;
648 int len, size, val;
649 object *rv;
650 int i;
651
652 if ( !getargs(args, "(s#i)",
653 &cp, &len, &size) )
654 return 0;
655
656 if ( size != 1 && size != 2 && size != 4) {
657 err_setstr(AudioopError, "Size should be 1, 2 or 4");
658 return 0;
659 }
660
661 rv = newsizedstringobject(NULL, len/size);
662 if ( rv == 0 )
663 return 0;
664 ncp = (unsigned char *)getstringvalue(rv);
665
666 for ( i=0; i < len; i += size ) {
667 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
668 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
669 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
670
671 *ncp++ = st_linear_to_ulaw(val);
672 }
673 return rv;
674}
675
676static object *
677audioop_ulaw2lin(self, args)
678 object *self;
679 object *args;
680{
681 unsigned char *cp;
682 unsigned char cval;
683 signed char *ncp;
684 int len, size, val;
685 object *rv;
686 int i;
687
688 if ( !getargs(args, "(s#i)",
689 &cp, &len, &size) )
690 return 0;
691
692 if ( size != 1 && size != 2 && size != 4) {
693 err_setstr(AudioopError, "Size should be 1, 2 or 4");
694 return 0;
695 }
696
697 rv = newsizedstringobject(NULL, len*size);
698 if ( rv == 0 )
699 return 0;
700 ncp = (signed char *)getstringvalue(rv);
701
702 for ( i=0; i < len*size; i += size ) {
703 cval = *cp++;
704 val = st_ulaw_to_linear(cval);
705
706 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val >> 8);
707 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val);
Guido van Rossumaad53441992-06-05 15:11:56 +0000708 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val<<16);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000709 }
710 return rv;
711}
712
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000713static object *
Guido van Rossumb64e6351992-07-06 14:21:56 +0000714audioop_lin2adpcm3(self, args)
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000715 object *self;
716 object *args;
717{
718 signed char *cp;
719 signed char *ncp;
720 int len, size, val, step, valprev, delta;
721 object *rv, *state, *str;
722 int i;
723
724 if ( !getargs(args, "(s#iO)",
725 &cp, &len, &size, &state) )
726 return 0;
727
728
729 if ( size != 1 && size != 2 && size != 4) {
730 err_setstr(AudioopError, "Size should be 1, 2 or 4");
731 return 0;
732 }
733
734 str = newsizedstringobject(NULL, len/size);
735 if ( str == 0 )
736 return 0;
737 ncp = (signed char *)getstringvalue(str);
738
739 /* Decode state, should have (value, step) */
740 if ( state == None ) {
741 /* First time, it seems. Set defaults */
742 valprev = 0;
743 step = 4; /* The '4' is magic. Dunno it's significance */
744 } else if ( !getargs(state, "(ii)", &valprev, &step) )
745 return 0;
746
747 for ( i=0; i < len; i += size ) {
748 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
749 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
750 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
751
752 /* Step 1 - compute difference with previous value */
753 delta = (val - valprev)/step;
754
755 /* Step 2 - Clamp */
756 if ( delta < -4 )
757 delta = -4;
758 else if ( delta > 3 )
759 delta = 3;
760
761 /* Step 3 - Update previous value */
762 valprev += delta*step;
763
764 /* Step 4 - Clamp previous value to 16 bits */
765 if ( valprev > 32767 )
766 valprev = 32767;
767 else if ( valprev < -32768 )
768 valprev = -32768;
769
770 /* Step 5 - Update step value */
771 step = step * newstep[abs(delta)];
772 step++; /* Don't understand this. */
773
774 /* Step 6 - Output value (as a whole byte, currently) */
775 *ncp++ = delta;
776 }
777 rv = mkvalue("(O(ii))", str, valprev, step);
778 DECREF(str);
779 return rv;
780}
781
782static object *
Guido van Rossumb64e6351992-07-06 14:21:56 +0000783audioop_adpcm32lin(self, args)
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000784 object *self;
785 object *args;
786{
787 signed char *cp;
788 signed char *ncp;
789 int len, size, val, valprev, step, delta;
790 object *rv, *str, *state;
791 int i;
792
793 if ( !getargs(args, "(s#iO)",
794 &cp, &len, &size, &state) )
795 return 0;
796
797 if ( size != 1 && size != 2 && size != 4) {
798 err_setstr(AudioopError, "Size should be 1, 2 or 4");
799 return 0;
800 }
801
802 /* Decode state, should have (value, step) */
803 if ( state == None ) {
804 /* First time, it seems. Set defaults */
805 valprev = 0;
806 step = 4; /* The '4' is magic. Dunno it's significance */
807 } else if ( !getargs(state, "(ii)", &valprev, &step) )
808 return 0;
809
810 str = newsizedstringobject(NULL, len*size);
811 if ( str == 0 )
812 return 0;
813 ncp = (signed char *)getstringvalue(str);
814
815 for ( i=0; i < len*size; i += size ) {
816 /* Step 1 - get the delta value */
817 delta = *cp++;
818
819 /* Step 2 - update output value */
820 valprev = valprev + delta*step;
821
822 /* Step 3 - clamp output value */
823 if ( valprev > 32767 )
824 valprev = 32767;
825 else if ( valprev < -32768 )
826 valprev = -32768;
827
828 /* Step 4 - Update step value */
829 step = step * newstep[abs(delta)];
830 step++;
831
832 /* Step 5 - Output value */
833 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valprev >> 8);
834 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valprev);
835 else if ( size == 4 ) *LONGP(ncp, i) = (long)(valprev<<16);
836 }
837
838 rv = mkvalue("(O(ii))", str, valprev, step);
839 DECREF(str);
840 return rv;
841}
842
Guido van Rossumb64e6351992-07-06 14:21:56 +0000843static object *
844audioop_lin2adpcm(self, args)
845 object *self;
846 object *args;
847{
848 signed char *cp;
849 signed char *ncp;
Jack Jansend513f0b1993-01-08 14:40:53 +0000850 int len, size, val, step, valpred, delta, index, sign, vpdiff, diff;
Guido van Rossumb64e6351992-07-06 14:21:56 +0000851 object *rv, *state, *str;
852 int i, outputbuffer, bufferstep;
853
854 if ( !getargs(args, "(s#iO)",
855 &cp, &len, &size, &state) )
856 return 0;
857
858
859 if ( size != 1 && size != 2 && size != 4) {
860 err_setstr(AudioopError, "Size should be 1, 2 or 4");
861 return 0;
862 }
863
864 str = newsizedstringobject(NULL, len/(size*2));
865 if ( str == 0 )
866 return 0;
867 ncp = (signed char *)getstringvalue(str);
868
869 /* Decode state, should have (value, step) */
870 if ( state == None ) {
871 /* First time, it seems. Set defaults */
Jack Jansend513f0b1993-01-08 14:40:53 +0000872 valpred = 0;
Guido van Rossumb64e6351992-07-06 14:21:56 +0000873 step = 7;
874 index = 0;
Jack Jansend513f0b1993-01-08 14:40:53 +0000875 } else if ( !getargs(state, "(iii)", &valpred, &step, &index) )
Guido van Rossumb64e6351992-07-06 14:21:56 +0000876 return 0;
877
878 bufferstep = 1;
879
880 for ( i=0; i < len; i += size ) {
881 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
882 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
883 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
884
885 /* Step 1 - compute difference with previous value */
Jack Jansend513f0b1993-01-08 14:40:53 +0000886 diff = val - valpred;
887 sign = (diff < 0) ? 8 : 0;
888 if ( sign ) diff = (-diff);
Guido van Rossumb64e6351992-07-06 14:21:56 +0000889
890 /* Step 2 - Divide and clamp */
Jack Jansend513f0b1993-01-08 14:40:53 +0000891 /* Note:
892 ** This code *approximately* computes:
893 ** delta = diff*4/step;
894 ** vpdiff = (delta+0.5)*step/4;
895 ** but in shift step bits are dropped. The net result of this is
896 ** that even if you have fast mul/div hardware you cannot put it to
897 ** good use since the fixup would be too expensive.
898 */
899 delta = 0;
900 vpdiff = (step >> 3);
901
902 if ( diff >= step ) {
903 delta = 4;
904 diff -= step;
905 vpdiff += step;
906 }
907 step >>= 1;
908 if ( diff >= step ) {
909 delta |= 2;
910 diff -= step;
911 vpdiff += step;
912 }
913 step >>= 1;
914 if ( diff >= step ) {
915 delta |= 1;
916 vpdiff += step;
917 }
918
Guido van Rossumb64e6351992-07-06 14:21:56 +0000919 /* Step 3 - Update previous value */
920 if ( sign )
Jack Jansend513f0b1993-01-08 14:40:53 +0000921 valpred -= vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +0000922 else
Jack Jansend513f0b1993-01-08 14:40:53 +0000923 valpred += vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +0000924
925 /* Step 4 - Clamp previous value to 16 bits */
Jack Jansend513f0b1993-01-08 14:40:53 +0000926 if ( valpred > 32767 )
927 valpred = 32767;
928 else if ( valpred < -32768 )
929 valpred = -32768;
Guido van Rossumb64e6351992-07-06 14:21:56 +0000930
931 /* Step 5 - Assemble value, update index and step values */
932 delta |= sign;
933
934 index += indexTable[delta];
935 if ( index < 0 ) index = 0;
936 if ( index > 88 ) index = 88;
937 step = stepsizeTable[index];
938
Jack Jansend513f0b1993-01-08 14:40:53 +0000939 /* Step 6 - Output value */
Guido van Rossumb64e6351992-07-06 14:21:56 +0000940 if ( bufferstep ) {
Jack Jansend513f0b1993-01-08 14:40:53 +0000941 outputbuffer = (delta << 4) & 0xf0;
Guido van Rossumb64e6351992-07-06 14:21:56 +0000942 } else {
Jack Jansend513f0b1993-01-08 14:40:53 +0000943 *ncp++ = (delta & 0x0f) | outputbuffer;
Guido van Rossumb64e6351992-07-06 14:21:56 +0000944 }
945 bufferstep = !bufferstep;
946 }
Jack Jansend513f0b1993-01-08 14:40:53 +0000947 rv = mkvalue("(O(iii))", str, valpred, step, index);
Guido van Rossumb64e6351992-07-06 14:21:56 +0000948 DECREF(str);
949 return rv;
950}
951
952static object *
953audioop_adpcm2lin(self, args)
954 object *self;
955 object *args;
956{
957 signed char *cp;
958 signed char *ncp;
Jack Jansend513f0b1993-01-08 14:40:53 +0000959 int len, size, val, valpred, step, delta, index, sign, vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +0000960 object *rv, *str, *state;
961 int i, inputbuffer, bufferstep;
962
963 if ( !getargs(args, "(s#iO)",
964 &cp, &len, &size, &state) )
965 return 0;
966
967 if ( size != 1 && size != 2 && size != 4) {
968 err_setstr(AudioopError, "Size should be 1, 2 or 4");
969 return 0;
970 }
971
972 /* Decode state, should have (value, step) */
973 if ( state == None ) {
974 /* First time, it seems. Set defaults */
Jack Jansend513f0b1993-01-08 14:40:53 +0000975 valpred = 0;
Guido van Rossumb64e6351992-07-06 14:21:56 +0000976 step = 7;
977 index = 0;
Jack Jansend513f0b1993-01-08 14:40:53 +0000978 } else if ( !getargs(state, "(iii)", &valpred, &step, &index) )
Guido van Rossumb64e6351992-07-06 14:21:56 +0000979 return 0;
980
981 str = newsizedstringobject(NULL, len*size*2);
982 if ( str == 0 )
983 return 0;
984 ncp = (signed char *)getstringvalue(str);
985
986 bufferstep = 0;
987
988 for ( i=0; i < len*size*2; i += size ) {
989 /* Step 1 - get the delta value and compute next index */
990 if ( bufferstep ) {
991 delta = inputbuffer & 0xf;
992 } else {
993 inputbuffer = *cp++;
994 delta = (inputbuffer >> 4) & 0xf;
995 }
996
997 bufferstep = !bufferstep;
998
Jack Jansend513f0b1993-01-08 14:40:53 +0000999 /* Step 2 - Find new index value (for later) */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001000 index += indexTable[delta];
1001 if ( index < 0 ) index = 0;
1002 if ( index > 88 ) index = 88;
1003
Jack Jansend513f0b1993-01-08 14:40:53 +00001004 /* Step 3 - Separate sign and magnitude */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001005 sign = delta & 8;
1006 delta = delta & 7;
1007
Jack Jansend513f0b1993-01-08 14:40:53 +00001008 /* Step 4 - Compute difference and new predicted value */
1009 /*
1010 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
1011 ** in adpcm_coder.
1012 */
1013 vpdiff = step >> 3;
1014 if ( delta & 4 ) vpdiff += step;
1015 if ( delta & 2 ) vpdiff += step>>1;
1016 if ( delta & 1 ) vpdiff += step>>2;
1017
Guido van Rossumb64e6351992-07-06 14:21:56 +00001018 if ( sign )
Jack Jansend513f0b1993-01-08 14:40:53 +00001019 valpred -= vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001020 else
Jack Jansend513f0b1993-01-08 14:40:53 +00001021 valpred += vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001022
Jack Jansend513f0b1993-01-08 14:40:53 +00001023 /* Step 5 - clamp output value */
1024 if ( valpred > 32767 )
1025 valpred = 32767;
1026 else if ( valpred < -32768 )
1027 valpred = -32768;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001028
Jack Jansend513f0b1993-01-08 14:40:53 +00001029 /* Step 6 - Update step value */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001030 step = stepsizeTable[index];
1031
1032 /* Step 6 - Output value */
Jack Jansend513f0b1993-01-08 14:40:53 +00001033 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valpred >> 8);
1034 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valpred);
1035 else if ( size == 4 ) *LONGP(ncp, i) = (long)(valpred<<16);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001036 }
1037
Jack Jansend513f0b1993-01-08 14:40:53 +00001038 rv = mkvalue("(O(iii))", str, valpred, step, index);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001039 DECREF(str);
1040 return rv;
1041}
1042
Guido van Rossumb66efa01992-06-01 16:01:24 +00001043static struct methodlist audioop_methods[] = {
1044 { "max", audioop_max },
1045 { "avg", audioop_avg },
Jack Jansene1b4d7c1992-08-24 14:36:31 +00001046 { "maxpp", audioop_maxpp },
1047 { "avgpp", audioop_avgpp },
1048 { "rms", audioop_rms },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001049 { "cross", audioop_cross },
1050 { "mul", audioop_mul },
1051 { "add", audioop_add },
1052 { "bias", audioop_bias },
1053 { "ulaw2lin", audioop_ulaw2lin },
1054 { "lin2ulaw", audioop_lin2ulaw },
Guido van Rossum8e7a0f01992-06-23 15:23:57 +00001055 { "adpcm2lin", audioop_adpcm2lin },
1056 { "lin2adpcm", audioop_lin2adpcm },
Guido van Rossumb64e6351992-07-06 14:21:56 +00001057 { "adpcm32lin", audioop_adpcm32lin },
1058 { "lin2adpcm3", audioop_lin2adpcm3 },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001059 { "tomono", audioop_tomono },
1060 { "tostereo", audioop_tostereo },
1061 { "getsample", audioop_getsample },
1062 { 0, 0 }
1063};
1064
1065
1066void
1067initaudioop()
1068{
1069 object *m, *d;
1070 m = initmodule("audioop", audioop_methods);
1071 d = getmoduledict(m);
1072 AudioopError = newstringobject("audioop.error");
1073 if ( AudioopError == NULL || dictinsert(d,"error",AudioopError) )
1074 fatal("can't define audioop.error");
1075}