blob: 92152b9c2d56dcf08c7c60d94101f611d2c396ba [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 *
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000274audioop_rms2(self, args)
275 object *self;
276 object *args;
277{
278 signed char *cp1, *cp2;
279 int len1, len2, size, val1, val2;
280 int i;
281 float sum_squares = 0.0;
282
283 if ( !getargs(args, "(s#s#i)", &cp1, &len1, &cp2, &len2, &size) )
284 return 0;
285 if ( size != 1 && size != 2 && size != 4 ) {
286 err_setstr(AudioopError, "Size should be 1, 2 or 4");
287 return 0;
288 }
289 if ( len1 != len2 ) {
290 err_setstr(AudioopError, "Samples should be same size");
291 return 0;
292 }
293 for ( i=0; i<len1; i+= size) {
294 if ( size == 1 ) {
295 val1 = (int)*CHARP(cp1, i);
296 val2 = (int)*CHARP(cp2, i);
297 } else if ( size == 2 ) {
298 val1 = (int)*SHORTP(cp1, i);
299 val2 = (int)*SHORTP(cp2, i);
300 } else if ( size == 4 ) {
301 val1 = (int)*LONGP(cp1, i);
302 val2 = (int)*LONGP(cp2, i);
303 }
304 sum_squares += (float)val1*(float)val2;
305 }
306 if ( len1 == 0 )
307 val1 = 0;
308 else
309 val1 = (int)sqrt(sum_squares / (float)(len1/size));
310 return newintobject(val1);
311}
312
313static object *
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000314audioop_avgpp(self, args)
315 object *self;
316 object *args;
317{
318 signed char *cp;
319 int len, size, val, prevval, prevextremevalid = 0, prevextreme;
320 int i;
321 float avg = 0.0;
322 int diff, prevdiff, extremediff, nextreme = 0;
323
324 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
325 return 0;
326 if ( size != 1 && size != 2 && size != 4 ) {
327 err_setstr(AudioopError, "Size should be 1, 2 or 4");
328 return 0;
329 }
330 /* Compute first delta value ahead. Also automatically makes us
331 ** skip the first extreme value
332 */
333 if ( size == 1 ) prevval = (int)*CHARP(cp, 0);
334 else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
335 else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
336 if ( size == 1 ) val = (int)*CHARP(cp, size);
337 else if ( size == 2 ) val = (int)*SHORTP(cp, size);
338 else if ( size == 4 ) val = (int)*LONGP(cp, size);
339 prevdiff = val - prevval;
340
341 for ( i=size; i<len; i+= size) {
342 if ( size == 1 ) val = (int)*CHARP(cp, i);
343 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
344 else if ( size == 4 ) val = (int)*LONGP(cp, i);
345 diff = val - prevval;
346 if ( diff*prevdiff < 0 ) {
347 /* Derivative changed sign. Compute difference to last extreme
348 ** value and remember.
349 */
350 if ( prevextremevalid ) {
351 extremediff = prevval - prevextreme;
352 if ( extremediff < 0 )
353 extremediff = -extremediff;
354 avg += extremediff;
355 nextreme++;
356 }
357 prevextremevalid = 1;
358 prevextreme = prevval;
359 }
360 prevval = val;
361 if ( diff != 0 )
362 prevdiff = diff;
363 }
364 if ( nextreme == 0 )
365 val = 0;
366 else
367 val = (int)(avg / (float)nextreme);
368 return newintobject(val);
369}
370
371static object *
372audioop_maxpp(self, args)
373 object *self;
374 object *args;
375{
376 signed char *cp;
377 int len, size, val, prevval, prevextremevalid = 0, prevextreme;
378 int i;
379 int max = 0;
380 int diff, prevdiff, extremediff;
381
382 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
383 return 0;
384 if ( size != 1 && size != 2 && size != 4 ) {
385 err_setstr(AudioopError, "Size should be 1, 2 or 4");
386 return 0;
387 }
388 /* Compute first delta value ahead. Also automatically makes us
389 ** skip the first extreme value
390 */
391 if ( size == 1 ) prevval = (int)*CHARP(cp, 0);
392 else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
393 else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
394 if ( size == 1 ) val = (int)*CHARP(cp, size);
395 else if ( size == 2 ) val = (int)*SHORTP(cp, size);
396 else if ( size == 4 ) val = (int)*LONGP(cp, size);
397 prevdiff = val - prevval;
398
399 for ( i=size; i<len; i+= size) {
400 if ( size == 1 ) val = (int)*CHARP(cp, i);
401 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
402 else if ( size == 4 ) val = (int)*LONGP(cp, i);
403 diff = val - prevval;
404 if ( diff*prevdiff < 0 ) {
405 /* Derivative changed sign. Compute difference to last extreme
406 ** value and remember.
407 */
408 if ( prevextremevalid ) {
409 extremediff = prevval - prevextreme;
410 if ( extremediff < 0 )
411 extremediff = -extremediff;
412 if ( extremediff > max )
413 max = extremediff;
414 }
415 prevextremevalid = 1;
416 prevextreme = prevval;
417 }
418 prevval = val;
419 if ( diff != 0 )
420 prevdiff = diff;
421 }
422 return newintobject(max);
423}
424
425static object *
Guido van Rossumb66efa01992-06-01 16:01:24 +0000426audioop_cross(self, args)
427 object *self;
428 object *args;
429{
430 signed char *cp;
431 int len, size, val;
432 int i;
433 int cross, prevval, ncross;
434
435 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
436 return 0;
437 if ( size != 1 && size != 2 && size != 4 ) {
438 err_setstr(AudioopError, "Size should be 1, 2 or 4");
439 return 0;
440 }
441 ncross = -1;
442 prevval = 17; /* Anything <> 0,1 */
443 for ( i=0; i<len; i+= size) {
444 if ( size == 1 ) val = ((int)*CHARP(cp, i)) >> 7;
445 else if ( size == 2 ) val = ((int)*SHORTP(cp, i)) >> 15;
446 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 31;
447 val = val & 1;
448 if ( val != prevval ) ncross++;
449 prevval = val;
450 }
451 return newintobject(ncross);
452}
453
454static object *
455audioop_mul(self, args)
456 object *self;
457 object *args;
458{
459 signed char *cp, *ncp;
460 int len, size, val;
461 double factor, fval, maxval;
462 object *rv;
463 int i;
464
465 if ( !getargs(args, "(s#id)", &cp, &len, &size, &factor ) )
466 return 0;
467
468 if ( size == 1 ) maxval = (double) 0x7f;
469 else if ( size == 2 ) maxval = (double) 0x7fff;
470 else if ( size == 4 ) maxval = (double) 0x7fffffff;
471 else {
472 err_setstr(AudioopError, "Size should be 1, 2 or 4");
473 return 0;
474 }
475
476 rv = newsizedstringobject(NULL, len);
477 if ( rv == 0 )
478 return 0;
479 ncp = (signed char *)getstringvalue(rv);
480
481
482 for ( i=0; i < len; i += size ) {
483 if ( size == 1 ) val = (int)*CHARP(cp, i);
484 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
485 else if ( size == 4 ) val = (int)*LONGP(cp, i);
486 fval = (double)val*factor;
487 if ( fval > maxval ) fval = maxval;
488 else if ( fval < -maxval ) fval = -maxval;
489 val = (int)fval;
490 if ( size == 1 ) *CHARP(ncp, i) = (signed char)val;
491 else if ( size == 2 ) *SHORTP(ncp, i) = (short)val;
492 else if ( size == 4 ) *LONGP(ncp, i) = (long)val;
493 }
494 return rv;
495}
496
497static object *
498audioop_tomono(self, args)
499 object *self;
500 object *args;
501{
502 signed char *cp, *ncp;
503 int len, size, val1, val2;
504 double fac1, fac2, fval, maxval;
505 object *rv;
506 int i;
507
508 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
509 return 0;
510
511 if ( size == 1 ) maxval = (double) 0x7f;
512 else if ( size == 2 ) maxval = (double) 0x7fff;
513 else if ( size == 4 ) maxval = (double) 0x7fffffff;
514 else {
515 err_setstr(AudioopError, "Size should be 1, 2 or 4");
516 return 0;
517 }
518
519 rv = newsizedstringobject(NULL, len/2);
520 if ( rv == 0 )
521 return 0;
522 ncp = (signed char *)getstringvalue(rv);
523
524
525 for ( i=0; i < len; i += size*2 ) {
526 if ( size == 1 ) val1 = (int)*CHARP(cp, i);
527 else if ( size == 2 ) val1 = (int)*SHORTP(cp, i);
528 else if ( size == 4 ) val1 = (int)*LONGP(cp, i);
529 if ( size == 1 ) val2 = (int)*CHARP(cp, i+1);
530 else if ( size == 2 ) val2 = (int)*SHORTP(cp, i+2);
531 else if ( size == 4 ) val2 = (int)*LONGP(cp, i+4);
532 fval = (double)val1*fac1 + (double)val2*fac2;
533 if ( fval > maxval ) fval = maxval;
534 else if ( fval < -maxval ) fval = -maxval;
535 val1 = (int)fval;
536 if ( size == 1 ) *CHARP(ncp, i/2) = (signed char)val1;
537 else if ( size == 2 ) *SHORTP(ncp, i/2) = (short)val1;
538 else if ( size == 4 ) *LONGP(ncp, i/2)= (long)val1;
539 }
540 return rv;
541}
542
543static object *
544audioop_tostereo(self, args)
545 object *self;
546 object *args;
547{
548 signed char *cp, *ncp;
549 int len, size, val1, val2, val;
550 double fac1, fac2, fval, maxval;
551 object *rv;
552 int i;
553
554 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
555 return 0;
556
557 if ( size == 1 ) maxval = (double) 0x7f;
558 else if ( size == 2 ) maxval = (double) 0x7fff;
559 else if ( size == 4 ) maxval = (double) 0x7fffffff;
560 else {
561 err_setstr(AudioopError, "Size should be 1, 2 or 4");
562 return 0;
563 }
564
565 rv = newsizedstringobject(NULL, len*2);
566 if ( rv == 0 )
567 return 0;
568 ncp = (signed char *)getstringvalue(rv);
569
570
571 for ( i=0; i < len; i += size ) {
572 if ( size == 1 ) val = (int)*CHARP(cp, i);
573 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
574 else if ( size == 4 ) val = (int)*LONGP(cp, i);
575
576 fval = (double)val*fac1;
577 if ( fval > maxval ) fval = maxval;
578 else if ( fval < -maxval ) fval = -maxval;
579 val1 = (int)fval;
580
581 fval = (double)val*fac2;
582 if ( fval > maxval ) fval = maxval;
583 else if ( fval < -maxval ) fval = -maxval;
584 val2 = (int)fval;
585
586 if ( size == 1 ) *CHARP(ncp, i*2) = (signed char)val1;
587 else if ( size == 2 ) *SHORTP(ncp, i*2) = (short)val1;
588 else if ( size == 4 ) *LONGP(ncp, i*2) = (long)val1;
589
590 if ( size == 1 ) *CHARP(ncp, i*2+1) = (signed char)val2;
591 else if ( size == 2 ) *SHORTP(ncp, i*2+2) = (short)val2;
592 else if ( size == 4 ) *LONGP(ncp, i*2+4) = (long)val2;
593 }
594 return rv;
595}
596
597static object *
598audioop_add(self, args)
599 object *self;
600 object *args;
601{
602 signed char *cp1, *cp2, *ncp;
603 int len1, len2, size, val1, val2;
604 object *rv;
605 int i;
606
607 if ( !getargs(args, "(s#s#i)",
608 &cp1, &len1, &cp2, &len2, &size ) )
609 return 0;
610
611 if ( len1 != len2 ) {
612 err_setstr(AudioopError, "Lengths should be the same");
613 return 0;
614 }
615
616 if ( size != 1 && size != 2 && size != 4) {
617 err_setstr(AudioopError, "Size should be 1, 2 or 4");
618 return 0;
619 }
620
621 rv = newsizedstringobject(NULL, len1);
622 if ( rv == 0 )
623 return 0;
624 ncp = (signed char *)getstringvalue(rv);
625
626
627 for ( i=0; i < len1; i += size ) {
628 if ( size == 1 ) val1 = (int)*CHARP(cp1, i);
629 else if ( size == 2 ) val1 = (int)*SHORTP(cp1, i);
630 else if ( size == 4 ) val1 = (int)*LONGP(cp1, i);
631
632 if ( size == 1 ) val2 = (int)*CHARP(cp2, i);
633 else if ( size == 2 ) val2 = (int)*SHORTP(cp2, i);
634 else if ( size == 4 ) val2 = (int)*LONGP(cp2, i);
635
636 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val1+val2);
637 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val1+val2);
638 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val1+val2);
639 }
640 return rv;
641}
642
643static object *
644audioop_bias(self, args)
645 object *self;
646 object *args;
647{
648 signed char *cp, *ncp;
649 int len, size, val;
650 object *rv;
651 int i;
652 int bias;
653
654 if ( !getargs(args, "(s#ii)",
655 &cp, &len, &size , &bias) )
656 return 0;
657
658 if ( size != 1 && size != 2 && size != 4) {
659 err_setstr(AudioopError, "Size should be 1, 2 or 4");
660 return 0;
661 }
662
663 rv = newsizedstringobject(NULL, len);
664 if ( rv == 0 )
665 return 0;
666 ncp = (signed char *)getstringvalue(rv);
667
668
669 for ( i=0; i < len; i += size ) {
670 if ( size == 1 ) val = (int)*CHARP(cp, i);
671 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
672 else if ( size == 4 ) val = (int)*LONGP(cp, i);
673
674 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val+bias);
675 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val+bias);
676 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val+bias);
677 }
678 return rv;
679}
680
681static object *
682audioop_lin2ulaw(self, args)
683 object *self;
684 object *args;
685{
686 signed char *cp;
687 unsigned char *ncp;
688 int len, size, val;
689 object *rv;
690 int i;
691
692 if ( !getargs(args, "(s#i)",
693 &cp, &len, &size) )
694 return 0;
695
696 if ( size != 1 && size != 2 && size != 4) {
697 err_setstr(AudioopError, "Size should be 1, 2 or 4");
698 return 0;
699 }
700
701 rv = newsizedstringobject(NULL, len/size);
702 if ( rv == 0 )
703 return 0;
704 ncp = (unsigned char *)getstringvalue(rv);
705
706 for ( i=0; i < len; i += size ) {
707 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
708 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
709 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
710
711 *ncp++ = st_linear_to_ulaw(val);
712 }
713 return rv;
714}
715
716static object *
717audioop_ulaw2lin(self, args)
718 object *self;
719 object *args;
720{
721 unsigned char *cp;
722 unsigned char cval;
723 signed char *ncp;
724 int len, size, val;
725 object *rv;
726 int i;
727
728 if ( !getargs(args, "(s#i)",
729 &cp, &len, &size) )
730 return 0;
731
732 if ( size != 1 && size != 2 && size != 4) {
733 err_setstr(AudioopError, "Size should be 1, 2 or 4");
734 return 0;
735 }
736
737 rv = newsizedstringobject(NULL, len*size);
738 if ( rv == 0 )
739 return 0;
740 ncp = (signed char *)getstringvalue(rv);
741
742 for ( i=0; i < len*size; i += size ) {
743 cval = *cp++;
744 val = st_ulaw_to_linear(cval);
745
746 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val >> 8);
747 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val);
Guido van Rossumaad53441992-06-05 15:11:56 +0000748 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val<<16);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000749 }
750 return rv;
751}
752
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000753static object *
Guido van Rossumb64e6351992-07-06 14:21:56 +0000754audioop_lin2adpcm3(self, args)
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000755 object *self;
756 object *args;
757{
758 signed char *cp;
759 signed char *ncp;
760 int len, size, val, step, valprev, delta;
761 object *rv, *state, *str;
762 int i;
763
764 if ( !getargs(args, "(s#iO)",
765 &cp, &len, &size, &state) )
766 return 0;
767
768
769 if ( size != 1 && size != 2 && size != 4) {
770 err_setstr(AudioopError, "Size should be 1, 2 or 4");
771 return 0;
772 }
773
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000774 str = newsizedstringobject(NULL, len/size);
775 if ( str == 0 )
776 return 0;
777 ncp = (signed char *)getstringvalue(str);
778
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000779 /* Decode state, should have (value, step) */
780 if ( state == None ) {
781 /* First time, it seems. Set defaults */
782 valprev = 0;
783 step = 4; /* The '4' is magic. Dunno it's significance */
784 } else if ( !getargs(state, "(ii)", &valprev, &step) )
785 return 0;
786
787 for ( i=0; i < len; i += size ) {
788 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
789 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
790 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
791
792 /* Step 1 - compute difference with previous value */
793 delta = (val - valprev)/step;
794
795 /* Step 2 - Clamp */
796 if ( delta < -4 )
797 delta = -4;
798 else if ( delta > 3 )
799 delta = 3;
800
801 /* Step 3 - Update previous value */
802 valprev += delta*step;
803
804 /* Step 4 - Clamp previous value to 16 bits */
805 if ( valprev > 32767 )
806 valprev = 32767;
807 else if ( valprev < -32768 )
808 valprev = -32768;
809
810 /* Step 5 - Update step value */
811 step = step * newstep[abs(delta)];
812 step++; /* Don't understand this. */
813
814 /* Step 6 - Output value (as a whole byte, currently) */
815 *ncp++ = delta;
816 }
817 rv = mkvalue("(O(ii))", str, valprev, step);
818 DECREF(str);
819 return rv;
820}
821
822static object *
Guido van Rossumb64e6351992-07-06 14:21:56 +0000823audioop_adpcm32lin(self, args)
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000824 object *self;
825 object *args;
826{
827 signed char *cp;
828 signed char *ncp;
829 int len, size, val, valprev, step, delta;
830 object *rv, *str, *state;
831 int i;
832
833 if ( !getargs(args, "(s#iO)",
834 &cp, &len, &size, &state) )
835 return 0;
836
837 if ( size != 1 && size != 2 && size != 4) {
838 err_setstr(AudioopError, "Size should be 1, 2 or 4");
839 return 0;
840 }
841
842 /* Decode state, should have (value, step) */
843 if ( state == None ) {
844 /* First time, it seems. Set defaults */
845 valprev = 0;
846 step = 4; /* The '4' is magic. Dunno it's significance */
847 } else if ( !getargs(state, "(ii)", &valprev, &step) )
848 return 0;
849
850 str = newsizedstringobject(NULL, len*size);
851 if ( str == 0 )
852 return 0;
853 ncp = (signed char *)getstringvalue(str);
854
855 for ( i=0; i < len*size; i += size ) {
856 /* Step 1 - get the delta value */
857 delta = *cp++;
858
859 /* Step 2 - update output value */
860 valprev = valprev + delta*step;
861
862 /* Step 3 - clamp output value */
863 if ( valprev > 32767 )
864 valprev = 32767;
865 else if ( valprev < -32768 )
866 valprev = -32768;
867
868 /* Step 4 - Update step value */
869 step = step * newstep[abs(delta)];
870 step++;
871
872 /* Step 5 - Output value */
873 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valprev >> 8);
874 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valprev);
875 else if ( size == 4 ) *LONGP(ncp, i) = (long)(valprev<<16);
876 }
877
878 rv = mkvalue("(O(ii))", str, valprev, step);
879 DECREF(str);
880 return rv;
881}
882
Guido van Rossumb64e6351992-07-06 14:21:56 +0000883static object *
884audioop_lin2adpcm(self, args)
885 object *self;
886 object *args;
887{
888 signed char *cp;
889 signed char *ncp;
Jack Jansend513f0b1993-01-08 14:40:53 +0000890 int len, size, val, step, valpred, delta, index, sign, vpdiff, diff;
Guido van Rossumb64e6351992-07-06 14:21:56 +0000891 object *rv, *state, *str;
892 int i, outputbuffer, bufferstep;
893
894 if ( !getargs(args, "(s#iO)",
895 &cp, &len, &size, &state) )
896 return 0;
897
898
899 if ( size != 1 && size != 2 && size != 4) {
900 err_setstr(AudioopError, "Size should be 1, 2 or 4");
901 return 0;
902 }
903
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000904 str = newsizedstringobject(NULL, len/(size*2));
905 if ( str == 0 )
906 return 0;
907 ncp = (signed char *)getstringvalue(str);
908
Guido van Rossumb64e6351992-07-06 14:21:56 +0000909 /* Decode state, should have (value, step) */
910 if ( state == None ) {
911 /* First time, it seems. Set defaults */
Jack Jansend513f0b1993-01-08 14:40:53 +0000912 valpred = 0;
Guido van Rossumb64e6351992-07-06 14:21:56 +0000913 step = 7;
914 index = 0;
Jack Jansen55cea471993-02-10 13:21:59 +0000915 } else if ( !getargs(state, "(ii)", &valpred, &index) )
Guido van Rossumb64e6351992-07-06 14:21:56 +0000916 return 0;
917
Jack Jansen55cea471993-02-10 13:21:59 +0000918 step = stepsizeTable[index];
Guido van Rossumb64e6351992-07-06 14:21:56 +0000919 bufferstep = 1;
920
921 for ( i=0; i < len; i += size ) {
922 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
923 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
924 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
925
926 /* Step 1 - compute difference with previous value */
Jack Jansend513f0b1993-01-08 14:40:53 +0000927 diff = val - valpred;
928 sign = (diff < 0) ? 8 : 0;
929 if ( sign ) diff = (-diff);
Guido van Rossumb64e6351992-07-06 14:21:56 +0000930
931 /* Step 2 - Divide and clamp */
Jack Jansend513f0b1993-01-08 14:40:53 +0000932 /* Note:
933 ** This code *approximately* computes:
934 ** delta = diff*4/step;
935 ** vpdiff = (delta+0.5)*step/4;
936 ** but in shift step bits are dropped. The net result of this is
937 ** that even if you have fast mul/div hardware you cannot put it to
938 ** good use since the fixup would be too expensive.
939 */
940 delta = 0;
941 vpdiff = (step >> 3);
942
943 if ( diff >= step ) {
944 delta = 4;
945 diff -= step;
946 vpdiff += step;
947 }
948 step >>= 1;
949 if ( diff >= step ) {
950 delta |= 2;
951 diff -= step;
952 vpdiff += step;
953 }
954 step >>= 1;
955 if ( diff >= step ) {
956 delta |= 1;
957 vpdiff += step;
958 }
959
Guido van Rossumb64e6351992-07-06 14:21:56 +0000960 /* Step 3 - Update previous value */
961 if ( sign )
Jack Jansend513f0b1993-01-08 14:40:53 +0000962 valpred -= vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +0000963 else
Jack Jansend513f0b1993-01-08 14:40:53 +0000964 valpred += vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +0000965
966 /* Step 4 - Clamp previous value to 16 bits */
Jack Jansend513f0b1993-01-08 14:40:53 +0000967 if ( valpred > 32767 )
968 valpred = 32767;
969 else if ( valpred < -32768 )
970 valpred = -32768;
Guido van Rossumb64e6351992-07-06 14:21:56 +0000971
972 /* Step 5 - Assemble value, update index and step values */
973 delta |= sign;
974
975 index += indexTable[delta];
976 if ( index < 0 ) index = 0;
977 if ( index > 88 ) index = 88;
978 step = stepsizeTable[index];
979
Jack Jansend513f0b1993-01-08 14:40:53 +0000980 /* Step 6 - Output value */
Guido van Rossumb64e6351992-07-06 14:21:56 +0000981 if ( bufferstep ) {
Jack Jansend513f0b1993-01-08 14:40:53 +0000982 outputbuffer = (delta << 4) & 0xf0;
Guido van Rossumb64e6351992-07-06 14:21:56 +0000983 } else {
Jack Jansend513f0b1993-01-08 14:40:53 +0000984 *ncp++ = (delta & 0x0f) | outputbuffer;
Guido van Rossumb64e6351992-07-06 14:21:56 +0000985 }
986 bufferstep = !bufferstep;
987 }
Jack Jansen55cea471993-02-10 13:21:59 +0000988 rv = mkvalue("(O(ii))", str, valpred, index);
Guido van Rossumb64e6351992-07-06 14:21:56 +0000989 DECREF(str);
990 return rv;
991}
992
993static object *
994audioop_adpcm2lin(self, args)
995 object *self;
996 object *args;
997{
998 signed char *cp;
999 signed char *ncp;
Jack Jansend513f0b1993-01-08 14:40:53 +00001000 int len, size, val, valpred, step, delta, index, sign, vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001001 object *rv, *str, *state;
1002 int i, inputbuffer, bufferstep;
1003
1004 if ( !getargs(args, "(s#iO)",
1005 &cp, &len, &size, &state) )
1006 return 0;
1007
1008 if ( size != 1 && size != 2 && size != 4) {
1009 err_setstr(AudioopError, "Size should be 1, 2 or 4");
1010 return 0;
1011 }
1012
1013 /* Decode state, should have (value, step) */
1014 if ( state == None ) {
1015 /* First time, it seems. Set defaults */
Jack Jansend513f0b1993-01-08 14:40:53 +00001016 valpred = 0;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001017 step = 7;
1018 index = 0;
Jack Jansen55cea471993-02-10 13:21:59 +00001019 } else if ( !getargs(state, "(ii)", &valpred, &index) )
Guido van Rossumb64e6351992-07-06 14:21:56 +00001020 return 0;
1021
1022 str = newsizedstringobject(NULL, len*size*2);
1023 if ( str == 0 )
1024 return 0;
1025 ncp = (signed char *)getstringvalue(str);
1026
Jack Jansen55cea471993-02-10 13:21:59 +00001027 step = stepsizeTable[index];
Guido van Rossumb64e6351992-07-06 14:21:56 +00001028 bufferstep = 0;
1029
1030 for ( i=0; i < len*size*2; i += size ) {
1031 /* Step 1 - get the delta value and compute next index */
1032 if ( bufferstep ) {
1033 delta = inputbuffer & 0xf;
1034 } else {
1035 inputbuffer = *cp++;
1036 delta = (inputbuffer >> 4) & 0xf;
1037 }
1038
1039 bufferstep = !bufferstep;
1040
Jack Jansend513f0b1993-01-08 14:40:53 +00001041 /* Step 2 - Find new index value (for later) */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001042 index += indexTable[delta];
1043 if ( index < 0 ) index = 0;
1044 if ( index > 88 ) index = 88;
1045
Jack Jansend513f0b1993-01-08 14:40:53 +00001046 /* Step 3 - Separate sign and magnitude */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001047 sign = delta & 8;
1048 delta = delta & 7;
1049
Jack Jansend513f0b1993-01-08 14:40:53 +00001050 /* Step 4 - Compute difference and new predicted value */
1051 /*
1052 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
1053 ** in adpcm_coder.
1054 */
1055 vpdiff = step >> 3;
1056 if ( delta & 4 ) vpdiff += step;
1057 if ( delta & 2 ) vpdiff += step>>1;
1058 if ( delta & 1 ) vpdiff += step>>2;
1059
Guido van Rossumb64e6351992-07-06 14:21:56 +00001060 if ( sign )
Jack Jansend513f0b1993-01-08 14:40:53 +00001061 valpred -= vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001062 else
Jack Jansend513f0b1993-01-08 14:40:53 +00001063 valpred += vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001064
Jack Jansend513f0b1993-01-08 14:40:53 +00001065 /* Step 5 - clamp output value */
1066 if ( valpred > 32767 )
1067 valpred = 32767;
1068 else if ( valpred < -32768 )
1069 valpred = -32768;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001070
Jack Jansend513f0b1993-01-08 14:40:53 +00001071 /* Step 6 - Update step value */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001072 step = stepsizeTable[index];
1073
1074 /* Step 6 - Output value */
Jack Jansend513f0b1993-01-08 14:40:53 +00001075 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valpred >> 8);
1076 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valpred);
1077 else if ( size == 4 ) *LONGP(ncp, i) = (long)(valpred<<16);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001078 }
1079
Jack Jansen55cea471993-02-10 13:21:59 +00001080 rv = mkvalue("(O(ii))", str, valpred, index);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001081 DECREF(str);
1082 return rv;
1083}
1084
Guido van Rossumb66efa01992-06-01 16:01:24 +00001085static struct methodlist audioop_methods[] = {
1086 { "max", audioop_max },
1087 { "avg", audioop_avg },
Jack Jansene1b4d7c1992-08-24 14:36:31 +00001088 { "maxpp", audioop_maxpp },
1089 { "avgpp", audioop_avgpp },
1090 { "rms", audioop_rms },
Jack Jansendd8a6ea1993-02-17 14:21:09 +00001091 { "rms2", audioop_rms2 },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001092 { "cross", audioop_cross },
1093 { "mul", audioop_mul },
1094 { "add", audioop_add },
1095 { "bias", audioop_bias },
1096 { "ulaw2lin", audioop_ulaw2lin },
1097 { "lin2ulaw", audioop_lin2ulaw },
Guido van Rossum8e7a0f01992-06-23 15:23:57 +00001098 { "adpcm2lin", audioop_adpcm2lin },
1099 { "lin2adpcm", audioop_lin2adpcm },
Guido van Rossumb64e6351992-07-06 14:21:56 +00001100 { "adpcm32lin", audioop_adpcm32lin },
1101 { "lin2adpcm3", audioop_lin2adpcm3 },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001102 { "tomono", audioop_tomono },
1103 { "tostereo", audioop_tostereo },
1104 { "getsample", audioop_getsample },
1105 { 0, 0 }
1106};
1107
1108
1109void
1110initaudioop()
1111{
1112 object *m, *d;
1113 m = initmodule("audioop", audioop_methods);
1114 d = getmoduledict(m);
1115 AudioopError = newstringobject("audioop.error");
1116 if ( AudioopError == NULL || dictinsert(d,"error",AudioopError) )
1117 fatal("can't define audioop.error");
1118}