blob: bfc6fda28be36503f4cb0335cb1d89db743e043e [file] [log] [blame]
Guido van Rossumb66efa01992-06-01 16:01:24 +00001/***********************************************************
Guido van Rossum34679b71993-01-26 13:33:44 +00002Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3Amsterdam, The Netherlands.
Guido van Rossumb66efa01992-06-01 16:01:24 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* audioopmodele - Module to detect peak values in arrays */
26
27#ifdef sun
28#define signed
29#endif
30
Jack Jansene1b4d7c1992-08-24 14:36:31 +000031#include <math.h>
32
Guido van Rossumb66efa01992-06-01 16:01:24 +000033#include "allobjects.h"
34#include "modsupport.h"
35
Jack Jansena90805f1993-02-17 14:29:28 +000036/* Code shamelessly stolen from sox,
Guido van Rossumb66efa01992-06-01 16:01:24 +000037** (c) Craig Reese, Joe Campbell and Jeff Poskanzer 1989 */
38
39#define MINLIN -32768
40#define MAXLIN 32767
41#define LINCLIP(x) do { if ( x < MINLIN ) x = MINLIN ; else if ( x > MAXLIN ) x = MAXLIN; } while ( 0 )
42
43unsigned char st_linear_to_ulaw( /* int sample */ );
44
45/*
46** This macro converts from ulaw to 16 bit linear, faster.
47**
48** Jef Poskanzer
49** 23 October 1989
50**
51** Input: 8 bit ulaw sample
52** Output: signed 16 bit linear sample
53*/
54#define st_ulaw_to_linear(ulawbyte) ulaw_table[ulawbyte]
55
56static int ulaw_table[256] = {
57 -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
58 -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
59 -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
60 -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316,
61 -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
62 -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
63 -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
64 -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
65 -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
66 -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
67 -876, -844, -812, -780, -748, -716, -684, -652,
68 -620, -588, -556, -524, -492, -460, -428, -396,
69 -372, -356, -340, -324, -308, -292, -276, -260,
70 -244, -228, -212, -196, -180, -164, -148, -132,
71 -120, -112, -104, -96, -88, -80, -72, -64,
72 -56, -48, -40, -32, -24, -16, -8, 0,
73 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
74 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
75 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
76 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
77 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
78 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
79 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
80 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
81 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
82 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
83 876, 844, 812, 780, 748, 716, 684, 652,
84 620, 588, 556, 524, 492, 460, 428, 396,
85 372, 356, 340, 324, 308, 292, 276, 260,
86 244, 228, 212, 196, 180, 164, 148, 132,
87 120, 112, 104, 96, 88, 80, 72, 64,
88 56, 48, 40, 32, 24, 16, 8, 0 };
89
90#define ZEROTRAP /* turn on the trap as per the MIL-STD */
91#define BIAS 0x84 /* define the add-in bias for 16 bit samples */
92#define CLIP 32635
93
94unsigned char
95st_linear_to_ulaw( sample )
96int sample;
97 {
98 static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
99 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
100 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
101 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
102 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
103 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
104 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
105 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
106 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
107 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
108 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
109 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
110 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
111 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
112 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
113 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
114 int sign, exponent, mantissa;
115 unsigned char ulawbyte;
116
117 /* Get the sample into sign-magnitude. */
118 sign = (sample >> 8) & 0x80; /* set aside the sign */
119 if ( sign != 0 ) sample = -sample; /* get magnitude */
120 if ( sample > CLIP ) sample = CLIP; /* clip the magnitude */
121
122 /* Convert from 16 bit linear to ulaw. */
123 sample = sample + BIAS;
124 exponent = exp_lut[( sample >> 7 ) & 0xFF];
125 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
126 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
127#ifdef ZEROTRAP
128 if ( ulawbyte == 0 ) ulawbyte = 0x02; /* optional CCITT trap */
129#endif
130
131 return ulawbyte;
132 }
133/* End of code taken from sox */
134
Guido van Rossumb64e6351992-07-06 14:21:56 +0000135/* ADPCM-3 step variation table */
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000136static float newstep[5] = { 0.8, 0.9, 1.0, 1.75, 1.75 };
137
Guido van Rossumb64e6351992-07-06 14:21:56 +0000138/* Intel ADPCM step variation table */
139static int indexTable[16] = {
140 -1, -1, -1, -1, 2, 4, 6, 8,
141 -1, -1, -1, -1, 2, 4, 6, 8,
142};
143
144static int stepsizeTable[89] = {
145 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
146 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
147 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
148 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
149 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
150 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
151 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
152 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
153 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
154};
155
Guido van Rossumb66efa01992-06-01 16:01:24 +0000156#define CHARP(cp, i) ((signed char *)(cp+i))
157#define SHORTP(cp, i) ((short *)(cp+i))
158#define LONGP(cp, i) ((long *)(cp+i))
159
160
161
162static object *AudioopError;
163
164static object *
165audioop_getsample(self, args)
166 object *self;
167 object *args;
168{
169 signed char *cp;
170 int len, size, val;
171 int i;
172
173 if ( !getargs(args, "(s#ii)", &cp, &len, &size, &i) )
174 return 0;
175 if ( size != 1 && size != 2 && size != 4 ) {
176 err_setstr(AudioopError, "Size should be 1, 2 or 4");
177 return 0;
178 }
179 if ( i < 0 || i >= len/size ) {
180 err_setstr(AudioopError, "Index out of range");
181 return 0;
182 }
183 if ( size == 1 ) val = (int)*CHARP(cp, i);
184 else if ( size == 2 ) val = (int)*SHORTP(cp, i*2);
185 else if ( size == 4 ) val = (int)*LONGP(cp, i*4);
186 return newintobject(val);
187}
188
189static object *
190audioop_max(self, args)
191 object *self;
192 object *args;
193{
194 signed char *cp;
195 int len, size, val;
196 int i;
197 int max = 0;
198
199 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
200 return 0;
201 if ( size != 1 && size != 2 && size != 4 ) {
202 err_setstr(AudioopError, "Size should be 1, 2 or 4");
203 return 0;
204 }
205 for ( i=0; i<len; i+= size) {
206 if ( size == 1 ) val = (int)*CHARP(cp, i);
207 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
208 else if ( size == 4 ) val = (int)*LONGP(cp, i);
209 if ( val < 0 ) val = (-val);
210 if ( val > max ) max = val;
211 }
212 return newintobject(max);
213}
214
215static object *
216audioop_avg(self, args)
217 object *self;
218 object *args;
219{
220 signed char *cp;
221 int len, size, val;
222 int i;
223 float avg = 0.0;
224
225 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
226 return 0;
227 if ( size != 1 && size != 2 && size != 4 ) {
228 err_setstr(AudioopError, "Size should be 1, 2 or 4");
229 return 0;
230 }
231 for ( i=0; i<len; i+= size) {
232 if ( size == 1 ) val = (int)*CHARP(cp, i);
233 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
234 else if ( size == 4 ) val = (int)*LONGP(cp, i);
235 avg += val;
236 }
237 if ( len == 0 )
238 val = 0;
239 else
240 val = (int)(avg / (float)(len/size));
241 return newintobject(val);
242}
243
244static object *
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000245audioop_rms(self, args)
246 object *self;
247 object *args;
248{
249 signed char *cp;
250 int len, size, val;
251 int i;
252 float sum_squares = 0.0;
253
254 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
255 return 0;
256 if ( size != 1 && size != 2 && size != 4 ) {
257 err_setstr(AudioopError, "Size should be 1, 2 or 4");
258 return 0;
259 }
260 for ( i=0; i<len; i+= size) {
261 if ( size == 1 ) val = (int)*CHARP(cp, i);
262 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
263 else if ( size == 4 ) val = (int)*LONGP(cp, i);
264 sum_squares += (float)val*(float)val;
265 }
266 if ( len == 0 )
267 val = 0;
268 else
269 val = (int)sqrt(sum_squares / (float)(len/size));
270 return newintobject(val);
271}
272
Jack Jansena90805f1993-02-17 14:29:28 +0000273double _sum2(a, b, len)
274 short *a;
275 short *b;
276 int len;
277{
278 int i;
279 double sum = 0.0;
280
281 for( i=0; i<len; i++) {
282 sum = sum + (double)a[i]*(double)b[i];
283 }
284 return sum;
285}
286
287/*
288** Findfit tries to locate a sample within another sample. Its main use
289** is in echo-cancellation (to find the feedback of the output signal in
290** the input signal).
291** The method used is as follows:
292**
293** let R be the reference signal (length n) and A the input signal (length N)
294** with N > n, and let all sums be over i from 0 to n-1.
295**
296** Now, for each j in {0..N-n} we compute a factor fj so that -fj*R matches A
297** as good as possible, i.e. sum( (A[j+i]+fj*R[i])^2 ) is minimal. This
298** equation gives fj = sum( A[j+i]R[i] ) / sum(R[i]^2).
299**
300** Next, we compute the relative distance between the original signal and
301** the modified signal and minimize that over j:
302** vj = sum( (A[j+i]-fj*R[i])^2 ) / sum( A[j+i]^2 ) =>
303** vj = ( sum(A[j+i]^2)*sum(R[i]^2) - sum(A[j+i]R[i])^2 ) / sum( A[j+i]^2 )
304**
305** In the code variables correspond as follows:
306** cp1 A
307** cp2 R
308** len1 N
309** len2 n
310** aj_m1 A[j-1]
311** aj_lm1 A[j+n-1]
312** sum_ri_2 sum(R[i]^2)
313** sum_aij_2 sum(A[i+j]^2)
314** sum_aij_ri sum(A[i+j]R[i])
315**
316** sum_ri is calculated once, sum_aij_2 is updated each step and sum_aij_ri
317** is completely recalculated each step.
318*/
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000319static object *
Jack Jansena90805f1993-02-17 14:29:28 +0000320audioop_findfit(self, args)
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000321 object *self;
322 object *args;
323{
Jack Jansena90805f1993-02-17 14:29:28 +0000324 short *cp1, *cp2;
325 int len1, len2;
326 int j, best_j;
327 double aj_m1, aj_lm1;
328 double sum_ri_2, sum_aij_2, sum_aij_ri, result, best_result, factor;
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000329
Jack Jansena90805f1993-02-17 14:29:28 +0000330 if ( !getargs(args, "(s#s#)", &cp1, &len1, &cp2, &len2) )
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000331 return 0;
Jack Jansena90805f1993-02-17 14:29:28 +0000332 if ( len1 & 1 || len2 & 1 ) {
333 err_setstr(AudioopError, "Strings should be even-sized");
334 return 0;
335 }
336 len1 >>= 1;
337 len2 >>= 1;
338
339 if ( len1 < len2 ) {
340 err_setstr(AudioopError, "First sample should be longer");
341 return 0;
342 }
343 sum_ri_2 = _sum2(cp2, cp2, len2);
344 sum_aij_2 = _sum2(cp1, cp1, len2);
345 sum_aij_ri = _sum2(cp1, cp2, len2);
346
347 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
348
349 best_result = result;
350 best_j = 0;
351 j = 0;
352
353 for ( j=1; j<=len1-len2; j++) {
354 aj_m1 = (double)cp1[j-1];
355 aj_lm1 = (double)cp1[j+len2-1];
356
357 sum_aij_2 = sum_aij_2 + aj_lm1*aj_lm1 - aj_m1*aj_m1;
358 sum_aij_ri = _sum2(cp1+j, cp2, len2);
359
360 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
361
362 if ( result < best_result ) {
363 best_result = result;
364 best_j = j;
365 }
366
367 }
368
369 factor = _sum2(cp1+best_j, cp2, len2) / sum_ri_2;
370
371 return mkvalue("(if)", best_j, factor);
372}
373
374/*
375** findfactor finds a factor f so that the energy in A-fB is minimal.
376** See the comment for findfit for details.
377*/
378static object *
379audioop_findfactor(self, args)
380 object *self;
381 object *args;
382{
383 short *cp1, *cp2;
384 int len1, len2;
385 double sum_ri_2, sum_aij_ri, result;
386
387 if ( !getargs(args, "(s#s#)", &cp1, &len1, &cp2, &len2) )
388 return 0;
389 if ( len1 & 1 || len2 & 1 ) {
390 err_setstr(AudioopError, "Strings should be even-sized");
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000391 return 0;
392 }
393 if ( len1 != len2 ) {
394 err_setstr(AudioopError, "Samples should be same size");
395 return 0;
396 }
Jack Jansena90805f1993-02-17 14:29:28 +0000397 len2 >>= 1;
398 sum_ri_2 = _sum2(cp2, cp2, len2);
399 sum_aij_ri = _sum2(cp1, cp2, len2);
400
401 result = sum_aij_ri / sum_ri_2;
402
403 return newfloatobject(result);
404}
405
406/*
407** findmax returns the index of the n-sized segment of the input sample
408** that contains the most energy.
409*/
410static object *
411audioop_findmax(self, args)
412 object *self;
413 object *args;
414{
415 short *cp1;
416 int len1, len2;
417 int j, best_j;
418 double aj_m1, aj_lm1;
419 double result, best_result;
420
421 if ( !getargs(args, "(s#i)", &cp1, &len1, &len2) )
422 return 0;
423 if ( len1 & 1 ) {
424 err_setstr(AudioopError, "Strings should be even-sized");
425 return 0;
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000426 }
Jack Jansena90805f1993-02-17 14:29:28 +0000427 len1 >>= 1;
428
429 if ( len1 < len2 ) {
430 err_setstr(AudioopError, "Input sample should be longer");
431 return 0;
432 }
433
434 result = _sum2(cp1, cp1, len2);
435
436 best_result = result;
437 best_j = 0;
438 j = 0;
439
440 for ( j=1; j<=len1-len2; j++) {
441 aj_m1 = (double)cp1[j-1];
442 aj_lm1 = (double)cp1[j+len2-1];
443
444 result = result + aj_lm1*aj_lm1 - aj_m1*aj_m1;
445
446 if ( result > best_result ) {
447 best_result = result;
448 best_j = j;
449 }
450
451 }
452
453 return newintobject(best_j);
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000454}
455
456static object *
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000457audioop_avgpp(self, args)
458 object *self;
459 object *args;
460{
461 signed char *cp;
462 int len, size, val, prevval, prevextremevalid = 0, prevextreme;
463 int i;
464 float avg = 0.0;
465 int diff, prevdiff, extremediff, nextreme = 0;
466
467 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
468 return 0;
469 if ( size != 1 && size != 2 && size != 4 ) {
470 err_setstr(AudioopError, "Size should be 1, 2 or 4");
471 return 0;
472 }
473 /* Compute first delta value ahead. Also automatically makes us
474 ** skip the first extreme value
475 */
476 if ( size == 1 ) prevval = (int)*CHARP(cp, 0);
477 else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
478 else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
479 if ( size == 1 ) val = (int)*CHARP(cp, size);
480 else if ( size == 2 ) val = (int)*SHORTP(cp, size);
481 else if ( size == 4 ) val = (int)*LONGP(cp, size);
482 prevdiff = val - prevval;
483
484 for ( i=size; i<len; i+= size) {
485 if ( size == 1 ) val = (int)*CHARP(cp, i);
486 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
487 else if ( size == 4 ) val = (int)*LONGP(cp, i);
488 diff = val - prevval;
489 if ( diff*prevdiff < 0 ) {
490 /* Derivative changed sign. Compute difference to last extreme
491 ** value and remember.
492 */
493 if ( prevextremevalid ) {
494 extremediff = prevval - prevextreme;
495 if ( extremediff < 0 )
496 extremediff = -extremediff;
497 avg += extremediff;
498 nextreme++;
499 }
500 prevextremevalid = 1;
501 prevextreme = prevval;
502 }
503 prevval = val;
504 if ( diff != 0 )
505 prevdiff = diff;
506 }
507 if ( nextreme == 0 )
508 val = 0;
509 else
510 val = (int)(avg / (float)nextreme);
511 return newintobject(val);
512}
513
514static object *
515audioop_maxpp(self, args)
516 object *self;
517 object *args;
518{
519 signed char *cp;
520 int len, size, val, prevval, prevextremevalid = 0, prevextreme;
521 int i;
522 int max = 0;
523 int diff, prevdiff, extremediff;
524
525 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
526 return 0;
527 if ( size != 1 && size != 2 && size != 4 ) {
528 err_setstr(AudioopError, "Size should be 1, 2 or 4");
529 return 0;
530 }
531 /* Compute first delta value ahead. Also automatically makes us
532 ** skip the first extreme value
533 */
534 if ( size == 1 ) prevval = (int)*CHARP(cp, 0);
535 else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
536 else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
537 if ( size == 1 ) val = (int)*CHARP(cp, size);
538 else if ( size == 2 ) val = (int)*SHORTP(cp, size);
539 else if ( size == 4 ) val = (int)*LONGP(cp, size);
540 prevdiff = val - prevval;
541
542 for ( i=size; i<len; i+= size) {
543 if ( size == 1 ) val = (int)*CHARP(cp, i);
544 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
545 else if ( size == 4 ) val = (int)*LONGP(cp, i);
546 diff = val - prevval;
547 if ( diff*prevdiff < 0 ) {
548 /* Derivative changed sign. Compute difference to last extreme
549 ** value and remember.
550 */
551 if ( prevextremevalid ) {
552 extremediff = prevval - prevextreme;
553 if ( extremediff < 0 )
554 extremediff = -extremediff;
555 if ( extremediff > max )
556 max = extremediff;
557 }
558 prevextremevalid = 1;
559 prevextreme = prevval;
560 }
561 prevval = val;
562 if ( diff != 0 )
563 prevdiff = diff;
564 }
565 return newintobject(max);
566}
567
568static object *
Guido van Rossumb66efa01992-06-01 16:01:24 +0000569audioop_cross(self, args)
570 object *self;
571 object *args;
572{
573 signed char *cp;
574 int len, size, val;
575 int i;
576 int cross, prevval, ncross;
577
578 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
579 return 0;
580 if ( size != 1 && size != 2 && size != 4 ) {
581 err_setstr(AudioopError, "Size should be 1, 2 or 4");
582 return 0;
583 }
584 ncross = -1;
585 prevval = 17; /* Anything <> 0,1 */
586 for ( i=0; i<len; i+= size) {
587 if ( size == 1 ) val = ((int)*CHARP(cp, i)) >> 7;
588 else if ( size == 2 ) val = ((int)*SHORTP(cp, i)) >> 15;
589 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 31;
590 val = val & 1;
591 if ( val != prevval ) ncross++;
592 prevval = val;
593 }
594 return newintobject(ncross);
595}
596
597static object *
598audioop_mul(self, args)
599 object *self;
600 object *args;
601{
602 signed char *cp, *ncp;
603 int len, size, val;
604 double factor, fval, maxval;
605 object *rv;
606 int i;
607
608 if ( !getargs(args, "(s#id)", &cp, &len, &size, &factor ) )
609 return 0;
610
611 if ( size == 1 ) maxval = (double) 0x7f;
612 else if ( size == 2 ) maxval = (double) 0x7fff;
613 else if ( size == 4 ) maxval = (double) 0x7fffffff;
614 else {
615 err_setstr(AudioopError, "Size should be 1, 2 or 4");
616 return 0;
617 }
618
619 rv = newsizedstringobject(NULL, len);
620 if ( rv == 0 )
621 return 0;
622 ncp = (signed char *)getstringvalue(rv);
623
624
625 for ( i=0; i < len; i += size ) {
626 if ( size == 1 ) val = (int)*CHARP(cp, i);
627 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
628 else if ( size == 4 ) val = (int)*LONGP(cp, i);
629 fval = (double)val*factor;
630 if ( fval > maxval ) fval = maxval;
631 else if ( fval < -maxval ) fval = -maxval;
632 val = (int)fval;
633 if ( size == 1 ) *CHARP(ncp, i) = (signed char)val;
634 else if ( size == 2 ) *SHORTP(ncp, i) = (short)val;
635 else if ( size == 4 ) *LONGP(ncp, i) = (long)val;
636 }
637 return rv;
638}
639
640static object *
641audioop_tomono(self, args)
642 object *self;
643 object *args;
644{
645 signed char *cp, *ncp;
646 int len, size, val1, val2;
647 double fac1, fac2, fval, maxval;
648 object *rv;
649 int i;
650
651 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
652 return 0;
653
654 if ( size == 1 ) maxval = (double) 0x7f;
655 else if ( size == 2 ) maxval = (double) 0x7fff;
656 else if ( size == 4 ) maxval = (double) 0x7fffffff;
657 else {
658 err_setstr(AudioopError, "Size should be 1, 2 or 4");
659 return 0;
660 }
661
662 rv = newsizedstringobject(NULL, len/2);
663 if ( rv == 0 )
664 return 0;
665 ncp = (signed char *)getstringvalue(rv);
666
667
668 for ( i=0; i < len; i += size*2 ) {
669 if ( size == 1 ) val1 = (int)*CHARP(cp, i);
670 else if ( size == 2 ) val1 = (int)*SHORTP(cp, i);
671 else if ( size == 4 ) val1 = (int)*LONGP(cp, i);
672 if ( size == 1 ) val2 = (int)*CHARP(cp, i+1);
673 else if ( size == 2 ) val2 = (int)*SHORTP(cp, i+2);
674 else if ( size == 4 ) val2 = (int)*LONGP(cp, i+4);
675 fval = (double)val1*fac1 + (double)val2*fac2;
676 if ( fval > maxval ) fval = maxval;
677 else if ( fval < -maxval ) fval = -maxval;
678 val1 = (int)fval;
679 if ( size == 1 ) *CHARP(ncp, i/2) = (signed char)val1;
680 else if ( size == 2 ) *SHORTP(ncp, i/2) = (short)val1;
681 else if ( size == 4 ) *LONGP(ncp, i/2)= (long)val1;
682 }
683 return rv;
684}
685
686static object *
687audioop_tostereo(self, args)
688 object *self;
689 object *args;
690{
691 signed char *cp, *ncp;
692 int len, size, val1, val2, val;
693 double fac1, fac2, fval, maxval;
694 object *rv;
695 int i;
696
697 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
698 return 0;
699
700 if ( size == 1 ) maxval = (double) 0x7f;
701 else if ( size == 2 ) maxval = (double) 0x7fff;
702 else if ( size == 4 ) maxval = (double) 0x7fffffff;
703 else {
704 err_setstr(AudioopError, "Size should be 1, 2 or 4");
705 return 0;
706 }
707
708 rv = newsizedstringobject(NULL, len*2);
709 if ( rv == 0 )
710 return 0;
711 ncp = (signed char *)getstringvalue(rv);
712
713
714 for ( i=0; i < len; i += size ) {
715 if ( size == 1 ) val = (int)*CHARP(cp, i);
716 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
717 else if ( size == 4 ) val = (int)*LONGP(cp, i);
718
719 fval = (double)val*fac1;
720 if ( fval > maxval ) fval = maxval;
721 else if ( fval < -maxval ) fval = -maxval;
722 val1 = (int)fval;
723
724 fval = (double)val*fac2;
725 if ( fval > maxval ) fval = maxval;
726 else if ( fval < -maxval ) fval = -maxval;
727 val2 = (int)fval;
728
729 if ( size == 1 ) *CHARP(ncp, i*2) = (signed char)val1;
730 else if ( size == 2 ) *SHORTP(ncp, i*2) = (short)val1;
731 else if ( size == 4 ) *LONGP(ncp, i*2) = (long)val1;
732
733 if ( size == 1 ) *CHARP(ncp, i*2+1) = (signed char)val2;
734 else if ( size == 2 ) *SHORTP(ncp, i*2+2) = (short)val2;
735 else if ( size == 4 ) *LONGP(ncp, i*2+4) = (long)val2;
736 }
737 return rv;
738}
739
740static object *
741audioop_add(self, args)
742 object *self;
743 object *args;
744{
745 signed char *cp1, *cp2, *ncp;
746 int len1, len2, size, val1, val2;
747 object *rv;
748 int i;
749
750 if ( !getargs(args, "(s#s#i)",
751 &cp1, &len1, &cp2, &len2, &size ) )
752 return 0;
753
754 if ( len1 != len2 ) {
755 err_setstr(AudioopError, "Lengths should be the same");
756 return 0;
757 }
758
759 if ( size != 1 && size != 2 && size != 4) {
760 err_setstr(AudioopError, "Size should be 1, 2 or 4");
761 return 0;
762 }
763
764 rv = newsizedstringobject(NULL, len1);
765 if ( rv == 0 )
766 return 0;
767 ncp = (signed char *)getstringvalue(rv);
768
769
770 for ( i=0; i < len1; i += size ) {
771 if ( size == 1 ) val1 = (int)*CHARP(cp1, i);
772 else if ( size == 2 ) val1 = (int)*SHORTP(cp1, i);
773 else if ( size == 4 ) val1 = (int)*LONGP(cp1, i);
774
775 if ( size == 1 ) val2 = (int)*CHARP(cp2, i);
776 else if ( size == 2 ) val2 = (int)*SHORTP(cp2, i);
777 else if ( size == 4 ) val2 = (int)*LONGP(cp2, i);
778
779 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val1+val2);
780 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val1+val2);
781 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val1+val2);
782 }
783 return rv;
784}
785
786static object *
787audioop_bias(self, args)
788 object *self;
789 object *args;
790{
791 signed char *cp, *ncp;
792 int len, size, val;
793 object *rv;
794 int i;
795 int bias;
796
797 if ( !getargs(args, "(s#ii)",
798 &cp, &len, &size , &bias) )
799 return 0;
800
801 if ( size != 1 && size != 2 && size != 4) {
802 err_setstr(AudioopError, "Size should be 1, 2 or 4");
803 return 0;
804 }
805
806 rv = newsizedstringobject(NULL, len);
807 if ( rv == 0 )
808 return 0;
809 ncp = (signed char *)getstringvalue(rv);
810
811
812 for ( i=0; i < len; i += size ) {
813 if ( size == 1 ) val = (int)*CHARP(cp, i);
814 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
815 else if ( size == 4 ) val = (int)*LONGP(cp, i);
816
817 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val+bias);
818 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val+bias);
819 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val+bias);
820 }
821 return rv;
822}
823
824static object *
Jack Jansen337b20e1993-02-23 13:39:57 +0000825audioop_reverse(self, args)
826 object *self;
827 object *args;
828{
829 signed char *cp;
830 unsigned char *ncp;
831 int len, size, val;
832 object *rv;
833 int i, j;
834
835 if ( !getargs(args, "(s#i)",
836 &cp, &len, &size) )
837 return 0;
838
839 if ( size != 1 && size != 2 && size != 4 ) {
840 err_setstr(AudioopError, "Size should be 1, 2 or 4");
841 return 0;
842 }
843
844 rv = newsizedstringobject(NULL, len);
845 if ( rv == 0 )
846 return 0;
847 ncp = (unsigned char *)getstringvalue(rv);
848
849 for ( i=0; i < len; i += size ) {
850 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
851 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
852 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
853
854 j = len - i - size;
855
856 if ( size == 1 ) *CHARP(ncp, j) = (signed char)(val >> 8);
857 else if ( size == 2 ) *SHORTP(ncp, j) = (short)(val);
858 else if ( size == 4 ) *LONGP(ncp, j) = (long)(val<<16);
859 }
860 return rv;
861}
862
863static object *
Jack Jansena90805f1993-02-17 14:29:28 +0000864audioop_lin2lin(self, args)
865 object *self;
866 object *args;
867{
868 signed char *cp;
869 unsigned char *ncp;
870 int len, size, size2, val;
871 object *rv;
872 int i, j;
873
874 if ( !getargs(args, "(s#ii)",
875 &cp, &len, &size, &size2) )
876 return 0;
877
878 if ( (size != 1 && size != 2 && size != 4) ||
879 (size2 != 1 && size2 != 2 && size2 != 4)) {
880 err_setstr(AudioopError, "Size should be 1, 2 or 4");
881 return 0;
882 }
883
884 rv = newsizedstringobject(NULL, (len/size)*size2);
885 if ( rv == 0 )
886 return 0;
887 ncp = (unsigned char *)getstringvalue(rv);
888
889 for ( i=0, j=0; i < len; i += size, j += size2 ) {
890 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
891 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
892 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
893
894 if ( size2 == 1 ) *CHARP(ncp, j) = (signed char)(val >> 8);
895 else if ( size2 == 2 ) *SHORTP(ncp, j) = (short)(val);
896 else if ( size2 == 4 ) *LONGP(ncp, j) = (long)(val<<16);
897 }
898 return rv;
899}
900
901static object *
Guido van Rossumb66efa01992-06-01 16:01:24 +0000902audioop_lin2ulaw(self, args)
903 object *self;
904 object *args;
905{
906 signed char *cp;
907 unsigned char *ncp;
908 int len, size, val;
909 object *rv;
910 int i;
911
912 if ( !getargs(args, "(s#i)",
913 &cp, &len, &size) )
914 return 0;
915
916 if ( size != 1 && size != 2 && size != 4) {
917 err_setstr(AudioopError, "Size should be 1, 2 or 4");
918 return 0;
919 }
920
921 rv = newsizedstringobject(NULL, len/size);
922 if ( rv == 0 )
923 return 0;
924 ncp = (unsigned char *)getstringvalue(rv);
925
926 for ( i=0; i < len; i += size ) {
927 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
928 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
929 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
930
931 *ncp++ = st_linear_to_ulaw(val);
932 }
933 return rv;
934}
935
936static object *
937audioop_ulaw2lin(self, args)
938 object *self;
939 object *args;
940{
941 unsigned char *cp;
942 unsigned char cval;
943 signed char *ncp;
944 int len, size, val;
945 object *rv;
946 int i;
947
948 if ( !getargs(args, "(s#i)",
949 &cp, &len, &size) )
950 return 0;
951
952 if ( size != 1 && size != 2 && size != 4) {
953 err_setstr(AudioopError, "Size should be 1, 2 or 4");
954 return 0;
955 }
956
957 rv = newsizedstringobject(NULL, len*size);
958 if ( rv == 0 )
959 return 0;
960 ncp = (signed char *)getstringvalue(rv);
961
962 for ( i=0; i < len*size; i += size ) {
963 cval = *cp++;
964 val = st_ulaw_to_linear(cval);
965
966 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val >> 8);
967 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val);
Guido van Rossumaad53441992-06-05 15:11:56 +0000968 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val<<16);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000969 }
970 return rv;
971}
972
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000973static object *
Guido van Rossumb64e6351992-07-06 14:21:56 +0000974audioop_lin2adpcm3(self, args)
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000975 object *self;
976 object *args;
977{
978 signed char *cp;
979 signed char *ncp;
980 int len, size, val, step, valprev, delta;
981 object *rv, *state, *str;
982 int i;
983
984 if ( !getargs(args, "(s#iO)",
985 &cp, &len, &size, &state) )
986 return 0;
987
988
989 if ( size != 1 && size != 2 && size != 4) {
990 err_setstr(AudioopError, "Size should be 1, 2 or 4");
991 return 0;
992 }
993
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000994 str = newsizedstringobject(NULL, len/size);
995 if ( str == 0 )
996 return 0;
997 ncp = (signed char *)getstringvalue(str);
998
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000999 /* Decode state, should have (value, step) */
1000 if ( state == None ) {
1001 /* First time, it seems. Set defaults */
1002 valprev = 0;
1003 step = 4; /* The '4' is magic. Dunno it's significance */
1004 } else if ( !getargs(state, "(ii)", &valprev, &step) )
1005 return 0;
1006
1007 for ( i=0; i < len; i += size ) {
1008 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
1009 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
1010 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
1011
1012 /* Step 1 - compute difference with previous value */
1013 delta = (val - valprev)/step;
1014
1015 /* Step 2 - Clamp */
1016 if ( delta < -4 )
1017 delta = -4;
1018 else if ( delta > 3 )
1019 delta = 3;
1020
1021 /* Step 3 - Update previous value */
1022 valprev += delta*step;
1023
1024 /* Step 4 - Clamp previous value to 16 bits */
1025 if ( valprev > 32767 )
1026 valprev = 32767;
1027 else if ( valprev < -32768 )
1028 valprev = -32768;
1029
1030 /* Step 5 - Update step value */
1031 step = step * newstep[abs(delta)];
1032 step++; /* Don't understand this. */
1033
1034 /* Step 6 - Output value (as a whole byte, currently) */
1035 *ncp++ = delta;
1036 }
1037 rv = mkvalue("(O(ii))", str, valprev, step);
1038 DECREF(str);
1039 return rv;
1040}
1041
1042static object *
Guido van Rossumb64e6351992-07-06 14:21:56 +00001043audioop_adpcm32lin(self, args)
Guido van Rossum8e7a0f01992-06-23 15:23:57 +00001044 object *self;
1045 object *args;
1046{
1047 signed char *cp;
1048 signed char *ncp;
1049 int len, size, val, valprev, step, delta;
1050 object *rv, *str, *state;
1051 int i;
1052
1053 if ( !getargs(args, "(s#iO)",
1054 &cp, &len, &size, &state) )
1055 return 0;
1056
1057 if ( size != 1 && size != 2 && size != 4) {
1058 err_setstr(AudioopError, "Size should be 1, 2 or 4");
1059 return 0;
1060 }
1061
1062 /* Decode state, should have (value, step) */
1063 if ( state == None ) {
1064 /* First time, it seems. Set defaults */
1065 valprev = 0;
1066 step = 4; /* The '4' is magic. Dunno it's significance */
1067 } else if ( !getargs(state, "(ii)", &valprev, &step) )
1068 return 0;
1069
1070 str = newsizedstringobject(NULL, len*size);
1071 if ( str == 0 )
1072 return 0;
1073 ncp = (signed char *)getstringvalue(str);
1074
1075 for ( i=0; i < len*size; i += size ) {
1076 /* Step 1 - get the delta value */
1077 delta = *cp++;
1078
1079 /* Step 2 - update output value */
1080 valprev = valprev + delta*step;
1081
1082 /* Step 3 - clamp output value */
1083 if ( valprev > 32767 )
1084 valprev = 32767;
1085 else if ( valprev < -32768 )
1086 valprev = -32768;
1087
1088 /* Step 4 - Update step value */
1089 step = step * newstep[abs(delta)];
1090 step++;
1091
1092 /* Step 5 - Output value */
1093 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valprev >> 8);
1094 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valprev);
1095 else if ( size == 4 ) *LONGP(ncp, i) = (long)(valprev<<16);
1096 }
1097
1098 rv = mkvalue("(O(ii))", str, valprev, step);
1099 DECREF(str);
1100 return rv;
1101}
1102
Guido van Rossumb64e6351992-07-06 14:21:56 +00001103static object *
1104audioop_lin2adpcm(self, args)
1105 object *self;
1106 object *args;
1107{
1108 signed char *cp;
1109 signed char *ncp;
Jack Jansend513f0b1993-01-08 14:40:53 +00001110 int len, size, val, step, valpred, delta, index, sign, vpdiff, diff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001111 object *rv, *state, *str;
1112 int i, outputbuffer, bufferstep;
1113
1114 if ( !getargs(args, "(s#iO)",
1115 &cp, &len, &size, &state) )
1116 return 0;
1117
1118
1119 if ( size != 1 && size != 2 && size != 4) {
1120 err_setstr(AudioopError, "Size should be 1, 2 or 4");
1121 return 0;
1122 }
1123
Jack Jansendd8a6ea1993-02-17 14:21:09 +00001124 str = newsizedstringobject(NULL, len/(size*2));
1125 if ( str == 0 )
1126 return 0;
1127 ncp = (signed char *)getstringvalue(str);
1128
Guido van Rossumb64e6351992-07-06 14:21:56 +00001129 /* Decode state, should have (value, step) */
1130 if ( state == None ) {
1131 /* First time, it seems. Set defaults */
Jack Jansend513f0b1993-01-08 14:40:53 +00001132 valpred = 0;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001133 step = 7;
1134 index = 0;
Jack Jansen55cea471993-02-10 13:21:59 +00001135 } else if ( !getargs(state, "(ii)", &valpred, &index) )
Guido van Rossumb64e6351992-07-06 14:21:56 +00001136 return 0;
1137
Jack Jansen55cea471993-02-10 13:21:59 +00001138 step = stepsizeTable[index];
Guido van Rossumb64e6351992-07-06 14:21:56 +00001139 bufferstep = 1;
1140
1141 for ( i=0; i < len; i += size ) {
1142 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
1143 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
1144 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
1145
1146 /* Step 1 - compute difference with previous value */
Jack Jansend513f0b1993-01-08 14:40:53 +00001147 diff = val - valpred;
1148 sign = (diff < 0) ? 8 : 0;
1149 if ( sign ) diff = (-diff);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001150
1151 /* Step 2 - Divide and clamp */
Jack Jansend513f0b1993-01-08 14:40:53 +00001152 /* Note:
1153 ** This code *approximately* computes:
1154 ** delta = diff*4/step;
1155 ** vpdiff = (delta+0.5)*step/4;
1156 ** but in shift step bits are dropped. The net result of this is
1157 ** that even if you have fast mul/div hardware you cannot put it to
1158 ** good use since the fixup would be too expensive.
1159 */
1160 delta = 0;
1161 vpdiff = (step >> 3);
1162
1163 if ( diff >= step ) {
1164 delta = 4;
1165 diff -= step;
1166 vpdiff += step;
1167 }
1168 step >>= 1;
1169 if ( diff >= step ) {
1170 delta |= 2;
1171 diff -= step;
1172 vpdiff += step;
1173 }
1174 step >>= 1;
1175 if ( diff >= step ) {
1176 delta |= 1;
1177 vpdiff += step;
1178 }
1179
Guido van Rossumb64e6351992-07-06 14:21:56 +00001180 /* Step 3 - Update previous value */
1181 if ( sign )
Jack Jansend513f0b1993-01-08 14:40:53 +00001182 valpred -= vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001183 else
Jack Jansend513f0b1993-01-08 14:40:53 +00001184 valpred += vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001185
1186 /* Step 4 - Clamp previous value to 16 bits */
Jack Jansend513f0b1993-01-08 14:40:53 +00001187 if ( valpred > 32767 )
1188 valpred = 32767;
1189 else if ( valpred < -32768 )
1190 valpred = -32768;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001191
1192 /* Step 5 - Assemble value, update index and step values */
1193 delta |= sign;
1194
1195 index += indexTable[delta];
1196 if ( index < 0 ) index = 0;
1197 if ( index > 88 ) index = 88;
1198 step = stepsizeTable[index];
1199
Jack Jansend513f0b1993-01-08 14:40:53 +00001200 /* Step 6 - Output value */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001201 if ( bufferstep ) {
Jack Jansend513f0b1993-01-08 14:40:53 +00001202 outputbuffer = (delta << 4) & 0xf0;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001203 } else {
Jack Jansend513f0b1993-01-08 14:40:53 +00001204 *ncp++ = (delta & 0x0f) | outputbuffer;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001205 }
1206 bufferstep = !bufferstep;
1207 }
Jack Jansen55cea471993-02-10 13:21:59 +00001208 rv = mkvalue("(O(ii))", str, valpred, index);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001209 DECREF(str);
1210 return rv;
1211}
1212
1213static object *
1214audioop_adpcm2lin(self, args)
1215 object *self;
1216 object *args;
1217{
1218 signed char *cp;
1219 signed char *ncp;
Jack Jansend513f0b1993-01-08 14:40:53 +00001220 int len, size, val, valpred, step, delta, index, sign, vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001221 object *rv, *str, *state;
1222 int i, inputbuffer, bufferstep;
1223
1224 if ( !getargs(args, "(s#iO)",
1225 &cp, &len, &size, &state) )
1226 return 0;
1227
1228 if ( size != 1 && size != 2 && size != 4) {
1229 err_setstr(AudioopError, "Size should be 1, 2 or 4");
1230 return 0;
1231 }
1232
1233 /* Decode state, should have (value, step) */
1234 if ( state == None ) {
1235 /* First time, it seems. Set defaults */
Jack Jansend513f0b1993-01-08 14:40:53 +00001236 valpred = 0;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001237 step = 7;
1238 index = 0;
Jack Jansen55cea471993-02-10 13:21:59 +00001239 } else if ( !getargs(state, "(ii)", &valpred, &index) )
Guido van Rossumb64e6351992-07-06 14:21:56 +00001240 return 0;
1241
1242 str = newsizedstringobject(NULL, len*size*2);
1243 if ( str == 0 )
1244 return 0;
1245 ncp = (signed char *)getstringvalue(str);
1246
Jack Jansen55cea471993-02-10 13:21:59 +00001247 step = stepsizeTable[index];
Guido van Rossumb64e6351992-07-06 14:21:56 +00001248 bufferstep = 0;
1249
1250 for ( i=0; i < len*size*2; i += size ) {
1251 /* Step 1 - get the delta value and compute next index */
1252 if ( bufferstep ) {
1253 delta = inputbuffer & 0xf;
1254 } else {
1255 inputbuffer = *cp++;
1256 delta = (inputbuffer >> 4) & 0xf;
1257 }
1258
1259 bufferstep = !bufferstep;
1260
Jack Jansend513f0b1993-01-08 14:40:53 +00001261 /* Step 2 - Find new index value (for later) */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001262 index += indexTable[delta];
1263 if ( index < 0 ) index = 0;
1264 if ( index > 88 ) index = 88;
1265
Jack Jansend513f0b1993-01-08 14:40:53 +00001266 /* Step 3 - Separate sign and magnitude */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001267 sign = delta & 8;
1268 delta = delta & 7;
1269
Jack Jansend513f0b1993-01-08 14:40:53 +00001270 /* Step 4 - Compute difference and new predicted value */
1271 /*
1272 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
1273 ** in adpcm_coder.
1274 */
1275 vpdiff = step >> 3;
1276 if ( delta & 4 ) vpdiff += step;
1277 if ( delta & 2 ) vpdiff += step>>1;
1278 if ( delta & 1 ) vpdiff += step>>2;
1279
Guido van Rossumb64e6351992-07-06 14:21:56 +00001280 if ( sign )
Jack Jansend513f0b1993-01-08 14:40:53 +00001281 valpred -= vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001282 else
Jack Jansend513f0b1993-01-08 14:40:53 +00001283 valpred += vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001284
Jack Jansend513f0b1993-01-08 14:40:53 +00001285 /* Step 5 - clamp output value */
1286 if ( valpred > 32767 )
1287 valpred = 32767;
1288 else if ( valpred < -32768 )
1289 valpred = -32768;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001290
Jack Jansend513f0b1993-01-08 14:40:53 +00001291 /* Step 6 - Update step value */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001292 step = stepsizeTable[index];
1293
1294 /* Step 6 - Output value */
Jack Jansend513f0b1993-01-08 14:40:53 +00001295 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valpred >> 8);
1296 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valpred);
1297 else if ( size == 4 ) *LONGP(ncp, i) = (long)(valpred<<16);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001298 }
1299
Jack Jansen55cea471993-02-10 13:21:59 +00001300 rv = mkvalue("(O(ii))", str, valpred, index);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001301 DECREF(str);
1302 return rv;
1303}
1304
Guido van Rossumb66efa01992-06-01 16:01:24 +00001305static struct methodlist audioop_methods[] = {
1306 { "max", audioop_max },
1307 { "avg", audioop_avg },
Jack Jansene1b4d7c1992-08-24 14:36:31 +00001308 { "maxpp", audioop_maxpp },
1309 { "avgpp", audioop_avgpp },
1310 { "rms", audioop_rms },
Jack Jansena90805f1993-02-17 14:29:28 +00001311 { "findfit", audioop_findfit },
1312 { "findmax", audioop_findmax },
1313 { "findfactor", audioop_findfactor },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001314 { "cross", audioop_cross },
1315 { "mul", audioop_mul },
1316 { "add", audioop_add },
1317 { "bias", audioop_bias },
1318 { "ulaw2lin", audioop_ulaw2lin },
1319 { "lin2ulaw", audioop_lin2ulaw },
Jack Jansena90805f1993-02-17 14:29:28 +00001320 { "lin2lin", audioop_lin2lin },
Guido van Rossum8e7a0f01992-06-23 15:23:57 +00001321 { "adpcm2lin", audioop_adpcm2lin },
1322 { "lin2adpcm", audioop_lin2adpcm },
Guido van Rossumb64e6351992-07-06 14:21:56 +00001323 { "adpcm32lin", audioop_adpcm32lin },
1324 { "lin2adpcm3", audioop_lin2adpcm3 },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001325 { "tomono", audioop_tomono },
1326 { "tostereo", audioop_tostereo },
1327 { "getsample", audioop_getsample },
Jack Jansen337b20e1993-02-23 13:39:57 +00001328 { "reverse", audioop_reverse },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001329 { 0, 0 }
1330};
1331
1332
1333void
1334initaudioop()
1335{
1336 object *m, *d;
1337 m = initmodule("audioop", audioop_methods);
1338 d = getmoduledict(m);
1339 AudioopError = newstringobject("audioop.error");
1340 if ( AudioopError == NULL || dictinsert(d,"error",AudioopError) )
1341 fatal("can't define audioop.error");
1342}