blob: d37ce8fd8328dc4b80e5b2119ced01fdfa2af882 [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 Rossumb64e6351992-07-06 14:21:56 +0000133/* ADPCM-3 step variation table */
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000134static float newstep[5] = { 0.8, 0.9, 1.0, 1.75, 1.75 };
135
Guido van Rossumb64e6351992-07-06 14:21:56 +0000136/* Intel ADPCM step variation table */
137static int indexTable[16] = {
138 -1, -1, -1, -1, 2, 4, 6, 8,
139 -1, -1, -1, -1, 2, 4, 6, 8,
140};
141
142static int stepsizeTable[89] = {
143 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
144 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
145 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
146 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
147 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
148 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
149 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
150 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
151 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
152};
153
Guido van Rossumb66efa01992-06-01 16:01:24 +0000154#define CHARP(cp, i) ((signed char *)(cp+i))
155#define SHORTP(cp, i) ((short *)(cp+i))
156#define LONGP(cp, i) ((long *)(cp+i))
157
158
159
160static object *AudioopError;
161
162static object *
163audioop_getsample(self, args)
164 object *self;
165 object *args;
166{
167 signed char *cp;
168 int len, size, val;
169 int i;
170
171 if ( !getargs(args, "(s#ii)", &cp, &len, &size, &i) )
172 return 0;
173 if ( size != 1 && size != 2 && size != 4 ) {
174 err_setstr(AudioopError, "Size should be 1, 2 or 4");
175 return 0;
176 }
177 if ( i < 0 || i >= len/size ) {
178 err_setstr(AudioopError, "Index out of range");
179 return 0;
180 }
181 if ( size == 1 ) val = (int)*CHARP(cp, i);
182 else if ( size == 2 ) val = (int)*SHORTP(cp, i*2);
183 else if ( size == 4 ) val = (int)*LONGP(cp, i*4);
184 return newintobject(val);
185}
186
187static object *
188audioop_max(self, args)
189 object *self;
190 object *args;
191{
192 signed char *cp;
193 int len, size, val;
194 int i;
195 int max = 0;
196
197 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
198 return 0;
199 if ( size != 1 && size != 2 && size != 4 ) {
200 err_setstr(AudioopError, "Size should be 1, 2 or 4");
201 return 0;
202 }
203 for ( i=0; i<len; i+= size) {
204 if ( size == 1 ) val = (int)*CHARP(cp, i);
205 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
206 else if ( size == 4 ) val = (int)*LONGP(cp, i);
207 if ( val < 0 ) val = (-val);
208 if ( val > max ) max = val;
209 }
210 return newintobject(max);
211}
212
213static object *
214audioop_avg(self, args)
215 object *self;
216 object *args;
217{
218 signed char *cp;
219 int len, size, val;
220 int i;
221 float avg = 0.0;
222
223 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
224 return 0;
225 if ( size != 1 && size != 2 && size != 4 ) {
226 err_setstr(AudioopError, "Size should be 1, 2 or 4");
227 return 0;
228 }
229 for ( i=0; i<len; i+= size) {
230 if ( size == 1 ) val = (int)*CHARP(cp, i);
231 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
232 else if ( size == 4 ) val = (int)*LONGP(cp, i);
233 avg += val;
234 }
235 if ( len == 0 )
236 val = 0;
237 else
238 val = (int)(avg / (float)(len/size));
239 return newintobject(val);
240}
241
242static object *
243audioop_cross(self, args)
244 object *self;
245 object *args;
246{
247 signed char *cp;
248 int len, size, val;
249 int i;
250 int cross, prevval, ncross;
251
252 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
253 return 0;
254 if ( size != 1 && size != 2 && size != 4 ) {
255 err_setstr(AudioopError, "Size should be 1, 2 or 4");
256 return 0;
257 }
258 ncross = -1;
259 prevval = 17; /* Anything <> 0,1 */
260 for ( i=0; i<len; i+= size) {
261 if ( size == 1 ) val = ((int)*CHARP(cp, i)) >> 7;
262 else if ( size == 2 ) val = ((int)*SHORTP(cp, i)) >> 15;
263 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 31;
264 val = val & 1;
265 if ( val != prevval ) ncross++;
266 prevval = val;
267 }
268 return newintobject(ncross);
269}
270
271static object *
272audioop_mul(self, args)
273 object *self;
274 object *args;
275{
276 signed char *cp, *ncp;
277 int len, size, val;
278 double factor, fval, maxval;
279 object *rv;
280 int i;
281
282 if ( !getargs(args, "(s#id)", &cp, &len, &size, &factor ) )
283 return 0;
284
285 if ( size == 1 ) maxval = (double) 0x7f;
286 else if ( size == 2 ) maxval = (double) 0x7fff;
287 else if ( size == 4 ) maxval = (double) 0x7fffffff;
288 else {
289 err_setstr(AudioopError, "Size should be 1, 2 or 4");
290 return 0;
291 }
292
293 rv = newsizedstringobject(NULL, len);
294 if ( rv == 0 )
295 return 0;
296 ncp = (signed char *)getstringvalue(rv);
297
298
299 for ( i=0; i < len; i += size ) {
300 if ( size == 1 ) val = (int)*CHARP(cp, i);
301 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
302 else if ( size == 4 ) val = (int)*LONGP(cp, i);
303 fval = (double)val*factor;
304 if ( fval > maxval ) fval = maxval;
305 else if ( fval < -maxval ) fval = -maxval;
306 val = (int)fval;
307 if ( size == 1 ) *CHARP(ncp, i) = (signed char)val;
308 else if ( size == 2 ) *SHORTP(ncp, i) = (short)val;
309 else if ( size == 4 ) *LONGP(ncp, i) = (long)val;
310 }
311 return rv;
312}
313
314static object *
315audioop_tomono(self, args)
316 object *self;
317 object *args;
318{
319 signed char *cp, *ncp;
320 int len, size, val1, val2;
321 double fac1, fac2, fval, maxval;
322 object *rv;
323 int i;
324
325 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
326 return 0;
327
328 if ( size == 1 ) maxval = (double) 0x7f;
329 else if ( size == 2 ) maxval = (double) 0x7fff;
330 else if ( size == 4 ) maxval = (double) 0x7fffffff;
331 else {
332 err_setstr(AudioopError, "Size should be 1, 2 or 4");
333 return 0;
334 }
335
336 rv = newsizedstringobject(NULL, len/2);
337 if ( rv == 0 )
338 return 0;
339 ncp = (signed char *)getstringvalue(rv);
340
341
342 for ( i=0; i < len; i += size*2 ) {
343 if ( size == 1 ) val1 = (int)*CHARP(cp, i);
344 else if ( size == 2 ) val1 = (int)*SHORTP(cp, i);
345 else if ( size == 4 ) val1 = (int)*LONGP(cp, i);
346 if ( size == 1 ) val2 = (int)*CHARP(cp, i+1);
347 else if ( size == 2 ) val2 = (int)*SHORTP(cp, i+2);
348 else if ( size == 4 ) val2 = (int)*LONGP(cp, i+4);
349 fval = (double)val1*fac1 + (double)val2*fac2;
350 if ( fval > maxval ) fval = maxval;
351 else if ( fval < -maxval ) fval = -maxval;
352 val1 = (int)fval;
353 if ( size == 1 ) *CHARP(ncp, i/2) = (signed char)val1;
354 else if ( size == 2 ) *SHORTP(ncp, i/2) = (short)val1;
355 else if ( size == 4 ) *LONGP(ncp, i/2)= (long)val1;
356 }
357 return rv;
358}
359
360static object *
361audioop_tostereo(self, args)
362 object *self;
363 object *args;
364{
365 signed char *cp, *ncp;
366 int len, size, val1, val2, val;
367 double fac1, fac2, fval, maxval;
368 object *rv;
369 int i;
370
371 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
372 return 0;
373
374 if ( size == 1 ) maxval = (double) 0x7f;
375 else if ( size == 2 ) maxval = (double) 0x7fff;
376 else if ( size == 4 ) maxval = (double) 0x7fffffff;
377 else {
378 err_setstr(AudioopError, "Size should be 1, 2 or 4");
379 return 0;
380 }
381
382 rv = newsizedstringobject(NULL, len*2);
383 if ( rv == 0 )
384 return 0;
385 ncp = (signed char *)getstringvalue(rv);
386
387
388 for ( i=0; i < len; i += size ) {
389 if ( size == 1 ) val = (int)*CHARP(cp, i);
390 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
391 else if ( size == 4 ) val = (int)*LONGP(cp, i);
392
393 fval = (double)val*fac1;
394 if ( fval > maxval ) fval = maxval;
395 else if ( fval < -maxval ) fval = -maxval;
396 val1 = (int)fval;
397
398 fval = (double)val*fac2;
399 if ( fval > maxval ) fval = maxval;
400 else if ( fval < -maxval ) fval = -maxval;
401 val2 = (int)fval;
402
403 if ( size == 1 ) *CHARP(ncp, i*2) = (signed char)val1;
404 else if ( size == 2 ) *SHORTP(ncp, i*2) = (short)val1;
405 else if ( size == 4 ) *LONGP(ncp, i*2) = (long)val1;
406
407 if ( size == 1 ) *CHARP(ncp, i*2+1) = (signed char)val2;
408 else if ( size == 2 ) *SHORTP(ncp, i*2+2) = (short)val2;
409 else if ( size == 4 ) *LONGP(ncp, i*2+4) = (long)val2;
410 }
411 return rv;
412}
413
414static object *
415audioop_add(self, args)
416 object *self;
417 object *args;
418{
419 signed char *cp1, *cp2, *ncp;
420 int len1, len2, size, val1, val2;
421 object *rv;
422 int i;
423
424 if ( !getargs(args, "(s#s#i)",
425 &cp1, &len1, &cp2, &len2, &size ) )
426 return 0;
427
428 if ( len1 != len2 ) {
429 err_setstr(AudioopError, "Lengths should be the same");
430 return 0;
431 }
432
433 if ( size != 1 && size != 2 && size != 4) {
434 err_setstr(AudioopError, "Size should be 1, 2 or 4");
435 return 0;
436 }
437
438 rv = newsizedstringobject(NULL, len1);
439 if ( rv == 0 )
440 return 0;
441 ncp = (signed char *)getstringvalue(rv);
442
443
444 for ( i=0; i < len1; i += size ) {
445 if ( size == 1 ) val1 = (int)*CHARP(cp1, i);
446 else if ( size == 2 ) val1 = (int)*SHORTP(cp1, i);
447 else if ( size == 4 ) val1 = (int)*LONGP(cp1, i);
448
449 if ( size == 1 ) val2 = (int)*CHARP(cp2, i);
450 else if ( size == 2 ) val2 = (int)*SHORTP(cp2, i);
451 else if ( size == 4 ) val2 = (int)*LONGP(cp2, i);
452
453 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val1+val2);
454 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val1+val2);
455 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val1+val2);
456 }
457 return rv;
458}
459
460static object *
461audioop_bias(self, args)
462 object *self;
463 object *args;
464{
465 signed char *cp, *ncp;
466 int len, size, val;
467 object *rv;
468 int i;
469 int bias;
470
471 if ( !getargs(args, "(s#ii)",
472 &cp, &len, &size , &bias) )
473 return 0;
474
475 if ( size != 1 && size != 2 && size != 4) {
476 err_setstr(AudioopError, "Size should be 1, 2 or 4");
477 return 0;
478 }
479
480 rv = newsizedstringobject(NULL, len);
481 if ( rv == 0 )
482 return 0;
483 ncp = (signed char *)getstringvalue(rv);
484
485
486 for ( i=0; i < len; i += size ) {
487 if ( size == 1 ) val = (int)*CHARP(cp, i);
488 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
489 else if ( size == 4 ) val = (int)*LONGP(cp, i);
490
491 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val+bias);
492 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val+bias);
493 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val+bias);
494 }
495 return rv;
496}
497
498static object *
499audioop_lin2ulaw(self, args)
500 object *self;
501 object *args;
502{
503 signed char *cp;
504 unsigned char *ncp;
505 int len, size, val;
506 object *rv;
507 int i;
508
509 if ( !getargs(args, "(s#i)",
510 &cp, &len, &size) )
511 return 0;
512
513 if ( size != 1 && size != 2 && size != 4) {
514 err_setstr(AudioopError, "Size should be 1, 2 or 4");
515 return 0;
516 }
517
518 rv = newsizedstringobject(NULL, len/size);
519 if ( rv == 0 )
520 return 0;
521 ncp = (unsigned char *)getstringvalue(rv);
522
523 for ( i=0; i < len; i += size ) {
524 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
525 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
526 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
527
528 *ncp++ = st_linear_to_ulaw(val);
529 }
530 return rv;
531}
532
533static object *
534audioop_ulaw2lin(self, args)
535 object *self;
536 object *args;
537{
538 unsigned char *cp;
539 unsigned char cval;
540 signed char *ncp;
541 int len, size, val;
542 object *rv;
543 int i;
544
545 if ( !getargs(args, "(s#i)",
546 &cp, &len, &size) )
547 return 0;
548
549 if ( size != 1 && size != 2 && size != 4) {
550 err_setstr(AudioopError, "Size should be 1, 2 or 4");
551 return 0;
552 }
553
554 rv = newsizedstringobject(NULL, len*size);
555 if ( rv == 0 )
556 return 0;
557 ncp = (signed char *)getstringvalue(rv);
558
559 for ( i=0; i < len*size; i += size ) {
560 cval = *cp++;
561 val = st_ulaw_to_linear(cval);
562
563 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val >> 8);
564 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val);
Guido van Rossumaad53441992-06-05 15:11:56 +0000565 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val<<16);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000566 }
567 return rv;
568}
569
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000570static object *
Guido van Rossumb64e6351992-07-06 14:21:56 +0000571audioop_lin2adpcm3(self, args)
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000572 object *self;
573 object *args;
574{
575 signed char *cp;
576 signed char *ncp;
577 int len, size, val, step, valprev, delta;
578 object *rv, *state, *str;
579 int i;
580
581 if ( !getargs(args, "(s#iO)",
582 &cp, &len, &size, &state) )
583 return 0;
584
585
586 if ( size != 1 && size != 2 && size != 4) {
587 err_setstr(AudioopError, "Size should be 1, 2 or 4");
588 return 0;
589 }
590
591 str = newsizedstringobject(NULL, len/size);
592 if ( str == 0 )
593 return 0;
594 ncp = (signed char *)getstringvalue(str);
595
596 /* Decode state, should have (value, step) */
597 if ( state == None ) {
598 /* First time, it seems. Set defaults */
599 valprev = 0;
600 step = 4; /* The '4' is magic. Dunno it's significance */
601 } else if ( !getargs(state, "(ii)", &valprev, &step) )
602 return 0;
603
604 for ( i=0; i < len; i += size ) {
605 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
606 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
607 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
608
609 /* Step 1 - compute difference with previous value */
610 delta = (val - valprev)/step;
611
612 /* Step 2 - Clamp */
613 if ( delta < -4 )
614 delta = -4;
615 else if ( delta > 3 )
616 delta = 3;
617
618 /* Step 3 - Update previous value */
619 valprev += delta*step;
620
621 /* Step 4 - Clamp previous value to 16 bits */
622 if ( valprev > 32767 )
623 valprev = 32767;
624 else if ( valprev < -32768 )
625 valprev = -32768;
626
627 /* Step 5 - Update step value */
628 step = step * newstep[abs(delta)];
629 step++; /* Don't understand this. */
630
631 /* Step 6 - Output value (as a whole byte, currently) */
632 *ncp++ = delta;
633 }
634 rv = mkvalue("(O(ii))", str, valprev, step);
635 DECREF(str);
636 return rv;
637}
638
639static object *
Guido van Rossumb64e6351992-07-06 14:21:56 +0000640audioop_adpcm32lin(self, args)
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000641 object *self;
642 object *args;
643{
644 signed char *cp;
645 signed char *ncp;
646 int len, size, val, valprev, step, delta;
647 object *rv, *str, *state;
648 int i;
649
650 if ( !getargs(args, "(s#iO)",
651 &cp, &len, &size, &state) )
652 return 0;
653
654 if ( size != 1 && size != 2 && size != 4) {
655 err_setstr(AudioopError, "Size should be 1, 2 or 4");
656 return 0;
657 }
658
659 /* Decode state, should have (value, step) */
660 if ( state == None ) {
661 /* First time, it seems. Set defaults */
662 valprev = 0;
663 step = 4; /* The '4' is magic. Dunno it's significance */
664 } else if ( !getargs(state, "(ii)", &valprev, &step) )
665 return 0;
666
667 str = newsizedstringobject(NULL, len*size);
668 if ( str == 0 )
669 return 0;
670 ncp = (signed char *)getstringvalue(str);
671
672 for ( i=0; i < len*size; i += size ) {
673 /* Step 1 - get the delta value */
674 delta = *cp++;
675
676 /* Step 2 - update output value */
677 valprev = valprev + delta*step;
678
679 /* Step 3 - clamp output value */
680 if ( valprev > 32767 )
681 valprev = 32767;
682 else if ( valprev < -32768 )
683 valprev = -32768;
684
685 /* Step 4 - Update step value */
686 step = step * newstep[abs(delta)];
687 step++;
688
689 /* Step 5 - Output value */
690 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valprev >> 8);
691 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valprev);
692 else if ( size == 4 ) *LONGP(ncp, i) = (long)(valprev<<16);
693 }
694
695 rv = mkvalue("(O(ii))", str, valprev, step);
696 DECREF(str);
697 return rv;
698}
699
Guido van Rossumb64e6351992-07-06 14:21:56 +0000700static object *
701audioop_lin2adpcm(self, args)
702 object *self;
703 object *args;
704{
705 signed char *cp;
706 signed char *ncp;
707 int len, size, val, step, valprev, delta, index, sign;
708 object *rv, *state, *str;
709 int i, outputbuffer, bufferstep;
710
711 if ( !getargs(args, "(s#iO)",
712 &cp, &len, &size, &state) )
713 return 0;
714
715
716 if ( size != 1 && size != 2 && size != 4) {
717 err_setstr(AudioopError, "Size should be 1, 2 or 4");
718 return 0;
719 }
720
721 str = newsizedstringobject(NULL, len/(size*2));
722 if ( str == 0 )
723 return 0;
724 ncp = (signed char *)getstringvalue(str);
725
726 /* Decode state, should have (value, step) */
727 if ( state == None ) {
728 /* First time, it seems. Set defaults */
729 valprev = 0;
730 step = 7;
731 index = 0;
732 } else if ( !getargs(state, "(iii)", &valprev, &step, &index) )
733 return 0;
734
735 bufferstep = 1;
736
737 for ( i=0; i < len; i += size ) {
738 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
739 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
740 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
741
742 /* Step 1 - compute difference with previous value */
743 delta = val - valprev;
744 sign = (delta < 0) ? 8 : 0;
745 if ( sign ) delta = (-delta);
746
747 /* Step 2 - Divide and clamp */
748#ifdef NODIVIDE
749 Program using shifts and subtracts;
750#else
751 delta = (delta<<2) / step;
752 if ( delta > 7 ) delta = 7;
753#endif
754
755 /* Step 3 - Update previous value */
756 if ( sign )
757 valprev -= (delta*step)>>2;
758 else
759 valprev += (delta*step)>>2;
760
761 /* Step 4 - Clamp previous value to 16 bits */
762 if ( valprev > 32767 )
763 valprev = 32767;
764 else if ( valprev < -32768 )
765 valprev = -32768;
766
767 /* Step 5 - Assemble value, update index and step values */
768 delta |= sign;
769
770 index += indexTable[delta];
771 if ( index < 0 ) index = 0;
772 if ( index > 88 ) index = 88;
773 step = stepsizeTable[index];
774
775 /* Step 6 - Output value (as a whole byte, currently) */
776 if ( bufferstep ) {
777 outputbuffer = (delta << 4);
778 } else {
779 *ncp++ = delta | outputbuffer;
780 }
781 bufferstep = !bufferstep;
782 }
783 rv = mkvalue("(O(iii))", str, valprev, step, index);
784 DECREF(str);
785 return rv;
786}
787
788static object *
789audioop_adpcm2lin(self, args)
790 object *self;
791 object *args;
792{
793 signed char *cp;
794 signed char *ncp;
795 int len, size, val, valprev, step, delta, index, sign;
796 object *rv, *str, *state;
797 int i, inputbuffer, bufferstep;
798
799 if ( !getargs(args, "(s#iO)",
800 &cp, &len, &size, &state) )
801 return 0;
802
803 if ( size != 1 && size != 2 && size != 4) {
804 err_setstr(AudioopError, "Size should be 1, 2 or 4");
805 return 0;
806 }
807
808 /* Decode state, should have (value, step) */
809 if ( state == None ) {
810 /* First time, it seems. Set defaults */
811 valprev = 0;
812 step = 7;
813 index = 0;
814 } else if ( !getargs(state, "(iii)", &valprev, &step, &index) )
815 return 0;
816
817 str = newsizedstringobject(NULL, len*size*2);
818 if ( str == 0 )
819 return 0;
820 ncp = (signed char *)getstringvalue(str);
821
822 bufferstep = 0;
823
824 for ( i=0; i < len*size*2; i += size ) {
825 /* Step 1 - get the delta value and compute next index */
826 if ( bufferstep ) {
827 delta = inputbuffer & 0xf;
828 } else {
829 inputbuffer = *cp++;
830 delta = (inputbuffer >> 4) & 0xf;
831 }
832
833 bufferstep = !bufferstep;
834
835 index += indexTable[delta];
836 if ( index < 0 ) index = 0;
837 if ( index > 88 ) index = 88;
838
839 /* Step 2 - Separate sign and magnitude */
840 sign = delta & 8;
841 delta = delta & 7;
842
843 /* Step 3 - update output value */
844 if ( sign )
845 valprev -= (delta*step) >> 2;
846 else
847 valprev += (delta*step) >> 2;
848
849 /* Step 4 - clamp output value */
850 if ( valprev > 32767 )
851 valprev = 32767;
852 else if ( valprev < -32768 )
853 valprev = -32768;
854
855 /* Step 5 - Update step value */
856 step = stepsizeTable[index];
857
858 /* Step 6 - Output value */
859 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valprev >> 8);
860 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valprev);
861 else if ( size == 4 ) *LONGP(ncp, i) = (long)(valprev<<16);
862 }
863
864 rv = mkvalue("(O(iii))", str, valprev, step, index);
865 DECREF(str);
866 return rv;
867}
868
Guido van Rossumb66efa01992-06-01 16:01:24 +0000869static struct methodlist audioop_methods[] = {
870 { "max", audioop_max },
871 { "avg", audioop_avg },
872 { "cross", audioop_cross },
873 { "mul", audioop_mul },
874 { "add", audioop_add },
875 { "bias", audioop_bias },
876 { "ulaw2lin", audioop_ulaw2lin },
877 { "lin2ulaw", audioop_lin2ulaw },
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000878 { "adpcm2lin", audioop_adpcm2lin },
879 { "lin2adpcm", audioop_lin2adpcm },
Guido van Rossumb64e6351992-07-06 14:21:56 +0000880 { "adpcm32lin", audioop_adpcm32lin },
881 { "lin2adpcm3", audioop_lin2adpcm3 },
Guido van Rossumb66efa01992-06-01 16:01:24 +0000882 { "tomono", audioop_tomono },
883 { "tostereo", audioop_tostereo },
884 { "getsample", audioop_getsample },
885 { 0, 0 }
886};
887
888
889void
890initaudioop()
891{
892 object *m, *d;
893 m = initmodule("audioop", audioop_methods);
894 d = getmoduledict(m);
895 AudioopError = newstringobject("audioop.error");
896 if ( AudioopError == NULL || dictinsert(d,"error",AudioopError) )
897 fatal("can't define audioop.error");
898}