This commit was manufactured by cvs2svn to create tag 'mac102'.
[python/dscho.git] / Modules / audioop.c
blobcfb97f2904e96872827732d61d56f7a170800ec5
1 /***********************************************************
2 Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
3 Amsterdam, The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 /* audioopmodule - Module to detect peak values in arrays */
27 #include "allobjects.h"
28 #include "modsupport.h"
30 #if defined(__CHAR_UNSIGNED__) && defined(signed)
31 !ERROR!; READ THE SOURCE FILE!;
32 /* This module currently does not work on systems where only unsigned
33 characters are available. Take it out of Setup. Sorry. */
34 #endif
36 #include <math.h>
38 /* Code shamelessly stolen from sox,
39 ** (c) Craig Reese, Joe Campbell and Jeff Poskanzer 1989 */
41 #define MINLIN -32768
42 #define MAXLIN 32767
43 #define LINCLIP(x) do { if ( x < MINLIN ) x = MINLIN ; else if ( x > MAXLIN ) x = MAXLIN; } while ( 0 )
45 unsigned char st_linear_to_ulaw( /* int sample */ );
48 ** This macro converts from ulaw to 16 bit linear, faster.
50 ** Jef Poskanzer
51 ** 23 October 1989
53 ** Input: 8 bit ulaw sample
54 ** Output: signed 16 bit linear sample
56 #define st_ulaw_to_linear(ulawbyte) ulaw_table[ulawbyte]
58 static int ulaw_table[256] = {
59 -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
60 -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
61 -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
62 -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316,
63 -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
64 -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
65 -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
66 -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
67 -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
68 -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
69 -876, -844, -812, -780, -748, -716, -684, -652,
70 -620, -588, -556, -524, -492, -460, -428, -396,
71 -372, -356, -340, -324, -308, -292, -276, -260,
72 -244, -228, -212, -196, -180, -164, -148, -132,
73 -120, -112, -104, -96, -88, -80, -72, -64,
74 -56, -48, -40, -32, -24, -16, -8, 0,
75 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
76 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
77 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
78 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
79 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
80 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
81 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
82 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
83 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
84 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
85 876, 844, 812, 780, 748, 716, 684, 652,
86 620, 588, 556, 524, 492, 460, 428, 396,
87 372, 356, 340, 324, 308, 292, 276, 260,
88 244, 228, 212, 196, 180, 164, 148, 132,
89 120, 112, 104, 96, 88, 80, 72, 64,
90 56, 48, 40, 32, 24, 16, 8, 0 };
92 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
93 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
94 #define CLIP 32635
96 unsigned char
97 st_linear_to_ulaw( sample )
98 int sample;
100 static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
101 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
102 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
103 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
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 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
107 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
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 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
115 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
116 int sign, exponent, mantissa;
117 unsigned char ulawbyte;
119 /* Get the sample into sign-magnitude. */
120 sign = (sample >> 8) & 0x80; /* set aside the sign */
121 if ( sign != 0 ) sample = -sample; /* get magnitude */
122 if ( sample > CLIP ) sample = CLIP; /* clip the magnitude */
124 /* Convert from 16 bit linear to ulaw. */
125 sample = sample + BIAS;
126 exponent = exp_lut[( sample >> 7 ) & 0xFF];
127 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
128 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
129 #ifdef ZEROTRAP
130 if ( ulawbyte == 0 ) ulawbyte = 0x02; /* optional CCITT trap */
131 #endif
133 return ulawbyte;
135 /* End of code taken from sox */
137 /* ADPCM-3 step variation table */
138 static float newstep[5] = { 0.8, 0.9, 1.0, 1.75, 1.75 };
140 /* Intel ADPCM step variation table */
141 static int indexTable[16] = {
142 -1, -1, -1, -1, 2, 4, 6, 8,
143 -1, -1, -1, -1, 2, 4, 6, 8,
146 static int stepsizeTable[89] = {
147 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
148 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
149 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
150 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
151 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
152 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
153 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
154 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
155 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
158 #define CHARP(cp, i) ((signed char *)(cp+i))
159 #define SHORTP(cp, i) ((short *)(cp+i))
160 #define LONGP(cp, i) ((long *)(cp+i))
164 static object *AudioopError;
166 static object *
167 audioop_getsample(self, args)
168 object *self;
169 object *args;
171 signed char *cp;
172 int len, size, val;
173 int i;
175 if ( !getargs(args, "(s#ii)", &cp, &len, &size, &i) )
176 return 0;
177 if ( size != 1 && size != 2 && size != 4 ) {
178 err_setstr(AudioopError, "Size should be 1, 2 or 4");
179 return 0;
181 if ( i < 0 || i >= len/size ) {
182 err_setstr(AudioopError, "Index out of range");
183 return 0;
185 if ( size == 1 ) val = (int)*CHARP(cp, i);
186 else if ( size == 2 ) val = (int)*SHORTP(cp, i*2);
187 else if ( size == 4 ) val = (int)*LONGP(cp, i*4);
188 return newintobject(val);
191 static object *
192 audioop_max(self, args)
193 object *self;
194 object *args;
196 signed char *cp;
197 int len, size, val;
198 int i;
199 int max = 0;
201 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
202 return 0;
203 if ( size != 1 && size != 2 && size != 4 ) {
204 err_setstr(AudioopError, "Size should be 1, 2 or 4");
205 return 0;
207 for ( i=0; i<len; i+= size) {
208 if ( size == 1 ) val = (int)*CHARP(cp, i);
209 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
210 else if ( size == 4 ) val = (int)*LONGP(cp, i);
211 if ( val < 0 ) val = (-val);
212 if ( val > max ) max = val;
214 return newintobject(max);
217 static object *
218 audioop_avg(self, args)
219 object *self;
220 object *args;
222 signed char *cp;
223 int len, size, val;
224 int i;
225 float avg = 0.0;
227 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
228 return 0;
229 if ( size != 1 && size != 2 && size != 4 ) {
230 err_setstr(AudioopError, "Size should be 1, 2 or 4");
231 return 0;
233 for ( i=0; i<len; i+= size) {
234 if ( size == 1 ) val = (int)*CHARP(cp, i);
235 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
236 else if ( size == 4 ) val = (int)*LONGP(cp, i);
237 avg += val;
239 if ( len == 0 )
240 val = 0;
241 else
242 val = (int)(avg / (float)(len/size));
243 return newintobject(val);
246 static object *
247 audioop_rms(self, args)
248 object *self;
249 object *args;
251 signed char *cp;
252 int len, size, val;
253 int i;
254 float sum_squares = 0.0;
256 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
257 return 0;
258 if ( size != 1 && size != 2 && size != 4 ) {
259 err_setstr(AudioopError, "Size should be 1, 2 or 4");
260 return 0;
262 for ( i=0; i<len; i+= size) {
263 if ( size == 1 ) val = (int)*CHARP(cp, i);
264 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
265 else if ( size == 4 ) val = (int)*LONGP(cp, i);
266 sum_squares += (float)val*(float)val;
268 if ( len == 0 )
269 val = 0;
270 else
271 val = (int)sqrt(sum_squares / (float)(len/size));
272 return newintobject(val);
275 double _sum2(a, b, len)
276 short *a;
277 short *b;
278 int len;
280 int i;
281 double sum = 0.0;
283 for( i=0; i<len; i++) {
284 sum = sum + (double)a[i]*(double)b[i];
286 return sum;
290 ** Findfit tries to locate a sample within another sample. Its main use
291 ** is in echo-cancellation (to find the feedback of the output signal in
292 ** the input signal).
293 ** The method used is as follows:
295 ** let R be the reference signal (length n) and A the input signal (length N)
296 ** with N > n, and let all sums be over i from 0 to n-1.
298 ** Now, for each j in {0..N-n} we compute a factor fj so that -fj*R matches A
299 ** as good as possible, i.e. sum( (A[j+i]+fj*R[i])^2 ) is minimal. This
300 ** equation gives fj = sum( A[j+i]R[i] ) / sum(R[i]^2).
302 ** Next, we compute the relative distance between the original signal and
303 ** the modified signal and minimize that over j:
304 ** vj = sum( (A[j+i]-fj*R[i])^2 ) / sum( A[j+i]^2 ) =>
305 ** vj = ( sum(A[j+i]^2)*sum(R[i]^2) - sum(A[j+i]R[i])^2 ) / sum( A[j+i]^2 )
307 ** In the code variables correspond as follows:
308 ** cp1 A
309 ** cp2 R
310 ** len1 N
311 ** len2 n
312 ** aj_m1 A[j-1]
313 ** aj_lm1 A[j+n-1]
314 ** sum_ri_2 sum(R[i]^2)
315 ** sum_aij_2 sum(A[i+j]^2)
316 ** sum_aij_ri sum(A[i+j]R[i])
318 ** sum_ri is calculated once, sum_aij_2 is updated each step and sum_aij_ri
319 ** is completely recalculated each step.
321 static object *
322 audioop_findfit(self, args)
323 object *self;
324 object *args;
326 short *cp1, *cp2;
327 int len1, len2;
328 int j, best_j;
329 double aj_m1, aj_lm1;
330 double sum_ri_2, sum_aij_2, sum_aij_ri, result, best_result, factor;
332 if ( !getargs(args, "(s#s#)", &cp1, &len1, &cp2, &len2) )
333 return 0;
334 if ( len1 & 1 || len2 & 1 ) {
335 err_setstr(AudioopError, "Strings should be even-sized");
336 return 0;
338 len1 >>= 1;
339 len2 >>= 1;
341 if ( len1 < len2 ) {
342 err_setstr(AudioopError, "First sample should be longer");
343 return 0;
345 sum_ri_2 = _sum2(cp2, cp2, len2);
346 sum_aij_2 = _sum2(cp1, cp1, len2);
347 sum_aij_ri = _sum2(cp1, cp2, len2);
349 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
351 best_result = result;
352 best_j = 0;
353 j = 0;
355 for ( j=1; j<=len1-len2; j++) {
356 aj_m1 = (double)cp1[j-1];
357 aj_lm1 = (double)cp1[j+len2-1];
359 sum_aij_2 = sum_aij_2 + aj_lm1*aj_lm1 - aj_m1*aj_m1;
360 sum_aij_ri = _sum2(cp1+j, cp2, len2);
362 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
364 if ( result < best_result ) {
365 best_result = result;
366 best_j = j;
371 factor = _sum2(cp1+best_j, cp2, len2) / sum_ri_2;
373 return mkvalue("(if)", best_j, factor);
377 ** findfactor finds a factor f so that the energy in A-fB is minimal.
378 ** See the comment for findfit for details.
380 static object *
381 audioop_findfactor(self, args)
382 object *self;
383 object *args;
385 short *cp1, *cp2;
386 int len1, len2;
387 double sum_ri_2, sum_aij_ri, result;
389 if ( !getargs(args, "(s#s#)", &cp1, &len1, &cp2, &len2) )
390 return 0;
391 if ( len1 & 1 || len2 & 1 ) {
392 err_setstr(AudioopError, "Strings should be even-sized");
393 return 0;
395 if ( len1 != len2 ) {
396 err_setstr(AudioopError, "Samples should be same size");
397 return 0;
399 len2 >>= 1;
400 sum_ri_2 = _sum2(cp2, cp2, len2);
401 sum_aij_ri = _sum2(cp1, cp2, len2);
403 result = sum_aij_ri / sum_ri_2;
405 return newfloatobject(result);
409 ** findmax returns the index of the n-sized segment of the input sample
410 ** that contains the most energy.
412 static object *
413 audioop_findmax(self, args)
414 object *self;
415 object *args;
417 short *cp1;
418 int len1, len2;
419 int j, best_j;
420 double aj_m1, aj_lm1;
421 double result, best_result;
423 if ( !getargs(args, "(s#i)", &cp1, &len1, &len2) )
424 return 0;
425 if ( len1 & 1 ) {
426 err_setstr(AudioopError, "Strings should be even-sized");
427 return 0;
429 len1 >>= 1;
431 if ( len1 < len2 ) {
432 err_setstr(AudioopError, "Input sample should be longer");
433 return 0;
436 result = _sum2(cp1, cp1, len2);
438 best_result = result;
439 best_j = 0;
440 j = 0;
442 for ( j=1; j<=len1-len2; j++) {
443 aj_m1 = (double)cp1[j-1];
444 aj_lm1 = (double)cp1[j+len2-1];
446 result = result + aj_lm1*aj_lm1 - aj_m1*aj_m1;
448 if ( result > best_result ) {
449 best_result = result;
450 best_j = j;
455 return newintobject(best_j);
458 static object *
459 audioop_avgpp(self, args)
460 object *self;
461 object *args;
463 signed char *cp;
464 int len, size, val, prevval, prevextremevalid = 0, prevextreme;
465 int i;
466 float avg = 0.0;
467 int diff, prevdiff, extremediff, nextreme = 0;
469 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
470 return 0;
471 if ( size != 1 && size != 2 && size != 4 ) {
472 err_setstr(AudioopError, "Size should be 1, 2 or 4");
473 return 0;
475 /* Compute first delta value ahead. Also automatically makes us
476 ** skip the first extreme value
478 if ( size == 1 ) prevval = (int)*CHARP(cp, 0);
479 else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
480 else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
481 if ( size == 1 ) val = (int)*CHARP(cp, size);
482 else if ( size == 2 ) val = (int)*SHORTP(cp, size);
483 else if ( size == 4 ) val = (int)*LONGP(cp, size);
484 prevdiff = val - prevval;
486 for ( i=size; 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 diff = val - prevval;
491 if ( diff*prevdiff < 0 ) {
492 /* Derivative changed sign. Compute difference to last extreme
493 ** value and remember.
495 if ( prevextremevalid ) {
496 extremediff = prevval - prevextreme;
497 if ( extremediff < 0 )
498 extremediff = -extremediff;
499 avg += extremediff;
500 nextreme++;
502 prevextremevalid = 1;
503 prevextreme = prevval;
505 prevval = val;
506 if ( diff != 0 )
507 prevdiff = diff;
509 if ( nextreme == 0 )
510 val = 0;
511 else
512 val = (int)(avg / (float)nextreme);
513 return newintobject(val);
516 static object *
517 audioop_maxpp(self, args)
518 object *self;
519 object *args;
521 signed char *cp;
522 int len, size, val, prevval, prevextremevalid = 0, prevextreme;
523 int i;
524 int max = 0;
525 int diff, prevdiff, extremediff;
527 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
528 return 0;
529 if ( size != 1 && size != 2 && size != 4 ) {
530 err_setstr(AudioopError, "Size should be 1, 2 or 4");
531 return 0;
533 /* Compute first delta value ahead. Also automatically makes us
534 ** skip the first extreme value
536 if ( size == 1 ) prevval = (int)*CHARP(cp, 0);
537 else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
538 else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
539 if ( size == 1 ) val = (int)*CHARP(cp, size);
540 else if ( size == 2 ) val = (int)*SHORTP(cp, size);
541 else if ( size == 4 ) val = (int)*LONGP(cp, size);
542 prevdiff = val - prevval;
544 for ( i=size; i<len; i+= size) {
545 if ( size == 1 ) val = (int)*CHARP(cp, i);
546 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
547 else if ( size == 4 ) val = (int)*LONGP(cp, i);
548 diff = val - prevval;
549 if ( diff*prevdiff < 0 ) {
550 /* Derivative changed sign. Compute difference to last extreme
551 ** value and remember.
553 if ( prevextremevalid ) {
554 extremediff = prevval - prevextreme;
555 if ( extremediff < 0 )
556 extremediff = -extremediff;
557 if ( extremediff > max )
558 max = extremediff;
560 prevextremevalid = 1;
561 prevextreme = prevval;
563 prevval = val;
564 if ( diff != 0 )
565 prevdiff = diff;
567 return newintobject(max);
570 static object *
571 audioop_cross(self, args)
572 object *self;
573 object *args;
575 signed char *cp;
576 int len, size, val;
577 int i;
578 int cross, prevval, ncross;
580 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
581 return 0;
582 if ( size != 1 && size != 2 && size != 4 ) {
583 err_setstr(AudioopError, "Size should be 1, 2 or 4");
584 return 0;
586 ncross = -1;
587 prevval = 17; /* Anything <> 0,1 */
588 for ( i=0; i<len; i+= size) {
589 if ( size == 1 ) val = ((int)*CHARP(cp, i)) >> 7;
590 else if ( size == 2 ) val = ((int)*SHORTP(cp, i)) >> 15;
591 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 31;
592 val = val & 1;
593 if ( val != prevval ) ncross++;
594 prevval = val;
596 return newintobject(ncross);
599 static object *
600 audioop_mul(self, args)
601 object *self;
602 object *args;
604 signed char *cp, *ncp;
605 int len, size, val;
606 double factor, fval, maxval;
607 object *rv;
608 int i;
610 if ( !getargs(args, "(s#id)", &cp, &len, &size, &factor ) )
611 return 0;
613 if ( size == 1 ) maxval = (double) 0x7f;
614 else if ( size == 2 ) maxval = (double) 0x7fff;
615 else if ( size == 4 ) maxval = (double) 0x7fffffff;
616 else {
617 err_setstr(AudioopError, "Size should be 1, 2 or 4");
618 return 0;
621 rv = newsizedstringobject(NULL, len);
622 if ( rv == 0 )
623 return 0;
624 ncp = (signed char *)getstringvalue(rv);
627 for ( i=0; i < len; i += size ) {
628 if ( size == 1 ) val = (int)*CHARP(cp, i);
629 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
630 else if ( size == 4 ) val = (int)*LONGP(cp, i);
631 fval = (double)val*factor;
632 if ( fval > maxval ) fval = maxval;
633 else if ( fval < -maxval ) fval = -maxval;
634 val = (int)fval;
635 if ( size == 1 ) *CHARP(ncp, i) = (signed char)val;
636 else if ( size == 2 ) *SHORTP(ncp, i) = (short)val;
637 else if ( size == 4 ) *LONGP(ncp, i) = (long)val;
639 return rv;
642 static object *
643 audioop_tomono(self, args)
644 object *self;
645 object *args;
647 signed char *cp, *ncp;
648 int len, size, val1, val2;
649 double fac1, fac2, fval, maxval;
650 object *rv;
651 int i;
653 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
654 return 0;
656 if ( size == 1 ) maxval = (double) 0x7f;
657 else if ( size == 2 ) maxval = (double) 0x7fff;
658 else if ( size == 4 ) maxval = (double) 0x7fffffff;
659 else {
660 err_setstr(AudioopError, "Size should be 1, 2 or 4");
661 return 0;
664 rv = newsizedstringobject(NULL, len/2);
665 if ( rv == 0 )
666 return 0;
667 ncp = (signed char *)getstringvalue(rv);
670 for ( i=0; i < len; i += size*2 ) {
671 if ( size == 1 ) val1 = (int)*CHARP(cp, i);
672 else if ( size == 2 ) val1 = (int)*SHORTP(cp, i);
673 else if ( size == 4 ) val1 = (int)*LONGP(cp, i);
674 if ( size == 1 ) val2 = (int)*CHARP(cp, i+1);
675 else if ( size == 2 ) val2 = (int)*SHORTP(cp, i+2);
676 else if ( size == 4 ) val2 = (int)*LONGP(cp, i+4);
677 fval = (double)val1*fac1 + (double)val2*fac2;
678 if ( fval > maxval ) fval = maxval;
679 else if ( fval < -maxval ) fval = -maxval;
680 val1 = (int)fval;
681 if ( size == 1 ) *CHARP(ncp, i/2) = (signed char)val1;
682 else if ( size == 2 ) *SHORTP(ncp, i/2) = (short)val1;
683 else if ( size == 4 ) *LONGP(ncp, i/2)= (long)val1;
685 return rv;
688 static object *
689 audioop_tostereo(self, args)
690 object *self;
691 object *args;
693 signed char *cp, *ncp;
694 int len, size, val1, val2, val;
695 double fac1, fac2, fval, maxval;
696 object *rv;
697 int i;
699 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
700 return 0;
702 if ( size == 1 ) maxval = (double) 0x7f;
703 else if ( size == 2 ) maxval = (double) 0x7fff;
704 else if ( size == 4 ) maxval = (double) 0x7fffffff;
705 else {
706 err_setstr(AudioopError, "Size should be 1, 2 or 4");
707 return 0;
710 rv = newsizedstringobject(NULL, len*2);
711 if ( rv == 0 )
712 return 0;
713 ncp = (signed char *)getstringvalue(rv);
716 for ( i=0; i < len; i += size ) {
717 if ( size == 1 ) val = (int)*CHARP(cp, i);
718 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
719 else if ( size == 4 ) val = (int)*LONGP(cp, i);
721 fval = (double)val*fac1;
722 if ( fval > maxval ) fval = maxval;
723 else if ( fval < -maxval ) fval = -maxval;
724 val1 = (int)fval;
726 fval = (double)val*fac2;
727 if ( fval > maxval ) fval = maxval;
728 else if ( fval < -maxval ) fval = -maxval;
729 val2 = (int)fval;
731 if ( size == 1 ) *CHARP(ncp, i*2) = (signed char)val1;
732 else if ( size == 2 ) *SHORTP(ncp, i*2) = (short)val1;
733 else if ( size == 4 ) *LONGP(ncp, i*2) = (long)val1;
735 if ( size == 1 ) *CHARP(ncp, i*2+1) = (signed char)val2;
736 else if ( size == 2 ) *SHORTP(ncp, i*2+2) = (short)val2;
737 else if ( size == 4 ) *LONGP(ncp, i*2+4) = (long)val2;
739 return rv;
742 static object *
743 audioop_add(self, args)
744 object *self;
745 object *args;
747 signed char *cp1, *cp2, *ncp;
748 int len1, len2, size, val1, val2;
749 object *rv;
750 int i;
752 if ( !getargs(args, "(s#s#i)",
753 &cp1, &len1, &cp2, &len2, &size ) )
754 return 0;
756 if ( len1 != len2 ) {
757 err_setstr(AudioopError, "Lengths should be the same");
758 return 0;
761 if ( size != 1 && size != 2 && size != 4) {
762 err_setstr(AudioopError, "Size should be 1, 2 or 4");
763 return 0;
766 rv = newsizedstringobject(NULL, len1);
767 if ( rv == 0 )
768 return 0;
769 ncp = (signed char *)getstringvalue(rv);
772 for ( i=0; i < len1; i += size ) {
773 if ( size == 1 ) val1 = (int)*CHARP(cp1, i);
774 else if ( size == 2 ) val1 = (int)*SHORTP(cp1, i);
775 else if ( size == 4 ) val1 = (int)*LONGP(cp1, i);
777 if ( size == 1 ) val2 = (int)*CHARP(cp2, i);
778 else if ( size == 2 ) val2 = (int)*SHORTP(cp2, i);
779 else if ( size == 4 ) val2 = (int)*LONGP(cp2, i);
781 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val1+val2);
782 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val1+val2);
783 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val1+val2);
785 return rv;
788 static object *
789 audioop_bias(self, args)
790 object *self;
791 object *args;
793 signed char *cp, *ncp;
794 int len, size, val;
795 object *rv;
796 int i;
797 int bias;
799 if ( !getargs(args, "(s#ii)",
800 &cp, &len, &size , &bias) )
801 return 0;
803 if ( size != 1 && size != 2 && size != 4) {
804 err_setstr(AudioopError, "Size should be 1, 2 or 4");
805 return 0;
808 rv = newsizedstringobject(NULL, len);
809 if ( rv == 0 )
810 return 0;
811 ncp = (signed char *)getstringvalue(rv);
814 for ( i=0; i < len; i += size ) {
815 if ( size == 1 ) val = (int)*CHARP(cp, i);
816 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
817 else if ( size == 4 ) val = (int)*LONGP(cp, i);
819 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val+bias);
820 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val+bias);
821 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val+bias);
823 return rv;
826 static object *
827 audioop_reverse(self, args)
828 object *self;
829 object *args;
831 signed char *cp;
832 unsigned char *ncp;
833 int len, size, val;
834 object *rv;
835 int i, j;
837 if ( !getargs(args, "(s#i)",
838 &cp, &len, &size) )
839 return 0;
841 if ( size != 1 && size != 2 && size != 4 ) {
842 err_setstr(AudioopError, "Size should be 1, 2 or 4");
843 return 0;
846 rv = newsizedstringobject(NULL, len);
847 if ( rv == 0 )
848 return 0;
849 ncp = (unsigned char *)getstringvalue(rv);
851 for ( i=0; i < len; i += size ) {
852 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
853 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
854 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
856 j = len - i - size;
858 if ( size == 1 ) *CHARP(ncp, j) = (signed char)(val >> 8);
859 else if ( size == 2 ) *SHORTP(ncp, j) = (short)(val);
860 else if ( size == 4 ) *LONGP(ncp, j) = (long)(val<<16);
862 return rv;
865 static object *
866 audioop_lin2lin(self, args)
867 object *self;
868 object *args;
870 signed char *cp;
871 unsigned char *ncp;
872 int len, size, size2, val;
873 object *rv;
874 int i, j;
876 if ( !getargs(args, "(s#ii)",
877 &cp, &len, &size, &size2) )
878 return 0;
880 if ( (size != 1 && size != 2 && size != 4) ||
881 (size2 != 1 && size2 != 2 && size2 != 4)) {
882 err_setstr(AudioopError, "Size should be 1, 2 or 4");
883 return 0;
886 rv = newsizedstringobject(NULL, (len/size)*size2);
887 if ( rv == 0 )
888 return 0;
889 ncp = (unsigned char *)getstringvalue(rv);
891 for ( i=0, j=0; i < len; i += size, j += size2 ) {
892 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
893 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
894 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
896 if ( size2 == 1 ) *CHARP(ncp, j) = (signed char)(val >> 8);
897 else if ( size2 == 2 ) *SHORTP(ncp, j) = (short)(val);
898 else if ( size2 == 4 ) *LONGP(ncp, j) = (long)(val<<16);
900 return rv;
903 static object *
904 audioop_lin2ulaw(self, args)
905 object *self;
906 object *args;
908 signed char *cp;
909 unsigned char *ncp;
910 int len, size, val;
911 object *rv;
912 int i;
914 if ( !getargs(args, "(s#i)",
915 &cp, &len, &size) )
916 return 0;
918 if ( size != 1 && size != 2 && size != 4) {
919 err_setstr(AudioopError, "Size should be 1, 2 or 4");
920 return 0;
923 rv = newsizedstringobject(NULL, len/size);
924 if ( rv == 0 )
925 return 0;
926 ncp = (unsigned char *)getstringvalue(rv);
928 for ( i=0; i < len; i += size ) {
929 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
930 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
931 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
933 *ncp++ = st_linear_to_ulaw(val);
935 return rv;
938 static object *
939 audioop_ulaw2lin(self, args)
940 object *self;
941 object *args;
943 unsigned char *cp;
944 unsigned char cval;
945 signed char *ncp;
946 int len, size, val;
947 object *rv;
948 int i;
950 if ( !getargs(args, "(s#i)",
951 &cp, &len, &size) )
952 return 0;
954 if ( size != 1 && size != 2 && size != 4) {
955 err_setstr(AudioopError, "Size should be 1, 2 or 4");
956 return 0;
959 rv = newsizedstringobject(NULL, len*size);
960 if ( rv == 0 )
961 return 0;
962 ncp = (signed char *)getstringvalue(rv);
964 for ( i=0; i < len*size; i += size ) {
965 cval = *cp++;
966 val = st_ulaw_to_linear(cval);
968 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val >> 8);
969 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val);
970 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val<<16);
972 return rv;
975 static object *
976 audioop_lin2adpcm(self, args)
977 object *self;
978 object *args;
980 signed char *cp;
981 signed char *ncp;
982 int len, size, val, step, valpred, delta, index, sign, vpdiff, diff;
983 object *rv, *state, *str;
984 int i, outputbuffer, bufferstep;
986 if ( !getargs(args, "(s#iO)",
987 &cp, &len, &size, &state) )
988 return 0;
991 if ( size != 1 && size != 2 && size != 4) {
992 err_setstr(AudioopError, "Size should be 1, 2 or 4");
993 return 0;
996 str = newsizedstringobject(NULL, len/(size*2));
997 if ( str == 0 )
998 return 0;
999 ncp = (signed char *)getstringvalue(str);
1001 /* Decode state, should have (value, step) */
1002 if ( state == None ) {
1003 /* First time, it seems. Set defaults */
1004 valpred = 0;
1005 step = 7;
1006 index = 0;
1007 } else if ( !getargs(state, "(ii)", &valpred, &index) )
1008 return 0;
1010 step = stepsizeTable[index];
1011 bufferstep = 1;
1013 for ( i=0; i < len; i += size ) {
1014 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
1015 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
1016 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
1018 /* Step 1 - compute difference with previous value */
1019 diff = val - valpred;
1020 sign = (diff < 0) ? 8 : 0;
1021 if ( sign ) diff = (-diff);
1023 /* Step 2 - Divide and clamp */
1024 /* Note:
1025 ** This code *approximately* computes:
1026 ** delta = diff*4/step;
1027 ** vpdiff = (delta+0.5)*step/4;
1028 ** but in shift step bits are dropped. The net result of this is
1029 ** that even if you have fast mul/div hardware you cannot put it to
1030 ** good use since the fixup would be too expensive.
1032 delta = 0;
1033 vpdiff = (step >> 3);
1035 if ( diff >= step ) {
1036 delta = 4;
1037 diff -= step;
1038 vpdiff += step;
1040 step >>= 1;
1041 if ( diff >= step ) {
1042 delta |= 2;
1043 diff -= step;
1044 vpdiff += step;
1046 step >>= 1;
1047 if ( diff >= step ) {
1048 delta |= 1;
1049 vpdiff += step;
1052 /* Step 3 - Update previous value */
1053 if ( sign )
1054 valpred -= vpdiff;
1055 else
1056 valpred += vpdiff;
1058 /* Step 4 - Clamp previous value to 16 bits */
1059 if ( valpred > 32767 )
1060 valpred = 32767;
1061 else if ( valpred < -32768 )
1062 valpred = -32768;
1064 /* Step 5 - Assemble value, update index and step values */
1065 delta |= sign;
1067 index += indexTable[delta];
1068 if ( index < 0 ) index = 0;
1069 if ( index > 88 ) index = 88;
1070 step = stepsizeTable[index];
1072 /* Step 6 - Output value */
1073 if ( bufferstep ) {
1074 outputbuffer = (delta << 4) & 0xf0;
1075 } else {
1076 *ncp++ = (delta & 0x0f) | outputbuffer;
1078 bufferstep = !bufferstep;
1080 rv = mkvalue("(O(ii))", str, valpred, index);
1081 DECREF(str);
1082 return rv;
1085 static object *
1086 audioop_adpcm2lin(self, args)
1087 object *self;
1088 object *args;
1090 signed char *cp;
1091 signed char *ncp;
1092 int len, size, val, valpred, step, delta, index, sign, vpdiff;
1093 object *rv, *str, *state;
1094 int i, inputbuffer, bufferstep;
1096 if ( !getargs(args, "(s#iO)",
1097 &cp, &len, &size, &state) )
1098 return 0;
1100 if ( size != 1 && size != 2 && size != 4) {
1101 err_setstr(AudioopError, "Size should be 1, 2 or 4");
1102 return 0;
1105 /* Decode state, should have (value, step) */
1106 if ( state == None ) {
1107 /* First time, it seems. Set defaults */
1108 valpred = 0;
1109 step = 7;
1110 index = 0;
1111 } else if ( !getargs(state, "(ii)", &valpred, &index) )
1112 return 0;
1114 str = newsizedstringobject(NULL, len*size*2);
1115 if ( str == 0 )
1116 return 0;
1117 ncp = (signed char *)getstringvalue(str);
1119 step = stepsizeTable[index];
1120 bufferstep = 0;
1122 for ( i=0; i < len*size*2; i += size ) {
1123 /* Step 1 - get the delta value and compute next index */
1124 if ( bufferstep ) {
1125 delta = inputbuffer & 0xf;
1126 } else {
1127 inputbuffer = *cp++;
1128 delta = (inputbuffer >> 4) & 0xf;
1131 bufferstep = !bufferstep;
1133 /* Step 2 - Find new index value (for later) */
1134 index += indexTable[delta];
1135 if ( index < 0 ) index = 0;
1136 if ( index > 88 ) index = 88;
1138 /* Step 3 - Separate sign and magnitude */
1139 sign = delta & 8;
1140 delta = delta & 7;
1142 /* Step 4 - Compute difference and new predicted value */
1144 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
1145 ** in adpcm_coder.
1147 vpdiff = step >> 3;
1148 if ( delta & 4 ) vpdiff += step;
1149 if ( delta & 2 ) vpdiff += step>>1;
1150 if ( delta & 1 ) vpdiff += step>>2;
1152 if ( sign )
1153 valpred -= vpdiff;
1154 else
1155 valpred += vpdiff;
1157 /* Step 5 - clamp output value */
1158 if ( valpred > 32767 )
1159 valpred = 32767;
1160 else if ( valpred < -32768 )
1161 valpred = -32768;
1163 /* Step 6 - Update step value */
1164 step = stepsizeTable[index];
1166 /* Step 6 - Output value */
1167 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valpred >> 8);
1168 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valpred);
1169 else if ( size == 4 ) *LONGP(ncp, i) = (long)(valpred<<16);
1172 rv = mkvalue("(O(ii))", str, valpred, index);
1173 DECREF(str);
1174 return rv;
1177 static struct methodlist audioop_methods[] = {
1178 { "max", audioop_max },
1179 { "avg", audioop_avg },
1180 { "maxpp", audioop_maxpp },
1181 { "avgpp", audioop_avgpp },
1182 { "rms", audioop_rms },
1183 { "findfit", audioop_findfit },
1184 { "findmax", audioop_findmax },
1185 { "findfactor", audioop_findfactor },
1186 { "cross", audioop_cross },
1187 { "mul", audioop_mul },
1188 { "add", audioop_add },
1189 { "bias", audioop_bias },
1190 { "ulaw2lin", audioop_ulaw2lin },
1191 { "lin2ulaw", audioop_lin2ulaw },
1192 { "lin2lin", audioop_lin2lin },
1193 { "adpcm2lin", audioop_adpcm2lin },
1194 { "lin2adpcm", audioop_lin2adpcm },
1195 { "tomono", audioop_tomono },
1196 { "tostereo", audioop_tostereo },
1197 { "getsample", audioop_getsample },
1198 { "reverse", audioop_reverse },
1199 { 0, 0 }
1203 void
1204 initaudioop()
1206 object *m, *d;
1207 m = initmodule("audioop", audioop_methods);
1208 d = getmoduledict(m);
1209 AudioopError = newstringobject("audioop.error");
1210 if ( AudioopError == NULL || dictinsert(d,"error",AudioopError) )
1211 fatal("can't define audioop.error");