blob: 385a2f9fea5314ba1c676aa33105d1dbe2a14ced [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 Jansena90805f1993-02-17 14:29:28 +0000825audioop_lin2lin(self, args)
826 object *self;
827 object *args;
828{
829 signed char *cp;
830 unsigned char *ncp;
831 int len, size, size2, val;
832 object *rv;
833 int i, j;
834
835 if ( !getargs(args, "(s#ii)",
836 &cp, &len, &size, &size2) )
837 return 0;
838
839 if ( (size != 1 && size != 2 && size != 4) ||
840 (size2 != 1 && size2 != 2 && size2 != 4)) {
841 err_setstr(AudioopError, "Size should be 1, 2 or 4");
842 return 0;
843 }
844
845 rv = newsizedstringobject(NULL, (len/size)*size2);
846 if ( rv == 0 )
847 return 0;
848 ncp = (unsigned char *)getstringvalue(rv);
849
850 for ( i=0, j=0; i < len; i += size, j += size2 ) {
851 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
852 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
853 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
854
855 if ( size2 == 1 ) *CHARP(ncp, j) = (signed char)(val >> 8);
856 else if ( size2 == 2 ) *SHORTP(ncp, j) = (short)(val);
857 else if ( size2 == 4 ) *LONGP(ncp, j) = (long)(val<<16);
858 }
859 return rv;
860}
861
862static object *
Guido van Rossumb66efa01992-06-01 16:01:24 +0000863audioop_lin2ulaw(self, args)
864 object *self;
865 object *args;
866{
867 signed char *cp;
868 unsigned char *ncp;
869 int len, size, val;
870 object *rv;
871 int i;
872
873 if ( !getargs(args, "(s#i)",
874 &cp, &len, &size) )
875 return 0;
876
877 if ( size != 1 && size != 2 && size != 4) {
878 err_setstr(AudioopError, "Size should be 1, 2 or 4");
879 return 0;
880 }
881
882 rv = newsizedstringobject(NULL, len/size);
883 if ( rv == 0 )
884 return 0;
885 ncp = (unsigned char *)getstringvalue(rv);
886
887 for ( i=0; i < len; i += size ) {
888 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
889 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
890 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
891
892 *ncp++ = st_linear_to_ulaw(val);
893 }
894 return rv;
895}
896
897static object *
898audioop_ulaw2lin(self, args)
899 object *self;
900 object *args;
901{
902 unsigned char *cp;
903 unsigned char cval;
904 signed char *ncp;
905 int len, size, val;
906 object *rv;
907 int i;
908
909 if ( !getargs(args, "(s#i)",
910 &cp, &len, &size) )
911 return 0;
912
913 if ( size != 1 && size != 2 && size != 4) {
914 err_setstr(AudioopError, "Size should be 1, 2 or 4");
915 return 0;
916 }
917
918 rv = newsizedstringobject(NULL, len*size);
919 if ( rv == 0 )
920 return 0;
921 ncp = (signed char *)getstringvalue(rv);
922
923 for ( i=0; i < len*size; i += size ) {
924 cval = *cp++;
925 val = st_ulaw_to_linear(cval);
926
927 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val >> 8);
928 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val);
Guido van Rossumaad53441992-06-05 15:11:56 +0000929 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val<<16);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000930 }
931 return rv;
932}
933
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000934static object *
Guido van Rossumb64e6351992-07-06 14:21:56 +0000935audioop_lin2adpcm3(self, args)
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000936 object *self;
937 object *args;
938{
939 signed char *cp;
940 signed char *ncp;
941 int len, size, val, step, valprev, delta;
942 object *rv, *state, *str;
943 int i;
944
945 if ( !getargs(args, "(s#iO)",
946 &cp, &len, &size, &state) )
947 return 0;
948
949
950 if ( size != 1 && size != 2 && size != 4) {
951 err_setstr(AudioopError, "Size should be 1, 2 or 4");
952 return 0;
953 }
954
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000955 str = newsizedstringobject(NULL, len/size);
956 if ( str == 0 )
957 return 0;
958 ncp = (signed char *)getstringvalue(str);
959
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000960 /* Decode state, should have (value, step) */
961 if ( state == None ) {
962 /* First time, it seems. Set defaults */
963 valprev = 0;
964 step = 4; /* The '4' is magic. Dunno it's significance */
965 } else if ( !getargs(state, "(ii)", &valprev, &step) )
966 return 0;
967
968 for ( i=0; i < len; i += size ) {
969 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
970 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
971 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
972
973 /* Step 1 - compute difference with previous value */
974 delta = (val - valprev)/step;
975
976 /* Step 2 - Clamp */
977 if ( delta < -4 )
978 delta = -4;
979 else if ( delta > 3 )
980 delta = 3;
981
982 /* Step 3 - Update previous value */
983 valprev += delta*step;
984
985 /* Step 4 - Clamp previous value to 16 bits */
986 if ( valprev > 32767 )
987 valprev = 32767;
988 else if ( valprev < -32768 )
989 valprev = -32768;
990
991 /* Step 5 - Update step value */
992 step = step * newstep[abs(delta)];
993 step++; /* Don't understand this. */
994
995 /* Step 6 - Output value (as a whole byte, currently) */
996 *ncp++ = delta;
997 }
998 rv = mkvalue("(O(ii))", str, valprev, step);
999 DECREF(str);
1000 return rv;
1001}
1002
1003static object *
Guido van Rossumb64e6351992-07-06 14:21:56 +00001004audioop_adpcm32lin(self, args)
Guido van Rossum8e7a0f01992-06-23 15:23:57 +00001005 object *self;
1006 object *args;
1007{
1008 signed char *cp;
1009 signed char *ncp;
1010 int len, size, val, valprev, step, delta;
1011 object *rv, *str, *state;
1012 int i;
1013
1014 if ( !getargs(args, "(s#iO)",
1015 &cp, &len, &size, &state) )
1016 return 0;
1017
1018 if ( size != 1 && size != 2 && size != 4) {
1019 err_setstr(AudioopError, "Size should be 1, 2 or 4");
1020 return 0;
1021 }
1022
1023 /* Decode state, should have (value, step) */
1024 if ( state == None ) {
1025 /* First time, it seems. Set defaults */
1026 valprev = 0;
1027 step = 4; /* The '4' is magic. Dunno it's significance */
1028 } else if ( !getargs(state, "(ii)", &valprev, &step) )
1029 return 0;
1030
1031 str = newsizedstringobject(NULL, len*size);
1032 if ( str == 0 )
1033 return 0;
1034 ncp = (signed char *)getstringvalue(str);
1035
1036 for ( i=0; i < len*size; i += size ) {
1037 /* Step 1 - get the delta value */
1038 delta = *cp++;
1039
1040 /* Step 2 - update output value */
1041 valprev = valprev + delta*step;
1042
1043 /* Step 3 - clamp output value */
1044 if ( valprev > 32767 )
1045 valprev = 32767;
1046 else if ( valprev < -32768 )
1047 valprev = -32768;
1048
1049 /* Step 4 - Update step value */
1050 step = step * newstep[abs(delta)];
1051 step++;
1052
1053 /* Step 5 - Output value */
1054 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valprev >> 8);
1055 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valprev);
1056 else if ( size == 4 ) *LONGP(ncp, i) = (long)(valprev<<16);
1057 }
1058
1059 rv = mkvalue("(O(ii))", str, valprev, step);
1060 DECREF(str);
1061 return rv;
1062}
1063
Guido van Rossumb64e6351992-07-06 14:21:56 +00001064static object *
1065audioop_lin2adpcm(self, args)
1066 object *self;
1067 object *args;
1068{
1069 signed char *cp;
1070 signed char *ncp;
Jack Jansend513f0b1993-01-08 14:40:53 +00001071 int len, size, val, step, valpred, delta, index, sign, vpdiff, diff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001072 object *rv, *state, *str;
1073 int i, outputbuffer, bufferstep;
1074
1075 if ( !getargs(args, "(s#iO)",
1076 &cp, &len, &size, &state) )
1077 return 0;
1078
1079
1080 if ( size != 1 && size != 2 && size != 4) {
1081 err_setstr(AudioopError, "Size should be 1, 2 or 4");
1082 return 0;
1083 }
1084
Jack Jansendd8a6ea1993-02-17 14:21:09 +00001085 str = newsizedstringobject(NULL, len/(size*2));
1086 if ( str == 0 )
1087 return 0;
1088 ncp = (signed char *)getstringvalue(str);
1089
Guido van Rossumb64e6351992-07-06 14:21:56 +00001090 /* Decode state, should have (value, step) */
1091 if ( state == None ) {
1092 /* First time, it seems. Set defaults */
Jack Jansend513f0b1993-01-08 14:40:53 +00001093 valpred = 0;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001094 step = 7;
1095 index = 0;
Jack Jansen55cea471993-02-10 13:21:59 +00001096 } else if ( !getargs(state, "(ii)", &valpred, &index) )
Guido van Rossumb64e6351992-07-06 14:21:56 +00001097 return 0;
1098
Jack Jansen55cea471993-02-10 13:21:59 +00001099 step = stepsizeTable[index];
Guido van Rossumb64e6351992-07-06 14:21:56 +00001100 bufferstep = 1;
1101
1102 for ( i=0; i < len; i += size ) {
1103 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
1104 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
1105 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
1106
1107 /* Step 1 - compute difference with previous value */
Jack Jansend513f0b1993-01-08 14:40:53 +00001108 diff = val - valpred;
1109 sign = (diff < 0) ? 8 : 0;
1110 if ( sign ) diff = (-diff);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001111
1112 /* Step 2 - Divide and clamp */
Jack Jansend513f0b1993-01-08 14:40:53 +00001113 /* Note:
1114 ** This code *approximately* computes:
1115 ** delta = diff*4/step;
1116 ** vpdiff = (delta+0.5)*step/4;
1117 ** but in shift step bits are dropped. The net result of this is
1118 ** that even if you have fast mul/div hardware you cannot put it to
1119 ** good use since the fixup would be too expensive.
1120 */
1121 delta = 0;
1122 vpdiff = (step >> 3);
1123
1124 if ( diff >= step ) {
1125 delta = 4;
1126 diff -= step;
1127 vpdiff += step;
1128 }
1129 step >>= 1;
1130 if ( diff >= step ) {
1131 delta |= 2;
1132 diff -= step;
1133 vpdiff += step;
1134 }
1135 step >>= 1;
1136 if ( diff >= step ) {
1137 delta |= 1;
1138 vpdiff += step;
1139 }
1140
Guido van Rossumb64e6351992-07-06 14:21:56 +00001141 /* Step 3 - Update previous value */
1142 if ( sign )
Jack Jansend513f0b1993-01-08 14:40:53 +00001143 valpred -= vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001144 else
Jack Jansend513f0b1993-01-08 14:40:53 +00001145 valpred += vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001146
1147 /* Step 4 - Clamp previous value to 16 bits */
Jack Jansend513f0b1993-01-08 14:40:53 +00001148 if ( valpred > 32767 )
1149 valpred = 32767;
1150 else if ( valpred < -32768 )
1151 valpred = -32768;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001152
1153 /* Step 5 - Assemble value, update index and step values */
1154 delta |= sign;
1155
1156 index += indexTable[delta];
1157 if ( index < 0 ) index = 0;
1158 if ( index > 88 ) index = 88;
1159 step = stepsizeTable[index];
1160
Jack Jansend513f0b1993-01-08 14:40:53 +00001161 /* Step 6 - Output value */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001162 if ( bufferstep ) {
Jack Jansend513f0b1993-01-08 14:40:53 +00001163 outputbuffer = (delta << 4) & 0xf0;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001164 } else {
Jack Jansend513f0b1993-01-08 14:40:53 +00001165 *ncp++ = (delta & 0x0f) | outputbuffer;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001166 }
1167 bufferstep = !bufferstep;
1168 }
Jack Jansen55cea471993-02-10 13:21:59 +00001169 rv = mkvalue("(O(ii))", str, valpred, index);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001170 DECREF(str);
1171 return rv;
1172}
1173
1174static object *
1175audioop_adpcm2lin(self, args)
1176 object *self;
1177 object *args;
1178{
1179 signed char *cp;
1180 signed char *ncp;
Jack Jansend513f0b1993-01-08 14:40:53 +00001181 int len, size, val, valpred, step, delta, index, sign, vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001182 object *rv, *str, *state;
1183 int i, inputbuffer, bufferstep;
1184
1185 if ( !getargs(args, "(s#iO)",
1186 &cp, &len, &size, &state) )
1187 return 0;
1188
1189 if ( size != 1 && size != 2 && size != 4) {
1190 err_setstr(AudioopError, "Size should be 1, 2 or 4");
1191 return 0;
1192 }
1193
1194 /* Decode state, should have (value, step) */
1195 if ( state == None ) {
1196 /* First time, it seems. Set defaults */
Jack Jansend513f0b1993-01-08 14:40:53 +00001197 valpred = 0;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001198 step = 7;
1199 index = 0;
Jack Jansen55cea471993-02-10 13:21:59 +00001200 } else if ( !getargs(state, "(ii)", &valpred, &index) )
Guido van Rossumb64e6351992-07-06 14:21:56 +00001201 return 0;
1202
1203 str = newsizedstringobject(NULL, len*size*2);
1204 if ( str == 0 )
1205 return 0;
1206 ncp = (signed char *)getstringvalue(str);
1207
Jack Jansen55cea471993-02-10 13:21:59 +00001208 step = stepsizeTable[index];
Guido van Rossumb64e6351992-07-06 14:21:56 +00001209 bufferstep = 0;
1210
1211 for ( i=0; i < len*size*2; i += size ) {
1212 /* Step 1 - get the delta value and compute next index */
1213 if ( bufferstep ) {
1214 delta = inputbuffer & 0xf;
1215 } else {
1216 inputbuffer = *cp++;
1217 delta = (inputbuffer >> 4) & 0xf;
1218 }
1219
1220 bufferstep = !bufferstep;
1221
Jack Jansend513f0b1993-01-08 14:40:53 +00001222 /* Step 2 - Find new index value (for later) */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001223 index += indexTable[delta];
1224 if ( index < 0 ) index = 0;
1225 if ( index > 88 ) index = 88;
1226
Jack Jansend513f0b1993-01-08 14:40:53 +00001227 /* Step 3 - Separate sign and magnitude */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001228 sign = delta & 8;
1229 delta = delta & 7;
1230
Jack Jansend513f0b1993-01-08 14:40:53 +00001231 /* Step 4 - Compute difference and new predicted value */
1232 /*
1233 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
1234 ** in adpcm_coder.
1235 */
1236 vpdiff = step >> 3;
1237 if ( delta & 4 ) vpdiff += step;
1238 if ( delta & 2 ) vpdiff += step>>1;
1239 if ( delta & 1 ) vpdiff += step>>2;
1240
Guido van Rossumb64e6351992-07-06 14:21:56 +00001241 if ( sign )
Jack Jansend513f0b1993-01-08 14:40:53 +00001242 valpred -= vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001243 else
Jack Jansend513f0b1993-01-08 14:40:53 +00001244 valpred += vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001245
Jack Jansend513f0b1993-01-08 14:40:53 +00001246 /* Step 5 - clamp output value */
1247 if ( valpred > 32767 )
1248 valpred = 32767;
1249 else if ( valpred < -32768 )
1250 valpred = -32768;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001251
Jack Jansend513f0b1993-01-08 14:40:53 +00001252 /* Step 6 - Update step value */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001253 step = stepsizeTable[index];
1254
1255 /* Step 6 - Output value */
Jack Jansend513f0b1993-01-08 14:40:53 +00001256 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valpred >> 8);
1257 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valpred);
1258 else if ( size == 4 ) *LONGP(ncp, i) = (long)(valpred<<16);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001259 }
1260
Jack Jansen55cea471993-02-10 13:21:59 +00001261 rv = mkvalue("(O(ii))", str, valpred, index);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001262 DECREF(str);
1263 return rv;
1264}
1265
Guido van Rossumb66efa01992-06-01 16:01:24 +00001266static struct methodlist audioop_methods[] = {
1267 { "max", audioop_max },
1268 { "avg", audioop_avg },
Jack Jansene1b4d7c1992-08-24 14:36:31 +00001269 { "maxpp", audioop_maxpp },
1270 { "avgpp", audioop_avgpp },
1271 { "rms", audioop_rms },
Jack Jansena90805f1993-02-17 14:29:28 +00001272 { "findfit", audioop_findfit },
1273 { "findmax", audioop_findmax },
1274 { "findfactor", audioop_findfactor },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001275 { "cross", audioop_cross },
1276 { "mul", audioop_mul },
1277 { "add", audioop_add },
1278 { "bias", audioop_bias },
1279 { "ulaw2lin", audioop_ulaw2lin },
1280 { "lin2ulaw", audioop_lin2ulaw },
Jack Jansena90805f1993-02-17 14:29:28 +00001281 { "lin2lin", audioop_lin2lin },
Guido van Rossum8e7a0f01992-06-23 15:23:57 +00001282 { "adpcm2lin", audioop_adpcm2lin },
1283 { "lin2adpcm", audioop_lin2adpcm },
Guido van Rossumb64e6351992-07-06 14:21:56 +00001284 { "adpcm32lin", audioop_adpcm32lin },
1285 { "lin2adpcm3", audioop_lin2adpcm3 },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001286 { "tomono", audioop_tomono },
1287 { "tostereo", audioop_tostereo },
1288 { "getsample", audioop_getsample },
1289 { 0, 0 }
1290};
1291
1292
1293void
1294initaudioop()
1295{
1296 object *m, *d;
1297 m = initmodule("audioop", audioop_methods);
1298 d = getmoduledict(m);
1299 AudioopError = newstringobject("audioop.error");
1300 if ( AudioopError == NULL || dictinsert(d,"error",AudioopError) )
1301 fatal("can't define audioop.error");
1302}