#changed all email address to go through python.org
[python/dscho.git] / Modules / audioop.c
blob899bbc62b1b37ac4f148f76e2f402a4144f3b88c
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 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__)
31 #if defined(signed)
32 !ERROR!; READ THE SOURCE FILE!;
33 /* This module currently does not work on systems where only unsigned
34 characters are available. Take it out of Setup. Sorry. */
35 #endif
36 #endif
38 #include "mymath.h"
40 /* Code shamelessly stolen from sox,
41 ** (c) Craig Reese, Joe Campbell and Jeff Poskanzer 1989 */
43 #define MINLIN -32768
44 #define MAXLIN 32767
45 #define LINCLIP(x) do { if ( x < MINLIN ) x = MINLIN ; else if ( x > MAXLIN ) x = MAXLIN; } while ( 0 )
47 static unsigned char st_linear_to_ulaw( /* int sample */ );
50 ** This macro converts from ulaw to 16 bit linear, faster.
52 ** Jef Poskanzer
53 ** 23 October 1989
55 ** Input: 8 bit ulaw sample
56 ** Output: signed 16 bit linear sample
58 #define st_ulaw_to_linear(ulawbyte) ulaw_table[ulawbyte]
60 static int ulaw_table[256] = {
61 -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
62 -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
63 -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
64 -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316,
65 -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
66 -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
67 -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
68 -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
69 -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
70 -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
71 -876, -844, -812, -780, -748, -716, -684, -652,
72 -620, -588, -556, -524, -492, -460, -428, -396,
73 -372, -356, -340, -324, -308, -292, -276, -260,
74 -244, -228, -212, -196, -180, -164, -148, -132,
75 -120, -112, -104, -96, -88, -80, -72, -64,
76 -56, -48, -40, -32, -24, -16, -8, 0,
77 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
78 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
79 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
80 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
81 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
82 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
83 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
84 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
85 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
86 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
87 876, 844, 812, 780, 748, 716, 684, 652,
88 620, 588, 556, 524, 492, 460, 428, 396,
89 372, 356, 340, 324, 308, 292, 276, 260,
90 244, 228, 212, 196, 180, 164, 148, 132,
91 120, 112, 104, 96, 88, 80, 72, 64,
92 56, 48, 40, 32, 24, 16, 8, 0 };
94 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
95 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
96 #define CLIP 32635
98 static unsigned char
99 st_linear_to_ulaw( sample )
100 int sample;
102 static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
103 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
104 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
105 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
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 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
109 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
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 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
117 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
118 int sign, exponent, mantissa;
119 unsigned char ulawbyte;
121 /* Get the sample into sign-magnitude. */
122 sign = (sample >> 8) & 0x80; /* set aside the sign */
123 if ( sign != 0 ) sample = -sample; /* get magnitude */
124 if ( sample > CLIP ) sample = CLIP; /* clip the magnitude */
126 /* Convert from 16 bit linear to ulaw. */
127 sample = sample + BIAS;
128 exponent = exp_lut[( sample >> 7 ) & 0xFF];
129 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
130 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
131 #ifdef ZEROTRAP
132 if ( ulawbyte == 0 ) ulawbyte = 0x02; /* optional CCITT trap */
133 #endif
135 return ulawbyte;
137 /* End of code taken from sox */
139 /* Intel ADPCM step variation table */
140 static int indexTable[16] = {
141 -1, -1, -1, -1, 2, 4, 6, 8,
142 -1, -1, -1, -1, 2, 4, 6, 8,
145 static int stepsizeTable[89] = {
146 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
147 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
148 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
149 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
150 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
151 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
152 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
153 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
154 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
157 #define CHARP(cp, i) ((signed char *)(cp+i))
158 #define SHORTP(cp, i) ((short *)(cp+i))
159 #define LONGP(cp, i) ((long *)(cp+i))
163 static object *AudioopError;
165 static object *
166 audioop_getsample(self, args)
167 object *self;
168 object *args;
170 signed char *cp;
171 int len, size, val;
172 int i;
174 if ( !getargs(args, "(s#ii)", &cp, &len, &size, &i) )
175 return 0;
176 if ( size != 1 && size != 2 && size != 4 ) {
177 err_setstr(AudioopError, "Size should be 1, 2 or 4");
178 return 0;
180 if ( i < 0 || i >= len/size ) {
181 err_setstr(AudioopError, "Index out of range");
182 return 0;
184 if ( size == 1 ) val = (int)*CHARP(cp, i);
185 else if ( size == 2 ) val = (int)*SHORTP(cp, i*2);
186 else if ( size == 4 ) val = (int)*LONGP(cp, i*4);
187 return newintobject(val);
190 static object *
191 audioop_max(self, args)
192 object *self;
193 object *args;
195 signed char *cp;
196 int len, size, val;
197 int i;
198 int max = 0;
200 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
201 return 0;
202 if ( size != 1 && size != 2 && size != 4 ) {
203 err_setstr(AudioopError, "Size should be 1, 2 or 4");
204 return 0;
206 for ( i=0; i<len; i+= size) {
207 if ( size == 1 ) val = (int)*CHARP(cp, i);
208 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
209 else if ( size == 4 ) val = (int)*LONGP(cp, i);
210 if ( val < 0 ) val = (-val);
211 if ( val > max ) max = val;
213 return newintobject(max);
216 static object *
217 audioop_minmax(self, args)
218 object *self;
219 object *args;
221 signed char *cp;
222 int len, size, val;
223 int i;
224 int min = 0x7fffffff, max = -0x7fffffff;
226 if (!getargs(args, "(s#i)", &cp, &len, &size))
227 return NULL;
228 if (size != 1 && size != 2 && size != 4) {
229 err_setstr(AudioopError, "Size should be 1, 2 or 4");
230 return NULL;
232 for (i = 0; i < len; i += size) {
233 if (size == 1) val = (int) *CHARP(cp, i);
234 else if (size == 2) val = (int) *SHORTP(cp, i);
235 else if (size == 4) val = (int) *LONGP(cp, i);
236 if (val > max) max = val;
237 if (val < min) min = val;
239 return mkvalue("(ii)", min, max);
242 static object *
243 audioop_avg(self, args)
244 object *self;
245 object *args;
247 signed char *cp;
248 int len, size, val;
249 int i;
250 float avg = 0.0;
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;
258 for ( i=0; i<len; i+= size) {
259 if ( size == 1 ) val = (int)*CHARP(cp, i);
260 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
261 else if ( size == 4 ) val = (int)*LONGP(cp, i);
262 avg += val;
264 if ( len == 0 )
265 val = 0;
266 else
267 val = (int)(avg / (float)(len/size));
268 return newintobject(val);
271 static object *
272 audioop_rms(self, args)
273 object *self;
274 object *args;
276 signed char *cp;
277 int len, size, val;
278 int i;
279 float sum_squares = 0.0;
281 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
282 return 0;
283 if ( size != 1 && size != 2 && size != 4 ) {
284 err_setstr(AudioopError, "Size should be 1, 2 or 4");
285 return 0;
287 for ( i=0; i<len; i+= size) {
288 if ( size == 1 ) val = (int)*CHARP(cp, i);
289 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
290 else if ( size == 4 ) val = (int)*LONGP(cp, i);
291 sum_squares += (float)val*(float)val;
293 if ( len == 0 )
294 val = 0;
295 else
296 val = (int)sqrt(sum_squares / (float)(len/size));
297 return newintobject(val);
300 static double _sum2(a, b, len)
301 short *a;
302 short *b;
303 int len;
305 int i;
306 double sum = 0.0;
308 for( i=0; i<len; i++) {
309 sum = sum + (double)a[i]*(double)b[i];
311 return sum;
315 ** Findfit tries to locate a sample within another sample. Its main use
316 ** is in echo-cancellation (to find the feedback of the output signal in
317 ** the input signal).
318 ** The method used is as follows:
320 ** let R be the reference signal (length n) and A the input signal (length N)
321 ** with N > n, and let all sums be over i from 0 to n-1.
323 ** Now, for each j in {0..N-n} we compute a factor fj so that -fj*R matches A
324 ** as good as possible, i.e. sum( (A[j+i]+fj*R[i])^2 ) is minimal. This
325 ** equation gives fj = sum( A[j+i]R[i] ) / sum(R[i]^2).
327 ** Next, we compute the relative distance between the original signal and
328 ** the modified signal and minimize that over j:
329 ** vj = sum( (A[j+i]-fj*R[i])^2 ) / sum( A[j+i]^2 ) =>
330 ** vj = ( sum(A[j+i]^2)*sum(R[i]^2) - sum(A[j+i]R[i])^2 ) / sum( A[j+i]^2 )
332 ** In the code variables correspond as follows:
333 ** cp1 A
334 ** cp2 R
335 ** len1 N
336 ** len2 n
337 ** aj_m1 A[j-1]
338 ** aj_lm1 A[j+n-1]
339 ** sum_ri_2 sum(R[i]^2)
340 ** sum_aij_2 sum(A[i+j]^2)
341 ** sum_aij_ri sum(A[i+j]R[i])
343 ** sum_ri is calculated once, sum_aij_2 is updated each step and sum_aij_ri
344 ** is completely recalculated each step.
346 static object *
347 audioop_findfit(self, args)
348 object *self;
349 object *args;
351 short *cp1, *cp2;
352 int len1, len2;
353 int j, best_j;
354 double aj_m1, aj_lm1;
355 double sum_ri_2, sum_aij_2, sum_aij_ri, result, best_result, factor;
357 if ( !getargs(args, "(s#s#)", &cp1, &len1, &cp2, &len2) )
358 return 0;
359 if ( len1 & 1 || len2 & 1 ) {
360 err_setstr(AudioopError, "Strings should be even-sized");
361 return 0;
363 len1 >>= 1;
364 len2 >>= 1;
366 if ( len1 < len2 ) {
367 err_setstr(AudioopError, "First sample should be longer");
368 return 0;
370 sum_ri_2 = _sum2(cp2, cp2, len2);
371 sum_aij_2 = _sum2(cp1, cp1, len2);
372 sum_aij_ri = _sum2(cp1, cp2, len2);
374 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
376 best_result = result;
377 best_j = 0;
378 j = 0;
380 for ( j=1; j<=len1-len2; j++) {
381 aj_m1 = (double)cp1[j-1];
382 aj_lm1 = (double)cp1[j+len2-1];
384 sum_aij_2 = sum_aij_2 + aj_lm1*aj_lm1 - aj_m1*aj_m1;
385 sum_aij_ri = _sum2(cp1+j, cp2, len2);
387 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
389 if ( result < best_result ) {
390 best_result = result;
391 best_j = j;
396 factor = _sum2(cp1+best_j, cp2, len2) / sum_ri_2;
398 return mkvalue("(if)", best_j, factor);
402 ** findfactor finds a factor f so that the energy in A-fB is minimal.
403 ** See the comment for findfit for details.
405 static object *
406 audioop_findfactor(self, args)
407 object *self;
408 object *args;
410 short *cp1, *cp2;
411 int len1, len2;
412 double sum_ri_2, sum_aij_ri, result;
414 if ( !getargs(args, "(s#s#)", &cp1, &len1, &cp2, &len2) )
415 return 0;
416 if ( len1 & 1 || len2 & 1 ) {
417 err_setstr(AudioopError, "Strings should be even-sized");
418 return 0;
420 if ( len1 != len2 ) {
421 err_setstr(AudioopError, "Samples should be same size");
422 return 0;
424 len2 >>= 1;
425 sum_ri_2 = _sum2(cp2, cp2, len2);
426 sum_aij_ri = _sum2(cp1, cp2, len2);
428 result = sum_aij_ri / sum_ri_2;
430 return newfloatobject(result);
434 ** findmax returns the index of the n-sized segment of the input sample
435 ** that contains the most energy.
437 static object *
438 audioop_findmax(self, args)
439 object *self;
440 object *args;
442 short *cp1;
443 int len1, len2;
444 int j, best_j;
445 double aj_m1, aj_lm1;
446 double result, best_result;
448 if ( !getargs(args, "(s#i)", &cp1, &len1, &len2) )
449 return 0;
450 if ( len1 & 1 ) {
451 err_setstr(AudioopError, "Strings should be even-sized");
452 return 0;
454 len1 >>= 1;
456 if ( len1 < len2 ) {
457 err_setstr(AudioopError, "Input sample should be longer");
458 return 0;
461 result = _sum2(cp1, cp1, len2);
463 best_result = result;
464 best_j = 0;
465 j = 0;
467 for ( j=1; j<=len1-len2; j++) {
468 aj_m1 = (double)cp1[j-1];
469 aj_lm1 = (double)cp1[j+len2-1];
471 result = result + aj_lm1*aj_lm1 - aj_m1*aj_m1;
473 if ( result > best_result ) {
474 best_result = result;
475 best_j = j;
480 return newintobject(best_j);
483 static object *
484 audioop_avgpp(self, args)
485 object *self;
486 object *args;
488 signed char *cp;
489 int len, size, val, prevval, prevextremevalid = 0, prevextreme;
490 int i;
491 float avg = 0.0;
492 int diff, prevdiff, extremediff, nextreme = 0;
494 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
495 return 0;
496 if ( size != 1 && size != 2 && size != 4 ) {
497 err_setstr(AudioopError, "Size should be 1, 2 or 4");
498 return 0;
500 /* Compute first delta value ahead. Also automatically makes us
501 ** skip the first extreme value
503 if ( size == 1 ) prevval = (int)*CHARP(cp, 0);
504 else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
505 else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
506 if ( size == 1 ) val = (int)*CHARP(cp, size);
507 else if ( size == 2 ) val = (int)*SHORTP(cp, size);
508 else if ( size == 4 ) val = (int)*LONGP(cp, size);
509 prevdiff = val - prevval;
511 for ( i=size; i<len; i+= size) {
512 if ( size == 1 ) val = (int)*CHARP(cp, i);
513 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
514 else if ( size == 4 ) val = (int)*LONGP(cp, i);
515 diff = val - prevval;
516 if ( diff*prevdiff < 0 ) {
517 /* Derivative changed sign. Compute difference to last extreme
518 ** value and remember.
520 if ( prevextremevalid ) {
521 extremediff = prevval - prevextreme;
522 if ( extremediff < 0 )
523 extremediff = -extremediff;
524 avg += extremediff;
525 nextreme++;
527 prevextremevalid = 1;
528 prevextreme = prevval;
530 prevval = val;
531 if ( diff != 0 )
532 prevdiff = diff;
534 if ( nextreme == 0 )
535 val = 0;
536 else
537 val = (int)(avg / (float)nextreme);
538 return newintobject(val);
541 static object *
542 audioop_maxpp(self, args)
543 object *self;
544 object *args;
546 signed char *cp;
547 int len, size, val, prevval, prevextremevalid = 0, prevextreme;
548 int i;
549 int max = 0;
550 int diff, prevdiff, extremediff;
552 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
553 return 0;
554 if ( size != 1 && size != 2 && size != 4 ) {
555 err_setstr(AudioopError, "Size should be 1, 2 or 4");
556 return 0;
558 /* Compute first delta value ahead. Also automatically makes us
559 ** skip the first extreme value
561 if ( size == 1 ) prevval = (int)*CHARP(cp, 0);
562 else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
563 else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
564 if ( size == 1 ) val = (int)*CHARP(cp, size);
565 else if ( size == 2 ) val = (int)*SHORTP(cp, size);
566 else if ( size == 4 ) val = (int)*LONGP(cp, size);
567 prevdiff = val - prevval;
569 for ( i=size; i<len; i+= size) {
570 if ( size == 1 ) val = (int)*CHARP(cp, i);
571 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
572 else if ( size == 4 ) val = (int)*LONGP(cp, i);
573 diff = val - prevval;
574 if ( diff*prevdiff < 0 ) {
575 /* Derivative changed sign. Compute difference to last extreme
576 ** value and remember.
578 if ( prevextremevalid ) {
579 extremediff = prevval - prevextreme;
580 if ( extremediff < 0 )
581 extremediff = -extremediff;
582 if ( extremediff > max )
583 max = extremediff;
585 prevextremevalid = 1;
586 prevextreme = prevval;
588 prevval = val;
589 if ( diff != 0 )
590 prevdiff = diff;
592 return newintobject(max);
595 static object *
596 audioop_cross(self, args)
597 object *self;
598 object *args;
600 signed char *cp;
601 int len, size, val;
602 int i;
603 int prevval, ncross;
605 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
606 return 0;
607 if ( size != 1 && size != 2 && size != 4 ) {
608 err_setstr(AudioopError, "Size should be 1, 2 or 4");
609 return 0;
611 ncross = -1;
612 prevval = 17; /* Anything <> 0,1 */
613 for ( i=0; i<len; i+= size) {
614 if ( size == 1 ) val = ((int)*CHARP(cp, i)) >> 7;
615 else if ( size == 2 ) val = ((int)*SHORTP(cp, i)) >> 15;
616 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 31;
617 val = val & 1;
618 if ( val != prevval ) ncross++;
619 prevval = val;
621 return newintobject(ncross);
624 static object *
625 audioop_mul(self, args)
626 object *self;
627 object *args;
629 signed char *cp, *ncp;
630 int len, size, val;
631 double factor, fval, maxval;
632 object *rv;
633 int i;
635 if ( !getargs(args, "(s#id)", &cp, &len, &size, &factor ) )
636 return 0;
638 if ( size == 1 ) maxval = (double) 0x7f;
639 else if ( size == 2 ) maxval = (double) 0x7fff;
640 else if ( size == 4 ) maxval = (double) 0x7fffffff;
641 else {
642 err_setstr(AudioopError, "Size should be 1, 2 or 4");
643 return 0;
646 rv = newsizedstringobject(NULL, len);
647 if ( rv == 0 )
648 return 0;
649 ncp = (signed char *)getstringvalue(rv);
652 for ( i=0; i < len; i += size ) {
653 if ( size == 1 ) val = (int)*CHARP(cp, i);
654 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
655 else if ( size == 4 ) val = (int)*LONGP(cp, i);
656 fval = (double)val*factor;
657 if ( fval > maxval ) fval = maxval;
658 else if ( fval < -maxval ) fval = -maxval;
659 val = (int)fval;
660 if ( size == 1 ) *CHARP(ncp, i) = (signed char)val;
661 else if ( size == 2 ) *SHORTP(ncp, i) = (short)val;
662 else if ( size == 4 ) *LONGP(ncp, i) = (long)val;
664 return rv;
667 static object *
668 audioop_tomono(self, args)
669 object *self;
670 object *args;
672 signed char *cp, *ncp;
673 int len, size, val1, val2;
674 double fac1, fac2, fval, maxval;
675 object *rv;
676 int i;
678 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
679 return 0;
681 if ( size == 1 ) maxval = (double) 0x7f;
682 else if ( size == 2 ) maxval = (double) 0x7fff;
683 else if ( size == 4 ) maxval = (double) 0x7fffffff;
684 else {
685 err_setstr(AudioopError, "Size should be 1, 2 or 4");
686 return 0;
689 rv = newsizedstringobject(NULL, len/2);
690 if ( rv == 0 )
691 return 0;
692 ncp = (signed char *)getstringvalue(rv);
695 for ( i=0; i < len; i += size*2 ) {
696 if ( size == 1 ) val1 = (int)*CHARP(cp, i);
697 else if ( size == 2 ) val1 = (int)*SHORTP(cp, i);
698 else if ( size == 4 ) val1 = (int)*LONGP(cp, i);
699 if ( size == 1 ) val2 = (int)*CHARP(cp, i+1);
700 else if ( size == 2 ) val2 = (int)*SHORTP(cp, i+2);
701 else if ( size == 4 ) val2 = (int)*LONGP(cp, i+4);
702 fval = (double)val1*fac1 + (double)val2*fac2;
703 if ( fval > maxval ) fval = maxval;
704 else if ( fval < -maxval ) fval = -maxval;
705 val1 = (int)fval;
706 if ( size == 1 ) *CHARP(ncp, i/2) = (signed char)val1;
707 else if ( size == 2 ) *SHORTP(ncp, i/2) = (short)val1;
708 else if ( size == 4 ) *LONGP(ncp, i/2)= (long)val1;
710 return rv;
713 static object *
714 audioop_tostereo(self, args)
715 object *self;
716 object *args;
718 signed char *cp, *ncp;
719 int len, size, val1, val2, val;
720 double fac1, fac2, fval, maxval;
721 object *rv;
722 int i;
724 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
725 return 0;
727 if ( size == 1 ) maxval = (double) 0x7f;
728 else if ( size == 2 ) maxval = (double) 0x7fff;
729 else if ( size == 4 ) maxval = (double) 0x7fffffff;
730 else {
731 err_setstr(AudioopError, "Size should be 1, 2 or 4");
732 return 0;
735 rv = newsizedstringobject(NULL, len*2);
736 if ( rv == 0 )
737 return 0;
738 ncp = (signed char *)getstringvalue(rv);
741 for ( i=0; i < len; i += size ) {
742 if ( size == 1 ) val = (int)*CHARP(cp, i);
743 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
744 else if ( size == 4 ) val = (int)*LONGP(cp, i);
746 fval = (double)val*fac1;
747 if ( fval > maxval ) fval = maxval;
748 else if ( fval < -maxval ) fval = -maxval;
749 val1 = (int)fval;
751 fval = (double)val*fac2;
752 if ( fval > maxval ) fval = maxval;
753 else if ( fval < -maxval ) fval = -maxval;
754 val2 = (int)fval;
756 if ( size == 1 ) *CHARP(ncp, i*2) = (signed char)val1;
757 else if ( size == 2 ) *SHORTP(ncp, i*2) = (short)val1;
758 else if ( size == 4 ) *LONGP(ncp, i*2) = (long)val1;
760 if ( size == 1 ) *CHARP(ncp, i*2+1) = (signed char)val2;
761 else if ( size == 2 ) *SHORTP(ncp, i*2+2) = (short)val2;
762 else if ( size == 4 ) *LONGP(ncp, i*2+4) = (long)val2;
764 return rv;
767 static object *
768 audioop_add(self, args)
769 object *self;
770 object *args;
772 signed char *cp1, *cp2, *ncp;
773 int len1, len2, size, val1, val2;
774 object *rv;
775 int i;
777 if ( !getargs(args, "(s#s#i)",
778 &cp1, &len1, &cp2, &len2, &size ) )
779 return 0;
781 if ( len1 != len2 ) {
782 err_setstr(AudioopError, "Lengths should be the same");
783 return 0;
786 if ( size != 1 && size != 2 && size != 4) {
787 err_setstr(AudioopError, "Size should be 1, 2 or 4");
788 return 0;
791 rv = newsizedstringobject(NULL, len1);
792 if ( rv == 0 )
793 return 0;
794 ncp = (signed char *)getstringvalue(rv);
797 for ( i=0; i < len1; i += size ) {
798 if ( size == 1 ) val1 = (int)*CHARP(cp1, i);
799 else if ( size == 2 ) val1 = (int)*SHORTP(cp1, i);
800 else if ( size == 4 ) val1 = (int)*LONGP(cp1, i);
802 if ( size == 1 ) val2 = (int)*CHARP(cp2, i);
803 else if ( size == 2 ) val2 = (int)*SHORTP(cp2, i);
804 else if ( size == 4 ) val2 = (int)*LONGP(cp2, i);
806 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val1+val2);
807 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val1+val2);
808 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val1+val2);
810 return rv;
813 static object *
814 audioop_bias(self, args)
815 object *self;
816 object *args;
818 signed char *cp, *ncp;
819 int len, size, val;
820 object *rv;
821 int i;
822 int bias;
824 if ( !getargs(args, "(s#ii)",
825 &cp, &len, &size , &bias) )
826 return 0;
828 if ( size != 1 && size != 2 && size != 4) {
829 err_setstr(AudioopError, "Size should be 1, 2 or 4");
830 return 0;
833 rv = newsizedstringobject(NULL, len);
834 if ( rv == 0 )
835 return 0;
836 ncp = (signed char *)getstringvalue(rv);
839 for ( i=0; i < len; i += size ) {
840 if ( size == 1 ) val = (int)*CHARP(cp, i);
841 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
842 else if ( size == 4 ) val = (int)*LONGP(cp, i);
844 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val+bias);
845 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val+bias);
846 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val+bias);
848 return rv;
851 static object *
852 audioop_reverse(self, args)
853 object *self;
854 object *args;
856 signed char *cp;
857 unsigned char *ncp;
858 int len, size, val;
859 object *rv;
860 int i, j;
862 if ( !getargs(args, "(s#i)",
863 &cp, &len, &size) )
864 return 0;
866 if ( size != 1 && size != 2 && size != 4 ) {
867 err_setstr(AudioopError, "Size should be 1, 2 or 4");
868 return 0;
871 rv = newsizedstringobject(NULL, len);
872 if ( rv == 0 )
873 return 0;
874 ncp = (unsigned char *)getstringvalue(rv);
876 for ( i=0; i < len; i += size ) {
877 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
878 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
879 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
881 j = len - i - size;
883 if ( size == 1 ) *CHARP(ncp, j) = (signed char)(val >> 8);
884 else if ( size == 2 ) *SHORTP(ncp, j) = (short)(val);
885 else if ( size == 4 ) *LONGP(ncp, j) = (long)(val<<16);
887 return rv;
890 static object *
891 audioop_lin2lin(self, args)
892 object *self;
893 object *args;
895 signed char *cp;
896 unsigned char *ncp;
897 int len, size, size2, val;
898 object *rv;
899 int i, j;
901 if ( !getargs(args, "(s#ii)",
902 &cp, &len, &size, &size2) )
903 return 0;
905 if ( (size != 1 && size != 2 && size != 4) ||
906 (size2 != 1 && size2 != 2 && size2 != 4)) {
907 err_setstr(AudioopError, "Size should be 1, 2 or 4");
908 return 0;
911 rv = newsizedstringobject(NULL, (len/size)*size2);
912 if ( rv == 0 )
913 return 0;
914 ncp = (unsigned char *)getstringvalue(rv);
916 for ( i=0, j=0; i < len; i += size, j += size2 ) {
917 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
918 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
919 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
921 if ( size2 == 1 ) *CHARP(ncp, j) = (signed char)(val >> 8);
922 else if ( size2 == 2 ) *SHORTP(ncp, j) = (short)(val);
923 else if ( size2 == 4 ) *LONGP(ncp, j) = (long)(val<<16);
925 return rv;
928 static object *
929 audioop_lin2ulaw(self, args)
930 object *self;
931 object *args;
933 signed char *cp;
934 unsigned char *ncp;
935 int len, size, val;
936 object *rv;
937 int i;
939 if ( !getargs(args, "(s#i)",
940 &cp, &len, &size) )
941 return 0;
943 if ( size != 1 && size != 2 && size != 4) {
944 err_setstr(AudioopError, "Size should be 1, 2 or 4");
945 return 0;
948 rv = newsizedstringobject(NULL, len/size);
949 if ( rv == 0 )
950 return 0;
951 ncp = (unsigned char *)getstringvalue(rv);
953 for ( i=0; i < len; i += size ) {
954 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
955 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
956 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
958 *ncp++ = st_linear_to_ulaw(val);
960 return rv;
963 static object *
964 audioop_ulaw2lin(self, args)
965 object *self;
966 object *args;
968 unsigned char *cp;
969 unsigned char cval;
970 signed char *ncp;
971 int len, size, val;
972 object *rv;
973 int i;
975 if ( !getargs(args, "(s#i)",
976 &cp, &len, &size) )
977 return 0;
979 if ( size != 1 && size != 2 && size != 4) {
980 err_setstr(AudioopError, "Size should be 1, 2 or 4");
981 return 0;
984 rv = newsizedstringobject(NULL, len*size);
985 if ( rv == 0 )
986 return 0;
987 ncp = (signed char *)getstringvalue(rv);
989 for ( i=0; i < len*size; i += size ) {
990 cval = *cp++;
991 val = st_ulaw_to_linear(cval);
993 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val >> 8);
994 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val);
995 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val<<16);
997 return rv;
1000 static object *
1001 audioop_lin2adpcm(self, args)
1002 object *self;
1003 object *args;
1005 signed char *cp;
1006 signed char *ncp;
1007 int len, size, val, step, valpred, delta, index, sign, vpdiff, diff;
1008 object *rv, *state, *str;
1009 int i, outputbuffer, bufferstep;
1011 if ( !getargs(args, "(s#iO)",
1012 &cp, &len, &size, &state) )
1013 return 0;
1016 if ( size != 1 && size != 2 && size != 4) {
1017 err_setstr(AudioopError, "Size should be 1, 2 or 4");
1018 return 0;
1021 str = newsizedstringobject(NULL, len/(size*2));
1022 if ( str == 0 )
1023 return 0;
1024 ncp = (signed char *)getstringvalue(str);
1026 /* Decode state, should have (value, step) */
1027 if ( state == None ) {
1028 /* First time, it seems. Set defaults */
1029 valpred = 0;
1030 step = 7;
1031 index = 0;
1032 } else if ( !getargs(state, "(ii)", &valpred, &index) )
1033 return 0;
1035 step = stepsizeTable[index];
1036 bufferstep = 1;
1038 for ( i=0; i < len; i += size ) {
1039 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
1040 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
1041 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
1043 /* Step 1 - compute difference with previous value */
1044 diff = val - valpred;
1045 sign = (diff < 0) ? 8 : 0;
1046 if ( sign ) diff = (-diff);
1048 /* Step 2 - Divide and clamp */
1049 /* Note:
1050 ** This code *approximately* computes:
1051 ** delta = diff*4/step;
1052 ** vpdiff = (delta+0.5)*step/4;
1053 ** but in shift step bits are dropped. The net result of this is
1054 ** that even if you have fast mul/div hardware you cannot put it to
1055 ** good use since the fixup would be too expensive.
1057 delta = 0;
1058 vpdiff = (step >> 3);
1060 if ( diff >= step ) {
1061 delta = 4;
1062 diff -= step;
1063 vpdiff += step;
1065 step >>= 1;
1066 if ( diff >= step ) {
1067 delta |= 2;
1068 diff -= step;
1069 vpdiff += step;
1071 step >>= 1;
1072 if ( diff >= step ) {
1073 delta |= 1;
1074 vpdiff += step;
1077 /* Step 3 - Update previous value */
1078 if ( sign )
1079 valpred -= vpdiff;
1080 else
1081 valpred += vpdiff;
1083 /* Step 4 - Clamp previous value to 16 bits */
1084 if ( valpred > 32767 )
1085 valpred = 32767;
1086 else if ( valpred < -32768 )
1087 valpred = -32768;
1089 /* Step 5 - Assemble value, update index and step values */
1090 delta |= sign;
1092 index += indexTable[delta];
1093 if ( index < 0 ) index = 0;
1094 if ( index > 88 ) index = 88;
1095 step = stepsizeTable[index];
1097 /* Step 6 - Output value */
1098 if ( bufferstep ) {
1099 outputbuffer = (delta << 4) & 0xf0;
1100 } else {
1101 *ncp++ = (delta & 0x0f) | outputbuffer;
1103 bufferstep = !bufferstep;
1105 rv = mkvalue("(O(ii))", str, valpred, index);
1106 DECREF(str);
1107 return rv;
1110 static object *
1111 audioop_adpcm2lin(self, args)
1112 object *self;
1113 object *args;
1115 signed char *cp;
1116 signed char *ncp;
1117 int len, size, valpred, step, delta, index, sign, vpdiff;
1118 object *rv, *str, *state;
1119 int i, inputbuffer, bufferstep;
1121 if ( !getargs(args, "(s#iO)",
1122 &cp, &len, &size, &state) )
1123 return 0;
1125 if ( size != 1 && size != 2 && size != 4) {
1126 err_setstr(AudioopError, "Size should be 1, 2 or 4");
1127 return 0;
1130 /* Decode state, should have (value, step) */
1131 if ( state == None ) {
1132 /* First time, it seems. Set defaults */
1133 valpred = 0;
1134 step = 7;
1135 index = 0;
1136 } else if ( !getargs(state, "(ii)", &valpred, &index) )
1137 return 0;
1139 str = newsizedstringobject(NULL, len*size*2);
1140 if ( str == 0 )
1141 return 0;
1142 ncp = (signed char *)getstringvalue(str);
1144 step = stepsizeTable[index];
1145 bufferstep = 0;
1147 for ( i=0; i < len*size*2; i += size ) {
1148 /* Step 1 - get the delta value and compute next index */
1149 if ( bufferstep ) {
1150 delta = inputbuffer & 0xf;
1151 } else {
1152 inputbuffer = *cp++;
1153 delta = (inputbuffer >> 4) & 0xf;
1156 bufferstep = !bufferstep;
1158 /* Step 2 - Find new index value (for later) */
1159 index += indexTable[delta];
1160 if ( index < 0 ) index = 0;
1161 if ( index > 88 ) index = 88;
1163 /* Step 3 - Separate sign and magnitude */
1164 sign = delta & 8;
1165 delta = delta & 7;
1167 /* Step 4 - Compute difference and new predicted value */
1169 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
1170 ** in adpcm_coder.
1172 vpdiff = step >> 3;
1173 if ( delta & 4 ) vpdiff += step;
1174 if ( delta & 2 ) vpdiff += step>>1;
1175 if ( delta & 1 ) vpdiff += step>>2;
1177 if ( sign )
1178 valpred -= vpdiff;
1179 else
1180 valpred += vpdiff;
1182 /* Step 5 - clamp output value */
1183 if ( valpred > 32767 )
1184 valpred = 32767;
1185 else if ( valpred < -32768 )
1186 valpred = -32768;
1188 /* Step 6 - Update step value */
1189 step = stepsizeTable[index];
1191 /* Step 6 - Output value */
1192 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valpred >> 8);
1193 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valpred);
1194 else if ( size == 4 ) *LONGP(ncp, i) = (long)(valpred<<16);
1197 rv = mkvalue("(O(ii))", str, valpred, index);
1198 DECREF(str);
1199 return rv;
1202 static struct methodlist audioop_methods[] = {
1203 { "max", audioop_max },
1204 { "minmax", audioop_minmax },
1205 { "avg", audioop_avg },
1206 { "maxpp", audioop_maxpp },
1207 { "avgpp", audioop_avgpp },
1208 { "rms", audioop_rms },
1209 { "findfit", audioop_findfit },
1210 { "findmax", audioop_findmax },
1211 { "findfactor", audioop_findfactor },
1212 { "cross", audioop_cross },
1213 { "mul", audioop_mul },
1214 { "add", audioop_add },
1215 { "bias", audioop_bias },
1216 { "ulaw2lin", audioop_ulaw2lin },
1217 { "lin2ulaw", audioop_lin2ulaw },
1218 { "lin2lin", audioop_lin2lin },
1219 { "adpcm2lin", audioop_adpcm2lin },
1220 { "lin2adpcm", audioop_lin2adpcm },
1221 { "tomono", audioop_tomono },
1222 { "tostereo", audioop_tostereo },
1223 { "getsample", audioop_getsample },
1224 { "reverse", audioop_reverse },
1225 { 0, 0 }
1229 void
1230 initaudioop()
1232 object *m, *d;
1233 m = initmodule("audioop", audioop_methods);
1234 d = getmoduledict(m);
1235 AudioopError = newstringobject("audioop.error");
1236 if ( AudioopError == NULL || dictinsert(d,"error",AudioopError) )
1237 fatal("can't define audioop.error");