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