blob: c3176f99a772d5876a342d4e2921a8d362f111cf [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
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000133/* ADPCM step variation table */
134static float newstep[5] = { 0.8, 0.9, 1.0, 1.75, 1.75 };
135
Guido van Rossumb66efa01992-06-01 16:01:24 +0000136#define CHARP(cp, i) ((signed char *)(cp+i))
137#define SHORTP(cp, i) ((short *)(cp+i))
138#define LONGP(cp, i) ((long *)(cp+i))
139
140
141
142static object *AudioopError;
143
144static object *
145audioop_getsample(self, args)
146 object *self;
147 object *args;
148{
149 signed char *cp;
150 int len, size, val;
151 int i;
152
153 if ( !getargs(args, "(s#ii)", &cp, &len, &size, &i) )
154 return 0;
155 if ( size != 1 && size != 2 && size != 4 ) {
156 err_setstr(AudioopError, "Size should be 1, 2 or 4");
157 return 0;
158 }
159 if ( i < 0 || i >= len/size ) {
160 err_setstr(AudioopError, "Index out of range");
161 return 0;
162 }
163 if ( size == 1 ) val = (int)*CHARP(cp, i);
164 else if ( size == 2 ) val = (int)*SHORTP(cp, i*2);
165 else if ( size == 4 ) val = (int)*LONGP(cp, i*4);
166 return newintobject(val);
167}
168
169static object *
170audioop_max(self, args)
171 object *self;
172 object *args;
173{
174 signed char *cp;
175 int len, size, val;
176 int i;
177 int max = 0;
178
179 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
180 return 0;
181 if ( size != 1 && size != 2 && size != 4 ) {
182 err_setstr(AudioopError, "Size should be 1, 2 or 4");
183 return 0;
184 }
185 for ( i=0; i<len; i+= size) {
186 if ( size == 1 ) val = (int)*CHARP(cp, i);
187 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
188 else if ( size == 4 ) val = (int)*LONGP(cp, i);
189 if ( val < 0 ) val = (-val);
190 if ( val > max ) max = val;
191 }
192 return newintobject(max);
193}
194
195static object *
196audioop_avg(self, args)
197 object *self;
198 object *args;
199{
200 signed char *cp;
201 int len, size, val;
202 int i;
203 float avg = 0.0;
204
205 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
206 return 0;
207 if ( size != 1 && size != 2 && size != 4 ) {
208 err_setstr(AudioopError, "Size should be 1, 2 or 4");
209 return 0;
210 }
211 for ( i=0; i<len; i+= size) {
212 if ( size == 1 ) val = (int)*CHARP(cp, i);
213 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
214 else if ( size == 4 ) val = (int)*LONGP(cp, i);
215 avg += val;
216 }
217 if ( len == 0 )
218 val = 0;
219 else
220 val = (int)(avg / (float)(len/size));
221 return newintobject(val);
222}
223
224static object *
225audioop_cross(self, args)
226 object *self;
227 object *args;
228{
229 signed char *cp;
230 int len, size, val;
231 int i;
232 int cross, prevval, ncross;
233
234 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
235 return 0;
236 if ( size != 1 && size != 2 && size != 4 ) {
237 err_setstr(AudioopError, "Size should be 1, 2 or 4");
238 return 0;
239 }
240 ncross = -1;
241 prevval = 17; /* Anything <> 0,1 */
242 for ( i=0; i<len; i+= size) {
243 if ( size == 1 ) val = ((int)*CHARP(cp, i)) >> 7;
244 else if ( size == 2 ) val = ((int)*SHORTP(cp, i)) >> 15;
245 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 31;
246 val = val & 1;
247 if ( val != prevval ) ncross++;
248 prevval = val;
249 }
250 return newintobject(ncross);
251}
252
253static object *
254audioop_mul(self, args)
255 object *self;
256 object *args;
257{
258 signed char *cp, *ncp;
259 int len, size, val;
260 double factor, fval, maxval;
261 object *rv;
262 int i;
263
264 if ( !getargs(args, "(s#id)", &cp, &len, &size, &factor ) )
265 return 0;
266
267 if ( size == 1 ) maxval = (double) 0x7f;
268 else if ( size == 2 ) maxval = (double) 0x7fff;
269 else if ( size == 4 ) maxval = (double) 0x7fffffff;
270 else {
271 err_setstr(AudioopError, "Size should be 1, 2 or 4");
272 return 0;
273 }
274
275 rv = newsizedstringobject(NULL, len);
276 if ( rv == 0 )
277 return 0;
278 ncp = (signed char *)getstringvalue(rv);
279
280
281 for ( i=0; i < len; i += size ) {
282 if ( size == 1 ) val = (int)*CHARP(cp, i);
283 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
284 else if ( size == 4 ) val = (int)*LONGP(cp, i);
285 fval = (double)val*factor;
286 if ( fval > maxval ) fval = maxval;
287 else if ( fval < -maxval ) fval = -maxval;
288 val = (int)fval;
289 if ( size == 1 ) *CHARP(ncp, i) = (signed char)val;
290 else if ( size == 2 ) *SHORTP(ncp, i) = (short)val;
291 else if ( size == 4 ) *LONGP(ncp, i) = (long)val;
292 }
293 return rv;
294}
295
296static object *
297audioop_tomono(self, args)
298 object *self;
299 object *args;
300{
301 signed char *cp, *ncp;
302 int len, size, val1, val2;
303 double fac1, fac2, fval, maxval;
304 object *rv;
305 int i;
306
307 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
308 return 0;
309
310 if ( size == 1 ) maxval = (double) 0x7f;
311 else if ( size == 2 ) maxval = (double) 0x7fff;
312 else if ( size == 4 ) maxval = (double) 0x7fffffff;
313 else {
314 err_setstr(AudioopError, "Size should be 1, 2 or 4");
315 return 0;
316 }
317
318 rv = newsizedstringobject(NULL, len/2);
319 if ( rv == 0 )
320 return 0;
321 ncp = (signed char *)getstringvalue(rv);
322
323
324 for ( i=0; i < len; i += size*2 ) {
325 if ( size == 1 ) val1 = (int)*CHARP(cp, i);
326 else if ( size == 2 ) val1 = (int)*SHORTP(cp, i);
327 else if ( size == 4 ) val1 = (int)*LONGP(cp, i);
328 if ( size == 1 ) val2 = (int)*CHARP(cp, i+1);
329 else if ( size == 2 ) val2 = (int)*SHORTP(cp, i+2);
330 else if ( size == 4 ) val2 = (int)*LONGP(cp, i+4);
331 fval = (double)val1*fac1 + (double)val2*fac2;
332 if ( fval > maxval ) fval = maxval;
333 else if ( fval < -maxval ) fval = -maxval;
334 val1 = (int)fval;
335 if ( size == 1 ) *CHARP(ncp, i/2) = (signed char)val1;
336 else if ( size == 2 ) *SHORTP(ncp, i/2) = (short)val1;
337 else if ( size == 4 ) *LONGP(ncp, i/2)= (long)val1;
338 }
339 return rv;
340}
341
342static object *
343audioop_tostereo(self, args)
344 object *self;
345 object *args;
346{
347 signed char *cp, *ncp;
348 int len, size, val1, val2, val;
349 double fac1, fac2, fval, maxval;
350 object *rv;
351 int i;
352
353 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
354 return 0;
355
356 if ( size == 1 ) maxval = (double) 0x7f;
357 else if ( size == 2 ) maxval = (double) 0x7fff;
358 else if ( size == 4 ) maxval = (double) 0x7fffffff;
359 else {
360 err_setstr(AudioopError, "Size should be 1, 2 or 4");
361 return 0;
362 }
363
364 rv = newsizedstringobject(NULL, len*2);
365 if ( rv == 0 )
366 return 0;
367 ncp = (signed char *)getstringvalue(rv);
368
369
370 for ( i=0; i < len; i += size ) {
371 if ( size == 1 ) val = (int)*CHARP(cp, i);
372 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
373 else if ( size == 4 ) val = (int)*LONGP(cp, i);
374
375 fval = (double)val*fac1;
376 if ( fval > maxval ) fval = maxval;
377 else if ( fval < -maxval ) fval = -maxval;
378 val1 = (int)fval;
379
380 fval = (double)val*fac2;
381 if ( fval > maxval ) fval = maxval;
382 else if ( fval < -maxval ) fval = -maxval;
383 val2 = (int)fval;
384
385 if ( size == 1 ) *CHARP(ncp, i*2) = (signed char)val1;
386 else if ( size == 2 ) *SHORTP(ncp, i*2) = (short)val1;
387 else if ( size == 4 ) *LONGP(ncp, i*2) = (long)val1;
388
389 if ( size == 1 ) *CHARP(ncp, i*2+1) = (signed char)val2;
390 else if ( size == 2 ) *SHORTP(ncp, i*2+2) = (short)val2;
391 else if ( size == 4 ) *LONGP(ncp, i*2+4) = (long)val2;
392 }
393 return rv;
394}
395
396static object *
397audioop_add(self, args)
398 object *self;
399 object *args;
400{
401 signed char *cp1, *cp2, *ncp;
402 int len1, len2, size, val1, val2;
403 object *rv;
404 int i;
405
406 if ( !getargs(args, "(s#s#i)",
407 &cp1, &len1, &cp2, &len2, &size ) )
408 return 0;
409
410 if ( len1 != len2 ) {
411 err_setstr(AudioopError, "Lengths should be the same");
412 return 0;
413 }
414
415 if ( size != 1 && size != 2 && size != 4) {
416 err_setstr(AudioopError, "Size should be 1, 2 or 4");
417 return 0;
418 }
419
420 rv = newsizedstringobject(NULL, len1);
421 if ( rv == 0 )
422 return 0;
423 ncp = (signed char *)getstringvalue(rv);
424
425
426 for ( i=0; i < len1; i += size ) {
427 if ( size == 1 ) val1 = (int)*CHARP(cp1, i);
428 else if ( size == 2 ) val1 = (int)*SHORTP(cp1, i);
429 else if ( size == 4 ) val1 = (int)*LONGP(cp1, i);
430
431 if ( size == 1 ) val2 = (int)*CHARP(cp2, i);
432 else if ( size == 2 ) val2 = (int)*SHORTP(cp2, i);
433 else if ( size == 4 ) val2 = (int)*LONGP(cp2, i);
434
435 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val1+val2);
436 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val1+val2);
437 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val1+val2);
438 }
439 return rv;
440}
441
442static object *
443audioop_bias(self, args)
444 object *self;
445 object *args;
446{
447 signed char *cp, *ncp;
448 int len, size, val;
449 object *rv;
450 int i;
451 int bias;
452
453 if ( !getargs(args, "(s#ii)",
454 &cp, &len, &size , &bias) )
455 return 0;
456
457 if ( size != 1 && size != 2 && size != 4) {
458 err_setstr(AudioopError, "Size should be 1, 2 or 4");
459 return 0;
460 }
461
462 rv = newsizedstringobject(NULL, len);
463 if ( rv == 0 )
464 return 0;
465 ncp = (signed char *)getstringvalue(rv);
466
467
468 for ( i=0; i < len; i += size ) {
469 if ( size == 1 ) val = (int)*CHARP(cp, i);
470 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
471 else if ( size == 4 ) val = (int)*LONGP(cp, i);
472
473 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val+bias);
474 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val+bias);
475 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val+bias);
476 }
477 return rv;
478}
479
480static object *
481audioop_lin2ulaw(self, args)
482 object *self;
483 object *args;
484{
485 signed char *cp;
486 unsigned char *ncp;
487 int len, size, val;
488 object *rv;
489 int i;
490
491 if ( !getargs(args, "(s#i)",
492 &cp, &len, &size) )
493 return 0;
494
495 if ( size != 1 && size != 2 && size != 4) {
496 err_setstr(AudioopError, "Size should be 1, 2 or 4");
497 return 0;
498 }
499
500 rv = newsizedstringobject(NULL, len/size);
501 if ( rv == 0 )
502 return 0;
503 ncp = (unsigned char *)getstringvalue(rv);
504
505 for ( i=0; i < len; i += size ) {
506 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
507 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
508 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
509
510 *ncp++ = st_linear_to_ulaw(val);
511 }
512 return rv;
513}
514
515static object *
516audioop_ulaw2lin(self, args)
517 object *self;
518 object *args;
519{
520 unsigned char *cp;
521 unsigned char cval;
522 signed char *ncp;
523 int len, size, val;
524 object *rv;
525 int i;
526
527 if ( !getargs(args, "(s#i)",
528 &cp, &len, &size) )
529 return 0;
530
531 if ( size != 1 && size != 2 && size != 4) {
532 err_setstr(AudioopError, "Size should be 1, 2 or 4");
533 return 0;
534 }
535
536 rv = newsizedstringobject(NULL, len*size);
537 if ( rv == 0 )
538 return 0;
539 ncp = (signed char *)getstringvalue(rv);
540
541 for ( i=0; i < len*size; i += size ) {
542 cval = *cp++;
543 val = st_ulaw_to_linear(cval);
544
545 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val >> 8);
546 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val);
Guido van Rossumaad53441992-06-05 15:11:56 +0000547 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val<<16);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000548 }
549 return rv;
550}
551
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000552static object *
553audioop_lin2adpcm(self, args)
554 object *self;
555 object *args;
556{
557 signed char *cp;
558 signed char *ncp;
559 int len, size, val, step, valprev, delta;
560 object *rv, *state, *str;
561 int i;
562
563 if ( !getargs(args, "(s#iO)",
564 &cp, &len, &size, &state) )
565 return 0;
566
567
568 if ( size != 1 && size != 2 && size != 4) {
569 err_setstr(AudioopError, "Size should be 1, 2 or 4");
570 return 0;
571 }
572
573 str = newsizedstringobject(NULL, len/size);
574 if ( str == 0 )
575 return 0;
576 ncp = (signed char *)getstringvalue(str);
577
578 /* Decode state, should have (value, step) */
579 if ( state == None ) {
580 /* First time, it seems. Set defaults */
581 valprev = 0;
582 step = 4; /* The '4' is magic. Dunno it's significance */
583 } else if ( !getargs(state, "(ii)", &valprev, &step) )
584 return 0;
585
586 for ( i=0; i < len; i += size ) {
587 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
588 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
589 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
590
591 /* Step 1 - compute difference with previous value */
592 delta = (val - valprev)/step;
593
594 /* Step 2 - Clamp */
595 if ( delta < -4 )
596 delta = -4;
597 else if ( delta > 3 )
598 delta = 3;
599
600 /* Step 3 - Update previous value */
601 valprev += delta*step;
602
603 /* Step 4 - Clamp previous value to 16 bits */
604 if ( valprev > 32767 )
605 valprev = 32767;
606 else if ( valprev < -32768 )
607 valprev = -32768;
608
609 /* Step 5 - Update step value */
610 step = step * newstep[abs(delta)];
611 step++; /* Don't understand this. */
612
613 /* Step 6 - Output value (as a whole byte, currently) */
614 *ncp++ = delta;
615 }
616 rv = mkvalue("(O(ii))", str, valprev, step);
617 DECREF(str);
618 return rv;
619}
620
621static object *
622audioop_adpcm2lin(self, args)
623 object *self;
624 object *args;
625{
626 signed char *cp;
627 signed char *ncp;
628 int len, size, val, valprev, step, delta;
629 object *rv, *str, *state;
630 int i;
631
632 if ( !getargs(args, "(s#iO)",
633 &cp, &len, &size, &state) )
634 return 0;
635
636 if ( size != 1 && size != 2 && size != 4) {
637 err_setstr(AudioopError, "Size should be 1, 2 or 4");
638 return 0;
639 }
640
641 /* Decode state, should have (value, step) */
642 if ( state == None ) {
643 /* First time, it seems. Set defaults */
644 valprev = 0;
645 step = 4; /* The '4' is magic. Dunno it's significance */
646 } else if ( !getargs(state, "(ii)", &valprev, &step) )
647 return 0;
648
649 str = newsizedstringobject(NULL, len*size);
650 if ( str == 0 )
651 return 0;
652 ncp = (signed char *)getstringvalue(str);
653
654 for ( i=0; i < len*size; i += size ) {
655 /* Step 1 - get the delta value */
656 delta = *cp++;
657
658 /* Step 2 - update output value */
659 valprev = valprev + delta*step;
660
661 /* Step 3 - clamp output value */
662 if ( valprev > 32767 )
663 valprev = 32767;
664 else if ( valprev < -32768 )
665 valprev = -32768;
666
667 /* Step 4 - Update step value */
668 step = step * newstep[abs(delta)];
669 step++;
670
671 /* Step 5 - Output value */
672 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valprev >> 8);
673 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valprev);
674 else if ( size == 4 ) *LONGP(ncp, i) = (long)(valprev<<16);
675 }
676
677 rv = mkvalue("(O(ii))", str, valprev, step);
678 DECREF(str);
679 return rv;
680}
681
Guido van Rossumb66efa01992-06-01 16:01:24 +0000682static struct methodlist audioop_methods[] = {
683 { "max", audioop_max },
684 { "avg", audioop_avg },
685 { "cross", audioop_cross },
686 { "mul", audioop_mul },
687 { "add", audioop_add },
688 { "bias", audioop_bias },
689 { "ulaw2lin", audioop_ulaw2lin },
690 { "lin2ulaw", audioop_lin2ulaw },
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000691 { "adpcm2lin", audioop_adpcm2lin },
692 { "lin2adpcm", audioop_lin2adpcm },
Guido van Rossumb66efa01992-06-01 16:01:24 +0000693 { "tomono", audioop_tomono },
694 { "tostereo", audioop_tostereo },
695 { "getsample", audioop_getsample },
696 { 0, 0 }
697};
698
699
700void
701initaudioop()
702{
703 object *m, *d;
704 m = initmodule("audioop", audioop_methods);
705 d = getmoduledict(m);
706 AudioopError = newstringobject("audioop.error");
707 if ( AudioopError == NULL || dictinsert(d,"error",AudioopError) )
708 fatal("can't define audioop.error");
709}