blob: e3297a3c44018261a858033e840ba6a2d80c3e9b [file] [log] [blame]
Guido van Rossumb66efa01992-06-01 16:01:24 +00001/***********************************************************
Guido van Rossumb6775db1994-08-01 11:34:53 +00002Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Guido van Rossum34679b71993-01-26 13:33:44 +00003Amsterdam, 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
Guido van Rossumb6775db1994-08-01 11:34:53 +000025/* audioopmodule - Module to detect peak values in arrays */
Jack Jansene1b4d7c1992-08-24 14:36:31 +000026
Guido van Rossumb66efa01992-06-01 16:01:24 +000027#include "allobjects.h"
28#include "modsupport.h"
29
Guido van Rossum7b1e9741994-08-29 10:46:42 +000030#if defined(__CHAR_UNSIGNED__)
31#if defined(signed)
Guido van Rossumb6775db1994-08-01 11:34:53 +000032!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
Guido van Rossum7b1e9741994-08-29 10:46:42 +000036#endif
Guido van Rossumb6775db1994-08-01 11:34:53 +000037
38#include <math.h>
39
Jack Jansena90805f1993-02-17 14:29:28 +000040/* Code shamelessly stolen from sox,
Guido van Rossumb66efa01992-06-01 16:01:24 +000041** (c) Craig Reese, Joe Campbell and Jeff Poskanzer 1989 */
42
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 )
46
47unsigned char st_linear_to_ulaw( /* int sample */ );
48
49/*
50** This macro converts from ulaw to 16 bit linear, faster.
51**
52** Jef Poskanzer
53** 23 October 1989
54**
55** Input: 8 bit ulaw sample
56** Output: signed 16 bit linear sample
57*/
58#define st_ulaw_to_linear(ulawbyte) ulaw_table[ulawbyte]
59
60static 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 };
93
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
97
98unsigned char
99st_linear_to_ulaw( sample )
100int sample;
101 {
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;
120
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 */
125
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
134
135 return ulawbyte;
136 }
137/* End of code taken from sox */
138
Guido van Rossumb64e6351992-07-06 14:21:56 +0000139/* ADPCM-3 step variation table */
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000140static float newstep[5] = { 0.8, 0.9, 1.0, 1.75, 1.75 };
141
Guido van Rossumb64e6351992-07-06 14:21:56 +0000142/* Intel ADPCM step variation table */
143static int indexTable[16] = {
144 -1, -1, -1, -1, 2, 4, 6, 8,
145 -1, -1, -1, -1, 2, 4, 6, 8,
146};
147
148static int stepsizeTable[89] = {
149 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
150 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
151 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
152 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
153 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
154 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
155 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
156 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
157 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
158};
159
Guido van Rossumb66efa01992-06-01 16:01:24 +0000160#define CHARP(cp, i) ((signed char *)(cp+i))
161#define SHORTP(cp, i) ((short *)(cp+i))
162#define LONGP(cp, i) ((long *)(cp+i))
163
164
165
166static object *AudioopError;
167
168static object *
169audioop_getsample(self, args)
170 object *self;
171 object *args;
172{
173 signed char *cp;
174 int len, size, val;
175 int i;
176
177 if ( !getargs(args, "(s#ii)", &cp, &len, &size, &i) )
178 return 0;
179 if ( size != 1 && size != 2 && size != 4 ) {
180 err_setstr(AudioopError, "Size should be 1, 2 or 4");
181 return 0;
182 }
183 if ( i < 0 || i >= len/size ) {
184 err_setstr(AudioopError, "Index out of range");
185 return 0;
186 }
187 if ( size == 1 ) val = (int)*CHARP(cp, i);
188 else if ( size == 2 ) val = (int)*SHORTP(cp, i*2);
189 else if ( size == 4 ) val = (int)*LONGP(cp, i*4);
190 return newintobject(val);
191}
192
193static object *
194audioop_max(self, args)
195 object *self;
196 object *args;
197{
198 signed char *cp;
199 int len, size, val;
200 int i;
201 int max = 0;
202
203 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
204 return 0;
205 if ( size != 1 && size != 2 && size != 4 ) {
206 err_setstr(AudioopError, "Size should be 1, 2 or 4");
207 return 0;
208 }
209 for ( i=0; i<len; i+= size) {
210 if ( size == 1 ) val = (int)*CHARP(cp, i);
211 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
212 else if ( size == 4 ) val = (int)*LONGP(cp, i);
213 if ( val < 0 ) val = (-val);
214 if ( val > max ) max = val;
215 }
216 return newintobject(max);
217}
218
219static object *
Sjoerd Mullendera1426131994-09-06 16:19:33 +0000220audioop_minmax(self, args)
221 object *self;
222 object *args;
223{
224 signed char *cp;
225 int len, size, val;
226 int i;
227 int min = 0x7fffffff, max = -0x7fffffff;
228
229 if (!getargs(args, "(s#i)", &cp, &len, &size))
230 return NULL;
231 if (size != 1 && size != 2 && size != 4) {
232 err_setstr(AudioopError, "Size should be 1, 2 or 4");
233 return NULL;
234 }
235 for (i = 0; i < len; i += size) {
236 if (size == 1) val = (int) *CHARP(cp, i);
237 else if (size == 2) val = (int) *SHORTP(cp, i);
238 else if (size == 4) val = (int) *LONGP(cp, i);
239 if (val > max) max = val;
240 if (val < min) min = val;
241 }
242 return mkvalue("(ii)", min, max);
243}
244
245static object *
Guido van Rossumb66efa01992-06-01 16:01:24 +0000246audioop_avg(self, args)
247 object *self;
248 object *args;
249{
250 signed char *cp;
251 int len, size, val;
252 int i;
253 float avg = 0.0;
254
255 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
256 return 0;
257 if ( size != 1 && size != 2 && size != 4 ) {
258 err_setstr(AudioopError, "Size should be 1, 2 or 4");
259 return 0;
260 }
261 for ( i=0; i<len; i+= size) {
262 if ( size == 1 ) val = (int)*CHARP(cp, i);
263 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
264 else if ( size == 4 ) val = (int)*LONGP(cp, i);
265 avg += val;
266 }
267 if ( len == 0 )
268 val = 0;
269 else
270 val = (int)(avg / (float)(len/size));
271 return newintobject(val);
272}
273
274static object *
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000275audioop_rms(self, args)
276 object *self;
277 object *args;
278{
279 signed char *cp;
280 int len, size, val;
281 int i;
282 float sum_squares = 0.0;
283
284 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
285 return 0;
286 if ( size != 1 && size != 2 && size != 4 ) {
287 err_setstr(AudioopError, "Size should be 1, 2 or 4");
288 return 0;
289 }
290 for ( i=0; i<len; i+= size) {
291 if ( size == 1 ) val = (int)*CHARP(cp, i);
292 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
293 else if ( size == 4 ) val = (int)*LONGP(cp, i);
294 sum_squares += (float)val*(float)val;
295 }
296 if ( len == 0 )
297 val = 0;
298 else
299 val = (int)sqrt(sum_squares / (float)(len/size));
300 return newintobject(val);
301}
302
Jack Jansena90805f1993-02-17 14:29:28 +0000303double _sum2(a, b, len)
304 short *a;
305 short *b;
306 int len;
307{
308 int i;
309 double sum = 0.0;
310
311 for( i=0; i<len; i++) {
312 sum = sum + (double)a[i]*(double)b[i];
313 }
314 return sum;
315}
316
317/*
318** Findfit tries to locate a sample within another sample. Its main use
319** is in echo-cancellation (to find the feedback of the output signal in
320** the input signal).
321** The method used is as follows:
322**
323** let R be the reference signal (length n) and A the input signal (length N)
324** with N > n, and let all sums be over i from 0 to n-1.
325**
326** Now, for each j in {0..N-n} we compute a factor fj so that -fj*R matches A
327** as good as possible, i.e. sum( (A[j+i]+fj*R[i])^2 ) is minimal. This
328** equation gives fj = sum( A[j+i]R[i] ) / sum(R[i]^2).
329**
330** Next, we compute the relative distance between the original signal and
331** the modified signal and minimize that over j:
332** vj = sum( (A[j+i]-fj*R[i])^2 ) / sum( A[j+i]^2 ) =>
333** vj = ( sum(A[j+i]^2)*sum(R[i]^2) - sum(A[j+i]R[i])^2 ) / sum( A[j+i]^2 )
334**
335** In the code variables correspond as follows:
336** cp1 A
337** cp2 R
338** len1 N
339** len2 n
340** aj_m1 A[j-1]
341** aj_lm1 A[j+n-1]
342** sum_ri_2 sum(R[i]^2)
343** sum_aij_2 sum(A[i+j]^2)
344** sum_aij_ri sum(A[i+j]R[i])
345**
346** sum_ri is calculated once, sum_aij_2 is updated each step and sum_aij_ri
347** is completely recalculated each step.
348*/
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000349static object *
Jack Jansena90805f1993-02-17 14:29:28 +0000350audioop_findfit(self, args)
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000351 object *self;
352 object *args;
353{
Jack Jansena90805f1993-02-17 14:29:28 +0000354 short *cp1, *cp2;
355 int len1, len2;
356 int j, best_j;
357 double aj_m1, aj_lm1;
358 double sum_ri_2, sum_aij_2, sum_aij_ri, result, best_result, factor;
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000359
Jack Jansena90805f1993-02-17 14:29:28 +0000360 if ( !getargs(args, "(s#s#)", &cp1, &len1, &cp2, &len2) )
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000361 return 0;
Jack Jansena90805f1993-02-17 14:29:28 +0000362 if ( len1 & 1 || len2 & 1 ) {
363 err_setstr(AudioopError, "Strings should be even-sized");
364 return 0;
365 }
366 len1 >>= 1;
367 len2 >>= 1;
368
369 if ( len1 < len2 ) {
370 err_setstr(AudioopError, "First sample should be longer");
371 return 0;
372 }
373 sum_ri_2 = _sum2(cp2, cp2, len2);
374 sum_aij_2 = _sum2(cp1, cp1, len2);
375 sum_aij_ri = _sum2(cp1, cp2, len2);
376
377 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
378
379 best_result = result;
380 best_j = 0;
381 j = 0;
382
383 for ( j=1; j<=len1-len2; j++) {
384 aj_m1 = (double)cp1[j-1];
385 aj_lm1 = (double)cp1[j+len2-1];
386
387 sum_aij_2 = sum_aij_2 + aj_lm1*aj_lm1 - aj_m1*aj_m1;
388 sum_aij_ri = _sum2(cp1+j, cp2, len2);
389
390 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
391
392 if ( result < best_result ) {
393 best_result = result;
394 best_j = j;
395 }
396
397 }
398
399 factor = _sum2(cp1+best_j, cp2, len2) / sum_ri_2;
400
401 return mkvalue("(if)", best_j, factor);
402}
403
404/*
405** findfactor finds a factor f so that the energy in A-fB is minimal.
406** See the comment for findfit for details.
407*/
408static object *
409audioop_findfactor(self, args)
410 object *self;
411 object *args;
412{
413 short *cp1, *cp2;
414 int len1, len2;
415 double sum_ri_2, sum_aij_ri, result;
416
417 if ( !getargs(args, "(s#s#)", &cp1, &len1, &cp2, &len2) )
418 return 0;
419 if ( len1 & 1 || len2 & 1 ) {
420 err_setstr(AudioopError, "Strings should be even-sized");
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000421 return 0;
422 }
423 if ( len1 != len2 ) {
424 err_setstr(AudioopError, "Samples should be same size");
425 return 0;
426 }
Jack Jansena90805f1993-02-17 14:29:28 +0000427 len2 >>= 1;
428 sum_ri_2 = _sum2(cp2, cp2, len2);
429 sum_aij_ri = _sum2(cp1, cp2, len2);
430
431 result = sum_aij_ri / sum_ri_2;
432
433 return newfloatobject(result);
434}
435
436/*
437** findmax returns the index of the n-sized segment of the input sample
438** that contains the most energy.
439*/
440static object *
441audioop_findmax(self, args)
442 object *self;
443 object *args;
444{
445 short *cp1;
446 int len1, len2;
447 int j, best_j;
448 double aj_m1, aj_lm1;
449 double result, best_result;
450
451 if ( !getargs(args, "(s#i)", &cp1, &len1, &len2) )
452 return 0;
453 if ( len1 & 1 ) {
454 err_setstr(AudioopError, "Strings should be even-sized");
455 return 0;
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000456 }
Jack Jansena90805f1993-02-17 14:29:28 +0000457 len1 >>= 1;
458
459 if ( len1 < len2 ) {
460 err_setstr(AudioopError, "Input sample should be longer");
461 return 0;
462 }
463
464 result = _sum2(cp1, cp1, len2);
465
466 best_result = result;
467 best_j = 0;
468 j = 0;
469
470 for ( j=1; j<=len1-len2; j++) {
471 aj_m1 = (double)cp1[j-1];
472 aj_lm1 = (double)cp1[j+len2-1];
473
474 result = result + aj_lm1*aj_lm1 - aj_m1*aj_m1;
475
476 if ( result > best_result ) {
477 best_result = result;
478 best_j = j;
479 }
480
481 }
482
483 return newintobject(best_j);
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000484}
485
486static object *
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000487audioop_avgpp(self, args)
488 object *self;
489 object *args;
490{
491 signed char *cp;
492 int len, size, val, prevval, prevextremevalid = 0, prevextreme;
493 int i;
494 float avg = 0.0;
495 int diff, prevdiff, extremediff, nextreme = 0;
496
497 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
498 return 0;
499 if ( size != 1 && size != 2 && size != 4 ) {
500 err_setstr(AudioopError, "Size should be 1, 2 or 4");
501 return 0;
502 }
503 /* Compute first delta value ahead. Also automatically makes us
504 ** skip the first extreme value
505 */
506 if ( size == 1 ) prevval = (int)*CHARP(cp, 0);
507 else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
508 else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
509 if ( size == 1 ) val = (int)*CHARP(cp, size);
510 else if ( size == 2 ) val = (int)*SHORTP(cp, size);
511 else if ( size == 4 ) val = (int)*LONGP(cp, size);
512 prevdiff = val - prevval;
513
514 for ( i=size; i<len; i+= size) {
515 if ( size == 1 ) val = (int)*CHARP(cp, i);
516 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
517 else if ( size == 4 ) val = (int)*LONGP(cp, i);
518 diff = val - prevval;
519 if ( diff*prevdiff < 0 ) {
520 /* Derivative changed sign. Compute difference to last extreme
521 ** value and remember.
522 */
523 if ( prevextremevalid ) {
524 extremediff = prevval - prevextreme;
525 if ( extremediff < 0 )
526 extremediff = -extremediff;
527 avg += extremediff;
528 nextreme++;
529 }
530 prevextremevalid = 1;
531 prevextreme = prevval;
532 }
533 prevval = val;
534 if ( diff != 0 )
535 prevdiff = diff;
536 }
537 if ( nextreme == 0 )
538 val = 0;
539 else
540 val = (int)(avg / (float)nextreme);
541 return newintobject(val);
542}
543
544static object *
545audioop_maxpp(self, args)
546 object *self;
547 object *args;
548{
549 signed char *cp;
550 int len, size, val, prevval, prevextremevalid = 0, prevextreme;
551 int i;
552 int max = 0;
553 int diff, prevdiff, extremediff;
554
555 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
556 return 0;
557 if ( size != 1 && size != 2 && size != 4 ) {
558 err_setstr(AudioopError, "Size should be 1, 2 or 4");
559 return 0;
560 }
561 /* Compute first delta value ahead. Also automatically makes us
562 ** skip the first extreme value
563 */
564 if ( size == 1 ) prevval = (int)*CHARP(cp, 0);
565 else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
566 else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
567 if ( size == 1 ) val = (int)*CHARP(cp, size);
568 else if ( size == 2 ) val = (int)*SHORTP(cp, size);
569 else if ( size == 4 ) val = (int)*LONGP(cp, size);
570 prevdiff = val - prevval;
571
572 for ( i=size; i<len; i+= size) {
573 if ( size == 1 ) val = (int)*CHARP(cp, i);
574 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
575 else if ( size == 4 ) val = (int)*LONGP(cp, i);
576 diff = val - prevval;
577 if ( diff*prevdiff < 0 ) {
578 /* Derivative changed sign. Compute difference to last extreme
579 ** value and remember.
580 */
581 if ( prevextremevalid ) {
582 extremediff = prevval - prevextreme;
583 if ( extremediff < 0 )
584 extremediff = -extremediff;
585 if ( extremediff > max )
586 max = extremediff;
587 }
588 prevextremevalid = 1;
589 prevextreme = prevval;
590 }
591 prevval = val;
592 if ( diff != 0 )
593 prevdiff = diff;
594 }
595 return newintobject(max);
596}
597
598static object *
Guido van Rossumb66efa01992-06-01 16:01:24 +0000599audioop_cross(self, args)
600 object *self;
601 object *args;
602{
603 signed char *cp;
604 int len, size, val;
605 int i;
606 int cross, prevval, ncross;
607
608 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
609 return 0;
610 if ( size != 1 && size != 2 && size != 4 ) {
611 err_setstr(AudioopError, "Size should be 1, 2 or 4");
612 return 0;
613 }
614 ncross = -1;
615 prevval = 17; /* Anything <> 0,1 */
616 for ( i=0; i<len; i+= size) {
617 if ( size == 1 ) val = ((int)*CHARP(cp, i)) >> 7;
618 else if ( size == 2 ) val = ((int)*SHORTP(cp, i)) >> 15;
619 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 31;
620 val = val & 1;
621 if ( val != prevval ) ncross++;
622 prevval = val;
623 }
624 return newintobject(ncross);
625}
626
627static object *
628audioop_mul(self, args)
629 object *self;
630 object *args;
631{
632 signed char *cp, *ncp;
633 int len, size, val;
634 double factor, fval, maxval;
635 object *rv;
636 int i;
637
638 if ( !getargs(args, "(s#id)", &cp, &len, &size, &factor ) )
639 return 0;
640
641 if ( size == 1 ) maxval = (double) 0x7f;
642 else if ( size == 2 ) maxval = (double) 0x7fff;
643 else if ( size == 4 ) maxval = (double) 0x7fffffff;
644 else {
645 err_setstr(AudioopError, "Size should be 1, 2 or 4");
646 return 0;
647 }
648
649 rv = newsizedstringobject(NULL, len);
650 if ( rv == 0 )
651 return 0;
652 ncp = (signed char *)getstringvalue(rv);
653
654
655 for ( i=0; i < len; i += size ) {
656 if ( size == 1 ) val = (int)*CHARP(cp, i);
657 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
658 else if ( size == 4 ) val = (int)*LONGP(cp, i);
659 fval = (double)val*factor;
660 if ( fval > maxval ) fval = maxval;
661 else if ( fval < -maxval ) fval = -maxval;
662 val = (int)fval;
663 if ( size == 1 ) *CHARP(ncp, i) = (signed char)val;
664 else if ( size == 2 ) *SHORTP(ncp, i) = (short)val;
665 else if ( size == 4 ) *LONGP(ncp, i) = (long)val;
666 }
667 return rv;
668}
669
670static object *
671audioop_tomono(self, args)
672 object *self;
673 object *args;
674{
675 signed char *cp, *ncp;
676 int len, size, val1, val2;
677 double fac1, fac2, fval, maxval;
678 object *rv;
679 int i;
680
681 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
682 return 0;
683
684 if ( size == 1 ) maxval = (double) 0x7f;
685 else if ( size == 2 ) maxval = (double) 0x7fff;
686 else if ( size == 4 ) maxval = (double) 0x7fffffff;
687 else {
688 err_setstr(AudioopError, "Size should be 1, 2 or 4");
689 return 0;
690 }
691
692 rv = newsizedstringobject(NULL, len/2);
693 if ( rv == 0 )
694 return 0;
695 ncp = (signed char *)getstringvalue(rv);
696
697
698 for ( i=0; i < len; i += size*2 ) {
699 if ( size == 1 ) val1 = (int)*CHARP(cp, i);
700 else if ( size == 2 ) val1 = (int)*SHORTP(cp, i);
701 else if ( size == 4 ) val1 = (int)*LONGP(cp, i);
702 if ( size == 1 ) val2 = (int)*CHARP(cp, i+1);
703 else if ( size == 2 ) val2 = (int)*SHORTP(cp, i+2);
704 else if ( size == 4 ) val2 = (int)*LONGP(cp, i+4);
705 fval = (double)val1*fac1 + (double)val2*fac2;
706 if ( fval > maxval ) fval = maxval;
707 else if ( fval < -maxval ) fval = -maxval;
708 val1 = (int)fval;
709 if ( size == 1 ) *CHARP(ncp, i/2) = (signed char)val1;
710 else if ( size == 2 ) *SHORTP(ncp, i/2) = (short)val1;
711 else if ( size == 4 ) *LONGP(ncp, i/2)= (long)val1;
712 }
713 return rv;
714}
715
716static object *
717audioop_tostereo(self, args)
718 object *self;
719 object *args;
720{
721 signed char *cp, *ncp;
722 int len, size, val1, val2, val;
723 double fac1, fac2, fval, maxval;
724 object *rv;
725 int i;
726
727 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
728 return 0;
729
730 if ( size == 1 ) maxval = (double) 0x7f;
731 else if ( size == 2 ) maxval = (double) 0x7fff;
732 else if ( size == 4 ) maxval = (double) 0x7fffffff;
733 else {
734 err_setstr(AudioopError, "Size should be 1, 2 or 4");
735 return 0;
736 }
737
738 rv = newsizedstringobject(NULL, len*2);
739 if ( rv == 0 )
740 return 0;
741 ncp = (signed char *)getstringvalue(rv);
742
743
744 for ( i=0; i < len; i += size ) {
745 if ( size == 1 ) val = (int)*CHARP(cp, i);
746 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
747 else if ( size == 4 ) val = (int)*LONGP(cp, i);
748
749 fval = (double)val*fac1;
750 if ( fval > maxval ) fval = maxval;
751 else if ( fval < -maxval ) fval = -maxval;
752 val1 = (int)fval;
753
754 fval = (double)val*fac2;
755 if ( fval > maxval ) fval = maxval;
756 else if ( fval < -maxval ) fval = -maxval;
757 val2 = (int)fval;
758
759 if ( size == 1 ) *CHARP(ncp, i*2) = (signed char)val1;
760 else if ( size == 2 ) *SHORTP(ncp, i*2) = (short)val1;
761 else if ( size == 4 ) *LONGP(ncp, i*2) = (long)val1;
762
763 if ( size == 1 ) *CHARP(ncp, i*2+1) = (signed char)val2;
764 else if ( size == 2 ) *SHORTP(ncp, i*2+2) = (short)val2;
765 else if ( size == 4 ) *LONGP(ncp, i*2+4) = (long)val2;
766 }
767 return rv;
768}
769
770static object *
771audioop_add(self, args)
772 object *self;
773 object *args;
774{
775 signed char *cp1, *cp2, *ncp;
776 int len1, len2, size, val1, val2;
777 object *rv;
778 int i;
779
780 if ( !getargs(args, "(s#s#i)",
781 &cp1, &len1, &cp2, &len2, &size ) )
782 return 0;
783
784 if ( len1 != len2 ) {
785 err_setstr(AudioopError, "Lengths should be the same");
786 return 0;
787 }
788
789 if ( size != 1 && size != 2 && size != 4) {
790 err_setstr(AudioopError, "Size should be 1, 2 or 4");
791 return 0;
792 }
793
794 rv = newsizedstringobject(NULL, len1);
795 if ( rv == 0 )
796 return 0;
797 ncp = (signed char *)getstringvalue(rv);
798
799
800 for ( i=0; i < len1; i += size ) {
801 if ( size == 1 ) val1 = (int)*CHARP(cp1, i);
802 else if ( size == 2 ) val1 = (int)*SHORTP(cp1, i);
803 else if ( size == 4 ) val1 = (int)*LONGP(cp1, i);
804
805 if ( size == 1 ) val2 = (int)*CHARP(cp2, i);
806 else if ( size == 2 ) val2 = (int)*SHORTP(cp2, i);
807 else if ( size == 4 ) val2 = (int)*LONGP(cp2, i);
808
809 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val1+val2);
810 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val1+val2);
811 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val1+val2);
812 }
813 return rv;
814}
815
816static object *
817audioop_bias(self, args)
818 object *self;
819 object *args;
820{
821 signed char *cp, *ncp;
822 int len, size, val;
823 object *rv;
824 int i;
825 int bias;
826
827 if ( !getargs(args, "(s#ii)",
828 &cp, &len, &size , &bias) )
829 return 0;
830
831 if ( size != 1 && size != 2 && size != 4) {
832 err_setstr(AudioopError, "Size should be 1, 2 or 4");
833 return 0;
834 }
835
836 rv = newsizedstringobject(NULL, len);
837 if ( rv == 0 )
838 return 0;
839 ncp = (signed char *)getstringvalue(rv);
840
841
842 for ( i=0; i < len; i += size ) {
843 if ( size == 1 ) val = (int)*CHARP(cp, i);
844 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
845 else if ( size == 4 ) val = (int)*LONGP(cp, i);
846
847 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val+bias);
848 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val+bias);
849 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val+bias);
850 }
851 return rv;
852}
853
854static object *
Jack Jansen337b20e1993-02-23 13:39:57 +0000855audioop_reverse(self, args)
856 object *self;
857 object *args;
858{
859 signed char *cp;
860 unsigned char *ncp;
861 int len, size, val;
862 object *rv;
863 int i, j;
864
865 if ( !getargs(args, "(s#i)",
866 &cp, &len, &size) )
867 return 0;
868
869 if ( size != 1 && size != 2 && size != 4 ) {
870 err_setstr(AudioopError, "Size should be 1, 2 or 4");
871 return 0;
872 }
873
874 rv = newsizedstringobject(NULL, len);
875 if ( rv == 0 )
876 return 0;
877 ncp = (unsigned char *)getstringvalue(rv);
878
879 for ( i=0; i < len; i += size ) {
880 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
881 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
882 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
883
884 j = len - i - size;
885
886 if ( size == 1 ) *CHARP(ncp, j) = (signed char)(val >> 8);
887 else if ( size == 2 ) *SHORTP(ncp, j) = (short)(val);
888 else if ( size == 4 ) *LONGP(ncp, j) = (long)(val<<16);
889 }
890 return rv;
891}
892
893static object *
Jack Jansena90805f1993-02-17 14:29:28 +0000894audioop_lin2lin(self, args)
895 object *self;
896 object *args;
897{
898 signed char *cp;
899 unsigned char *ncp;
900 int len, size, size2, val;
901 object *rv;
902 int i, j;
903
904 if ( !getargs(args, "(s#ii)",
905 &cp, &len, &size, &size2) )
906 return 0;
907
908 if ( (size != 1 && size != 2 && size != 4) ||
909 (size2 != 1 && size2 != 2 && size2 != 4)) {
910 err_setstr(AudioopError, "Size should be 1, 2 or 4");
911 return 0;
912 }
913
914 rv = newsizedstringobject(NULL, (len/size)*size2);
915 if ( rv == 0 )
916 return 0;
917 ncp = (unsigned char *)getstringvalue(rv);
918
919 for ( i=0, j=0; i < len; i += size, j += size2 ) {
920 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
921 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
922 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
923
924 if ( size2 == 1 ) *CHARP(ncp, j) = (signed char)(val >> 8);
925 else if ( size2 == 2 ) *SHORTP(ncp, j) = (short)(val);
926 else if ( size2 == 4 ) *LONGP(ncp, j) = (long)(val<<16);
927 }
928 return rv;
929}
930
931static object *
Guido van Rossumb66efa01992-06-01 16:01:24 +0000932audioop_lin2ulaw(self, args)
933 object *self;
934 object *args;
935{
936 signed char *cp;
937 unsigned char *ncp;
938 int len, size, val;
939 object *rv;
940 int i;
941
942 if ( !getargs(args, "(s#i)",
943 &cp, &len, &size) )
944 return 0;
945
946 if ( size != 1 && size != 2 && size != 4) {
947 err_setstr(AudioopError, "Size should be 1, 2 or 4");
948 return 0;
949 }
950
951 rv = newsizedstringobject(NULL, len/size);
952 if ( rv == 0 )
953 return 0;
954 ncp = (unsigned char *)getstringvalue(rv);
955
956 for ( i=0; i < len; i += size ) {
957 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
958 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
959 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
960
961 *ncp++ = st_linear_to_ulaw(val);
962 }
963 return rv;
964}
965
966static object *
967audioop_ulaw2lin(self, args)
968 object *self;
969 object *args;
970{
971 unsigned char *cp;
972 unsigned char cval;
973 signed char *ncp;
974 int len, size, val;
975 object *rv;
976 int i;
977
978 if ( !getargs(args, "(s#i)",
979 &cp, &len, &size) )
980 return 0;
981
982 if ( size != 1 && size != 2 && size != 4) {
983 err_setstr(AudioopError, "Size should be 1, 2 or 4");
984 return 0;
985 }
986
987 rv = newsizedstringobject(NULL, len*size);
988 if ( rv == 0 )
989 return 0;
990 ncp = (signed char *)getstringvalue(rv);
991
992 for ( i=0; i < len*size; i += size ) {
993 cval = *cp++;
994 val = st_ulaw_to_linear(cval);
995
996 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val >> 8);
997 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val);
Guido van Rossumaad53441992-06-05 15:11:56 +0000998 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val<<16);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000999 }
1000 return rv;
1001}
1002
Guido van Rossum8e7a0f01992-06-23 15:23:57 +00001003static object *
Guido van Rossumb64e6351992-07-06 14:21:56 +00001004audioop_lin2adpcm(self, args)
1005 object *self;
1006 object *args;
1007{
1008 signed char *cp;
1009 signed char *ncp;
Jack Jansend513f0b1993-01-08 14:40:53 +00001010 int len, size, val, step, valpred, delta, index, sign, vpdiff, diff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001011 object *rv, *state, *str;
1012 int i, outputbuffer, bufferstep;
1013
1014 if ( !getargs(args, "(s#iO)",
1015 &cp, &len, &size, &state) )
1016 return 0;
1017
1018
1019 if ( size != 1 && size != 2 && size != 4) {
1020 err_setstr(AudioopError, "Size should be 1, 2 or 4");
1021 return 0;
1022 }
1023
Jack Jansendd8a6ea1993-02-17 14:21:09 +00001024 str = newsizedstringobject(NULL, len/(size*2));
1025 if ( str == 0 )
1026 return 0;
1027 ncp = (signed char *)getstringvalue(str);
1028
Guido van Rossumb64e6351992-07-06 14:21:56 +00001029 /* Decode state, should have (value, step) */
1030 if ( state == None ) {
1031 /* First time, it seems. Set defaults */
Jack Jansend513f0b1993-01-08 14:40:53 +00001032 valpred = 0;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001033 step = 7;
1034 index = 0;
Jack Jansen55cea471993-02-10 13:21:59 +00001035 } else if ( !getargs(state, "(ii)", &valpred, &index) )
Guido van Rossumb64e6351992-07-06 14:21:56 +00001036 return 0;
1037
Jack Jansen55cea471993-02-10 13:21:59 +00001038 step = stepsizeTable[index];
Guido van Rossumb64e6351992-07-06 14:21:56 +00001039 bufferstep = 1;
1040
1041 for ( i=0; i < len; i += size ) {
1042 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
1043 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
1044 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
1045
1046 /* Step 1 - compute difference with previous value */
Jack Jansend513f0b1993-01-08 14:40:53 +00001047 diff = val - valpred;
1048 sign = (diff < 0) ? 8 : 0;
1049 if ( sign ) diff = (-diff);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001050
1051 /* Step 2 - Divide and clamp */
Jack Jansend513f0b1993-01-08 14:40:53 +00001052 /* Note:
1053 ** This code *approximately* computes:
1054 ** delta = diff*4/step;
1055 ** vpdiff = (delta+0.5)*step/4;
1056 ** but in shift step bits are dropped. The net result of this is
1057 ** that even if you have fast mul/div hardware you cannot put it to
1058 ** good use since the fixup would be too expensive.
1059 */
1060 delta = 0;
1061 vpdiff = (step >> 3);
1062
1063 if ( diff >= step ) {
1064 delta = 4;
1065 diff -= step;
1066 vpdiff += step;
1067 }
1068 step >>= 1;
1069 if ( diff >= step ) {
1070 delta |= 2;
1071 diff -= step;
1072 vpdiff += step;
1073 }
1074 step >>= 1;
1075 if ( diff >= step ) {
1076 delta |= 1;
1077 vpdiff += step;
1078 }
1079
Guido van Rossumb64e6351992-07-06 14:21:56 +00001080 /* Step 3 - Update previous value */
1081 if ( sign )
Jack Jansend513f0b1993-01-08 14:40:53 +00001082 valpred -= vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001083 else
Jack Jansend513f0b1993-01-08 14:40:53 +00001084 valpred += vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001085
1086 /* Step 4 - Clamp previous value to 16 bits */
Jack Jansend513f0b1993-01-08 14:40:53 +00001087 if ( valpred > 32767 )
1088 valpred = 32767;
1089 else if ( valpred < -32768 )
1090 valpred = -32768;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001091
1092 /* Step 5 - Assemble value, update index and step values */
1093 delta |= sign;
1094
1095 index += indexTable[delta];
1096 if ( index < 0 ) index = 0;
1097 if ( index > 88 ) index = 88;
1098 step = stepsizeTable[index];
1099
Jack Jansend513f0b1993-01-08 14:40:53 +00001100 /* Step 6 - Output value */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001101 if ( bufferstep ) {
Jack Jansend513f0b1993-01-08 14:40:53 +00001102 outputbuffer = (delta << 4) & 0xf0;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001103 } else {
Jack Jansend513f0b1993-01-08 14:40:53 +00001104 *ncp++ = (delta & 0x0f) | outputbuffer;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001105 }
1106 bufferstep = !bufferstep;
1107 }
Jack Jansen55cea471993-02-10 13:21:59 +00001108 rv = mkvalue("(O(ii))", str, valpred, index);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001109 DECREF(str);
1110 return rv;
1111}
1112
1113static object *
1114audioop_adpcm2lin(self, args)
1115 object *self;
1116 object *args;
1117{
1118 signed char *cp;
1119 signed char *ncp;
Jack Jansend513f0b1993-01-08 14:40:53 +00001120 int len, size, val, valpred, step, delta, index, sign, vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001121 object *rv, *str, *state;
1122 int i, inputbuffer, bufferstep;
1123
1124 if ( !getargs(args, "(s#iO)",
1125 &cp, &len, &size, &state) )
1126 return 0;
1127
1128 if ( size != 1 && size != 2 && size != 4) {
1129 err_setstr(AudioopError, "Size should be 1, 2 or 4");
1130 return 0;
1131 }
1132
1133 /* Decode state, should have (value, step) */
1134 if ( state == None ) {
1135 /* First time, it seems. Set defaults */
Jack Jansend513f0b1993-01-08 14:40:53 +00001136 valpred = 0;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001137 step = 7;
1138 index = 0;
Jack Jansen55cea471993-02-10 13:21:59 +00001139 } else if ( !getargs(state, "(ii)", &valpred, &index) )
Guido van Rossumb64e6351992-07-06 14:21:56 +00001140 return 0;
1141
1142 str = newsizedstringobject(NULL, len*size*2);
1143 if ( str == 0 )
1144 return 0;
1145 ncp = (signed char *)getstringvalue(str);
1146
Jack Jansen55cea471993-02-10 13:21:59 +00001147 step = stepsizeTable[index];
Guido van Rossumb64e6351992-07-06 14:21:56 +00001148 bufferstep = 0;
1149
1150 for ( i=0; i < len*size*2; i += size ) {
1151 /* Step 1 - get the delta value and compute next index */
1152 if ( bufferstep ) {
1153 delta = inputbuffer & 0xf;
1154 } else {
1155 inputbuffer = *cp++;
1156 delta = (inputbuffer >> 4) & 0xf;
1157 }
1158
1159 bufferstep = !bufferstep;
1160
Jack Jansend513f0b1993-01-08 14:40:53 +00001161 /* Step 2 - Find new index value (for later) */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001162 index += indexTable[delta];
1163 if ( index < 0 ) index = 0;
1164 if ( index > 88 ) index = 88;
1165
Jack Jansend513f0b1993-01-08 14:40:53 +00001166 /* Step 3 - Separate sign and magnitude */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001167 sign = delta & 8;
1168 delta = delta & 7;
1169
Jack Jansend513f0b1993-01-08 14:40:53 +00001170 /* Step 4 - Compute difference and new predicted value */
1171 /*
1172 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
1173 ** in adpcm_coder.
1174 */
1175 vpdiff = step >> 3;
1176 if ( delta & 4 ) vpdiff += step;
1177 if ( delta & 2 ) vpdiff += step>>1;
1178 if ( delta & 1 ) vpdiff += step>>2;
1179
Guido van Rossumb64e6351992-07-06 14:21:56 +00001180 if ( sign )
Jack Jansend513f0b1993-01-08 14:40:53 +00001181 valpred -= vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001182 else
Jack Jansend513f0b1993-01-08 14:40:53 +00001183 valpred += vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001184
Jack Jansend513f0b1993-01-08 14:40:53 +00001185 /* Step 5 - clamp output value */
1186 if ( valpred > 32767 )
1187 valpred = 32767;
1188 else if ( valpred < -32768 )
1189 valpred = -32768;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001190
Jack Jansend513f0b1993-01-08 14:40:53 +00001191 /* Step 6 - Update step value */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001192 step = stepsizeTable[index];
1193
1194 /* Step 6 - Output value */
Jack Jansend513f0b1993-01-08 14:40:53 +00001195 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valpred >> 8);
1196 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valpred);
1197 else if ( size == 4 ) *LONGP(ncp, i) = (long)(valpred<<16);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001198 }
1199
Jack Jansen55cea471993-02-10 13:21:59 +00001200 rv = mkvalue("(O(ii))", str, valpred, index);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001201 DECREF(str);
1202 return rv;
1203}
1204
Guido van Rossumb66efa01992-06-01 16:01:24 +00001205static struct methodlist audioop_methods[] = {
1206 { "max", audioop_max },
Sjoerd Mullendera1426131994-09-06 16:19:33 +00001207 { "minmax", audioop_minmax },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001208 { "avg", audioop_avg },
Jack Jansene1b4d7c1992-08-24 14:36:31 +00001209 { "maxpp", audioop_maxpp },
1210 { "avgpp", audioop_avgpp },
1211 { "rms", audioop_rms },
Jack Jansena90805f1993-02-17 14:29:28 +00001212 { "findfit", audioop_findfit },
1213 { "findmax", audioop_findmax },
1214 { "findfactor", audioop_findfactor },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001215 { "cross", audioop_cross },
1216 { "mul", audioop_mul },
1217 { "add", audioop_add },
1218 { "bias", audioop_bias },
1219 { "ulaw2lin", audioop_ulaw2lin },
1220 { "lin2ulaw", audioop_lin2ulaw },
Jack Jansena90805f1993-02-17 14:29:28 +00001221 { "lin2lin", audioop_lin2lin },
Guido van Rossum8e7a0f01992-06-23 15:23:57 +00001222 { "adpcm2lin", audioop_adpcm2lin },
1223 { "lin2adpcm", audioop_lin2adpcm },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001224 { "tomono", audioop_tomono },
1225 { "tostereo", audioop_tostereo },
1226 { "getsample", audioop_getsample },
Jack Jansen337b20e1993-02-23 13:39:57 +00001227 { "reverse", audioop_reverse },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001228 { 0, 0 }
1229};
1230
1231
1232void
1233initaudioop()
1234{
1235 object *m, *d;
1236 m = initmodule("audioop", audioop_methods);
1237 d = getmoduledict(m);
1238 AudioopError = newstringobject("audioop.error");
1239 if ( AudioopError == NULL || dictinsert(d,"error",AudioopError) )
1240 fatal("can't define audioop.error");
1241}