blob: 8bd833ad48f2adb4026d2ab38057f24ab8c37d5b [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 *
Sjoerd Mullenderc4801ed1993-12-13 12:06:27 +0000216audioop_minmax(self, args)
217 object *self;
218 object *args;
219{
220 signed char *cp;
221 int len, size, val;
222 int i;
223 int min = 0x7fffffff, max = -0x7fffffff;
224
225 if (!getargs(args, "(s#i)", &cp, &len, &size))
226 return NULL;
227 if (size != 1 && size != 2 && size != 4) {
228 err_setstr(AudioopError, "Size should be 1, 2 or 4");
229 return NULL;
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 if (val > max) max = val;
236 if (val < min) min = val;
237 }
238 return mkvalue("(ii)", min, max);
239}
240
241static object *
Guido van Rossumb66efa01992-06-01 16:01:24 +0000242audioop_avg(self, args)
243 object *self;
244 object *args;
245{
246 signed char *cp;
247 int len, size, val;
248 int i;
249 float avg = 0.0;
250
251 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
252 return 0;
253 if ( size != 1 && size != 2 && size != 4 ) {
254 err_setstr(AudioopError, "Size should be 1, 2 or 4");
255 return 0;
256 }
257 for ( i=0; i<len; i+= size) {
258 if ( size == 1 ) val = (int)*CHARP(cp, i);
259 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
260 else if ( size == 4 ) val = (int)*LONGP(cp, i);
261 avg += val;
262 }
263 if ( len == 0 )
264 val = 0;
265 else
266 val = (int)(avg / (float)(len/size));
267 return newintobject(val);
268}
269
270static object *
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000271audioop_rms(self, args)
272 object *self;
273 object *args;
274{
275 signed char *cp;
276 int len, size, val;
277 int i;
278 float sum_squares = 0.0;
279
280 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
281 return 0;
282 if ( size != 1 && size != 2 && size != 4 ) {
283 err_setstr(AudioopError, "Size should be 1, 2 or 4");
284 return 0;
285 }
286 for ( i=0; i<len; i+= size) {
287 if ( size == 1 ) val = (int)*CHARP(cp, i);
288 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
289 else if ( size == 4 ) val = (int)*LONGP(cp, i);
290 sum_squares += (float)val*(float)val;
291 }
292 if ( len == 0 )
293 val = 0;
294 else
295 val = (int)sqrt(sum_squares / (float)(len/size));
296 return newintobject(val);
297}
298
Jack Jansena90805f1993-02-17 14:29:28 +0000299double _sum2(a, b, len)
300 short *a;
301 short *b;
302 int len;
303{
304 int i;
305 double sum = 0.0;
306
307 for( i=0; i<len; i++) {
308 sum = sum + (double)a[i]*(double)b[i];
309 }
310 return sum;
311}
312
313/*
314** Findfit tries to locate a sample within another sample. Its main use
315** is in echo-cancellation (to find the feedback of the output signal in
316** the input signal).
317** The method used is as follows:
318**
319** let R be the reference signal (length n) and A the input signal (length N)
320** with N > n, and let all sums be over i from 0 to n-1.
321**
322** Now, for each j in {0..N-n} we compute a factor fj so that -fj*R matches A
323** as good as possible, i.e. sum( (A[j+i]+fj*R[i])^2 ) is minimal. This
324** equation gives fj = sum( A[j+i]R[i] ) / sum(R[i]^2).
325**
326** Next, we compute the relative distance between the original signal and
327** the modified signal and minimize that over j:
328** vj = sum( (A[j+i]-fj*R[i])^2 ) / sum( A[j+i]^2 ) =>
329** vj = ( sum(A[j+i]^2)*sum(R[i]^2) - sum(A[j+i]R[i])^2 ) / sum( A[j+i]^2 )
330**
331** In the code variables correspond as follows:
332** cp1 A
333** cp2 R
334** len1 N
335** len2 n
336** aj_m1 A[j-1]
337** aj_lm1 A[j+n-1]
338** sum_ri_2 sum(R[i]^2)
339** sum_aij_2 sum(A[i+j]^2)
340** sum_aij_ri sum(A[i+j]R[i])
341**
342** sum_ri is calculated once, sum_aij_2 is updated each step and sum_aij_ri
343** is completely recalculated each step.
344*/
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000345static object *
Jack Jansena90805f1993-02-17 14:29:28 +0000346audioop_findfit(self, args)
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000347 object *self;
348 object *args;
349{
Jack Jansena90805f1993-02-17 14:29:28 +0000350 short *cp1, *cp2;
351 int len1, len2;
352 int j, best_j;
353 double aj_m1, aj_lm1;
354 double sum_ri_2, sum_aij_2, sum_aij_ri, result, best_result, factor;
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000355
Jack Jansena90805f1993-02-17 14:29:28 +0000356 if ( !getargs(args, "(s#s#)", &cp1, &len1, &cp2, &len2) )
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000357 return 0;
Jack Jansena90805f1993-02-17 14:29:28 +0000358 if ( len1 & 1 || len2 & 1 ) {
359 err_setstr(AudioopError, "Strings should be even-sized");
360 return 0;
361 }
362 len1 >>= 1;
363 len2 >>= 1;
364
365 if ( len1 < len2 ) {
366 err_setstr(AudioopError, "First sample should be longer");
367 return 0;
368 }
369 sum_ri_2 = _sum2(cp2, cp2, len2);
370 sum_aij_2 = _sum2(cp1, cp1, len2);
371 sum_aij_ri = _sum2(cp1, cp2, len2);
372
373 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
374
375 best_result = result;
376 best_j = 0;
377 j = 0;
378
379 for ( j=1; j<=len1-len2; j++) {
380 aj_m1 = (double)cp1[j-1];
381 aj_lm1 = (double)cp1[j+len2-1];
382
383 sum_aij_2 = sum_aij_2 + aj_lm1*aj_lm1 - aj_m1*aj_m1;
384 sum_aij_ri = _sum2(cp1+j, cp2, len2);
385
386 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
387
388 if ( result < best_result ) {
389 best_result = result;
390 best_j = j;
391 }
392
393 }
394
395 factor = _sum2(cp1+best_j, cp2, len2) / sum_ri_2;
396
397 return mkvalue("(if)", best_j, factor);
398}
399
400/*
401** findfactor finds a factor f so that the energy in A-fB is minimal.
402** See the comment for findfit for details.
403*/
404static object *
405audioop_findfactor(self, args)
406 object *self;
407 object *args;
408{
409 short *cp1, *cp2;
410 int len1, len2;
411 double sum_ri_2, sum_aij_ri, result;
412
413 if ( !getargs(args, "(s#s#)", &cp1, &len1, &cp2, &len2) )
414 return 0;
415 if ( len1 & 1 || len2 & 1 ) {
416 err_setstr(AudioopError, "Strings should be even-sized");
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000417 return 0;
418 }
419 if ( len1 != len2 ) {
420 err_setstr(AudioopError, "Samples should be same size");
421 return 0;
422 }
Jack Jansena90805f1993-02-17 14:29:28 +0000423 len2 >>= 1;
424 sum_ri_2 = _sum2(cp2, cp2, len2);
425 sum_aij_ri = _sum2(cp1, cp2, len2);
426
427 result = sum_aij_ri / sum_ri_2;
428
429 return newfloatobject(result);
430}
431
432/*
433** findmax returns the index of the n-sized segment of the input sample
434** that contains the most energy.
435*/
436static object *
437audioop_findmax(self, args)
438 object *self;
439 object *args;
440{
441 short *cp1;
442 int len1, len2;
443 int j, best_j;
444 double aj_m1, aj_lm1;
445 double result, best_result;
446
447 if ( !getargs(args, "(s#i)", &cp1, &len1, &len2) )
448 return 0;
449 if ( len1 & 1 ) {
450 err_setstr(AudioopError, "Strings should be even-sized");
451 return 0;
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000452 }
Jack Jansena90805f1993-02-17 14:29:28 +0000453 len1 >>= 1;
454
455 if ( len1 < len2 ) {
456 err_setstr(AudioopError, "Input sample should be longer");
457 return 0;
458 }
459
460 result = _sum2(cp1, cp1, len2);
461
462 best_result = result;
463 best_j = 0;
464 j = 0;
465
466 for ( j=1; j<=len1-len2; j++) {
467 aj_m1 = (double)cp1[j-1];
468 aj_lm1 = (double)cp1[j+len2-1];
469
470 result = result + aj_lm1*aj_lm1 - aj_m1*aj_m1;
471
472 if ( result > best_result ) {
473 best_result = result;
474 best_j = j;
475 }
476
477 }
478
479 return newintobject(best_j);
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000480}
481
482static object *
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000483audioop_avgpp(self, args)
484 object *self;
485 object *args;
486{
487 signed char *cp;
488 int len, size, val, prevval, prevextremevalid = 0, prevextreme;
489 int i;
490 float avg = 0.0;
491 int diff, prevdiff, extremediff, nextreme = 0;
492
493 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
494 return 0;
495 if ( size != 1 && size != 2 && size != 4 ) {
496 err_setstr(AudioopError, "Size should be 1, 2 or 4");
497 return 0;
498 }
499 /* Compute first delta value ahead. Also automatically makes us
500 ** skip the first extreme value
501 */
502 if ( size == 1 ) prevval = (int)*CHARP(cp, 0);
503 else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
504 else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
505 if ( size == 1 ) val = (int)*CHARP(cp, size);
506 else if ( size == 2 ) val = (int)*SHORTP(cp, size);
507 else if ( size == 4 ) val = (int)*LONGP(cp, size);
508 prevdiff = val - prevval;
509
510 for ( i=size; i<len; i+= size) {
511 if ( size == 1 ) val = (int)*CHARP(cp, i);
512 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
513 else if ( size == 4 ) val = (int)*LONGP(cp, i);
514 diff = val - prevval;
515 if ( diff*prevdiff < 0 ) {
516 /* Derivative changed sign. Compute difference to last extreme
517 ** value and remember.
518 */
519 if ( prevextremevalid ) {
520 extremediff = prevval - prevextreme;
521 if ( extremediff < 0 )
522 extremediff = -extremediff;
523 avg += extremediff;
524 nextreme++;
525 }
526 prevextremevalid = 1;
527 prevextreme = prevval;
528 }
529 prevval = val;
530 if ( diff != 0 )
531 prevdiff = diff;
532 }
533 if ( nextreme == 0 )
534 val = 0;
535 else
536 val = (int)(avg / (float)nextreme);
537 return newintobject(val);
538}
539
540static object *
541audioop_maxpp(self, args)
542 object *self;
543 object *args;
544{
545 signed char *cp;
546 int len, size, val, prevval, prevextremevalid = 0, prevextreme;
547 int i;
548 int max = 0;
549 int diff, prevdiff, extremediff;
550
551 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
552 return 0;
553 if ( size != 1 && size != 2 && size != 4 ) {
554 err_setstr(AudioopError, "Size should be 1, 2 or 4");
555 return 0;
556 }
557 /* Compute first delta value ahead. Also automatically makes us
558 ** skip the first extreme value
559 */
560 if ( size == 1 ) prevval = (int)*CHARP(cp, 0);
561 else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
562 else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
563 if ( size == 1 ) val = (int)*CHARP(cp, size);
564 else if ( size == 2 ) val = (int)*SHORTP(cp, size);
565 else if ( size == 4 ) val = (int)*LONGP(cp, size);
566 prevdiff = val - prevval;
567
568 for ( i=size; i<len; i+= size) {
569 if ( size == 1 ) val = (int)*CHARP(cp, i);
570 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
571 else if ( size == 4 ) val = (int)*LONGP(cp, i);
572 diff = val - prevval;
573 if ( diff*prevdiff < 0 ) {
574 /* Derivative changed sign. Compute difference to last extreme
575 ** value and remember.
576 */
577 if ( prevextremevalid ) {
578 extremediff = prevval - prevextreme;
579 if ( extremediff < 0 )
580 extremediff = -extremediff;
581 if ( extremediff > max )
582 max = extremediff;
583 }
584 prevextremevalid = 1;
585 prevextreme = prevval;
586 }
587 prevval = val;
588 if ( diff != 0 )
589 prevdiff = diff;
590 }
591 return newintobject(max);
592}
593
594static object *
Guido van Rossumb66efa01992-06-01 16:01:24 +0000595audioop_cross(self, args)
596 object *self;
597 object *args;
598{
599 signed char *cp;
600 int len, size, val;
601 int i;
602 int cross, prevval, ncross;
603
604 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
605 return 0;
606 if ( size != 1 && size != 2 && size != 4 ) {
607 err_setstr(AudioopError, "Size should be 1, 2 or 4");
608 return 0;
609 }
610 ncross = -1;
611 prevval = 17; /* Anything <> 0,1 */
612 for ( i=0; i<len; i+= size) {
613 if ( size == 1 ) val = ((int)*CHARP(cp, i)) >> 7;
614 else if ( size == 2 ) val = ((int)*SHORTP(cp, i)) >> 15;
615 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 31;
616 val = val & 1;
617 if ( val != prevval ) ncross++;
618 prevval = val;
619 }
620 return newintobject(ncross);
621}
622
623static object *
624audioop_mul(self, args)
625 object *self;
626 object *args;
627{
628 signed char *cp, *ncp;
629 int len, size, val;
630 double factor, fval, maxval;
631 object *rv;
632 int i;
633
634 if ( !getargs(args, "(s#id)", &cp, &len, &size, &factor ) )
635 return 0;
636
637 if ( size == 1 ) maxval = (double) 0x7f;
638 else if ( size == 2 ) maxval = (double) 0x7fff;
639 else if ( size == 4 ) maxval = (double) 0x7fffffff;
640 else {
641 err_setstr(AudioopError, "Size should be 1, 2 or 4");
642 return 0;
643 }
644
645 rv = newsizedstringobject(NULL, len);
646 if ( rv == 0 )
647 return 0;
648 ncp = (signed char *)getstringvalue(rv);
649
650
651 for ( i=0; i < len; i += size ) {
652 if ( size == 1 ) val = (int)*CHARP(cp, i);
653 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
654 else if ( size == 4 ) val = (int)*LONGP(cp, i);
655 fval = (double)val*factor;
656 if ( fval > maxval ) fval = maxval;
657 else if ( fval < -maxval ) fval = -maxval;
658 val = (int)fval;
659 if ( size == 1 ) *CHARP(ncp, i) = (signed char)val;
660 else if ( size == 2 ) *SHORTP(ncp, i) = (short)val;
661 else if ( size == 4 ) *LONGP(ncp, i) = (long)val;
662 }
663 return rv;
664}
665
666static object *
667audioop_tomono(self, args)
668 object *self;
669 object *args;
670{
671 signed char *cp, *ncp;
672 int len, size, val1, val2;
673 double fac1, fac2, fval, maxval;
674 object *rv;
675 int i;
676
677 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
678 return 0;
679
680 if ( size == 1 ) maxval = (double) 0x7f;
681 else if ( size == 2 ) maxval = (double) 0x7fff;
682 else if ( size == 4 ) maxval = (double) 0x7fffffff;
683 else {
684 err_setstr(AudioopError, "Size should be 1, 2 or 4");
685 return 0;
686 }
687
688 rv = newsizedstringobject(NULL, len/2);
689 if ( rv == 0 )
690 return 0;
691 ncp = (signed char *)getstringvalue(rv);
692
693
694 for ( i=0; i < len; i += size*2 ) {
695 if ( size == 1 ) val1 = (int)*CHARP(cp, i);
696 else if ( size == 2 ) val1 = (int)*SHORTP(cp, i);
697 else if ( size == 4 ) val1 = (int)*LONGP(cp, i);
698 if ( size == 1 ) val2 = (int)*CHARP(cp, i+1);
699 else if ( size == 2 ) val2 = (int)*SHORTP(cp, i+2);
700 else if ( size == 4 ) val2 = (int)*LONGP(cp, i+4);
701 fval = (double)val1*fac1 + (double)val2*fac2;
702 if ( fval > maxval ) fval = maxval;
703 else if ( fval < -maxval ) fval = -maxval;
704 val1 = (int)fval;
705 if ( size == 1 ) *CHARP(ncp, i/2) = (signed char)val1;
706 else if ( size == 2 ) *SHORTP(ncp, i/2) = (short)val1;
707 else if ( size == 4 ) *LONGP(ncp, i/2)= (long)val1;
708 }
709 return rv;
710}
711
712static object *
713audioop_tostereo(self, args)
714 object *self;
715 object *args;
716{
717 signed char *cp, *ncp;
718 int len, size, val1, val2, val;
719 double fac1, fac2, fval, maxval;
720 object *rv;
721 int i;
722
723 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
724 return 0;
725
726 if ( size == 1 ) maxval = (double) 0x7f;
727 else if ( size == 2 ) maxval = (double) 0x7fff;
728 else if ( size == 4 ) maxval = (double) 0x7fffffff;
729 else {
730 err_setstr(AudioopError, "Size should be 1, 2 or 4");
731 return 0;
732 }
733
734 rv = newsizedstringobject(NULL, len*2);
735 if ( rv == 0 )
736 return 0;
737 ncp = (signed char *)getstringvalue(rv);
738
739
740 for ( i=0; i < len; i += size ) {
741 if ( size == 1 ) val = (int)*CHARP(cp, i);
742 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
743 else if ( size == 4 ) val = (int)*LONGP(cp, i);
744
745 fval = (double)val*fac1;
746 if ( fval > maxval ) fval = maxval;
747 else if ( fval < -maxval ) fval = -maxval;
748 val1 = (int)fval;
749
750 fval = (double)val*fac2;
751 if ( fval > maxval ) fval = maxval;
752 else if ( fval < -maxval ) fval = -maxval;
753 val2 = (int)fval;
754
755 if ( size == 1 ) *CHARP(ncp, i*2) = (signed char)val1;
756 else if ( size == 2 ) *SHORTP(ncp, i*2) = (short)val1;
757 else if ( size == 4 ) *LONGP(ncp, i*2) = (long)val1;
758
759 if ( size == 1 ) *CHARP(ncp, i*2+1) = (signed char)val2;
760 else if ( size == 2 ) *SHORTP(ncp, i*2+2) = (short)val2;
761 else if ( size == 4 ) *LONGP(ncp, i*2+4) = (long)val2;
762 }
763 return rv;
764}
765
766static object *
767audioop_add(self, args)
768 object *self;
769 object *args;
770{
771 signed char *cp1, *cp2, *ncp;
772 int len1, len2, size, val1, val2;
773 object *rv;
774 int i;
775
776 if ( !getargs(args, "(s#s#i)",
777 &cp1, &len1, &cp2, &len2, &size ) )
778 return 0;
779
780 if ( len1 != len2 ) {
781 err_setstr(AudioopError, "Lengths should be the same");
782 return 0;
783 }
784
785 if ( size != 1 && size != 2 && size != 4) {
786 err_setstr(AudioopError, "Size should be 1, 2 or 4");
787 return 0;
788 }
789
790 rv = newsizedstringobject(NULL, len1);
791 if ( rv == 0 )
792 return 0;
793 ncp = (signed char *)getstringvalue(rv);
794
795
796 for ( i=0; i < len1; i += size ) {
797 if ( size == 1 ) val1 = (int)*CHARP(cp1, i);
798 else if ( size == 2 ) val1 = (int)*SHORTP(cp1, i);
799 else if ( size == 4 ) val1 = (int)*LONGP(cp1, i);
800
801 if ( size == 1 ) val2 = (int)*CHARP(cp2, i);
802 else if ( size == 2 ) val2 = (int)*SHORTP(cp2, i);
803 else if ( size == 4 ) val2 = (int)*LONGP(cp2, i);
804
805 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val1+val2);
806 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val1+val2);
807 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val1+val2);
808 }
809 return rv;
810}
811
812static object *
813audioop_bias(self, args)
814 object *self;
815 object *args;
816{
817 signed char *cp, *ncp;
818 int len, size, val;
819 object *rv;
820 int i;
821 int bias;
822
823 if ( !getargs(args, "(s#ii)",
824 &cp, &len, &size , &bias) )
825 return 0;
826
827 if ( size != 1 && size != 2 && size != 4) {
828 err_setstr(AudioopError, "Size should be 1, 2 or 4");
829 return 0;
830 }
831
832 rv = newsizedstringobject(NULL, len);
833 if ( rv == 0 )
834 return 0;
835 ncp = (signed char *)getstringvalue(rv);
836
837
838 for ( i=0; i < len; i += size ) {
839 if ( size == 1 ) val = (int)*CHARP(cp, i);
840 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
841 else if ( size == 4 ) val = (int)*LONGP(cp, i);
842
843 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val+bias);
844 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val+bias);
845 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val+bias);
846 }
847 return rv;
848}
849
850static object *
Jack Jansen337b20e1993-02-23 13:39:57 +0000851audioop_reverse(self, args)
852 object *self;
853 object *args;
854{
855 signed char *cp;
856 unsigned char *ncp;
857 int len, size, val;
858 object *rv;
859 int i, j;
860
861 if ( !getargs(args, "(s#i)",
862 &cp, &len, &size) )
863 return 0;
864
865 if ( size != 1 && size != 2 && size != 4 ) {
866 err_setstr(AudioopError, "Size should be 1, 2 or 4");
867 return 0;
868 }
869
870 rv = newsizedstringobject(NULL, len);
871 if ( rv == 0 )
872 return 0;
873 ncp = (unsigned char *)getstringvalue(rv);
874
875 for ( i=0; i < len; i += size ) {
876 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
877 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
878 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
879
880 j = len - i - size;
881
882 if ( size == 1 ) *CHARP(ncp, j) = (signed char)(val >> 8);
883 else if ( size == 2 ) *SHORTP(ncp, j) = (short)(val);
884 else if ( size == 4 ) *LONGP(ncp, j) = (long)(val<<16);
885 }
886 return rv;
887}
888
889static object *
Jack Jansena90805f1993-02-17 14:29:28 +0000890audioop_lin2lin(self, args)
891 object *self;
892 object *args;
893{
894 signed char *cp;
895 unsigned char *ncp;
896 int len, size, size2, val;
897 object *rv;
898 int i, j;
899
900 if ( !getargs(args, "(s#ii)",
901 &cp, &len, &size, &size2) )
902 return 0;
903
904 if ( (size != 1 && size != 2 && size != 4) ||
905 (size2 != 1 && size2 != 2 && size2 != 4)) {
906 err_setstr(AudioopError, "Size should be 1, 2 or 4");
907 return 0;
908 }
909
910 rv = newsizedstringobject(NULL, (len/size)*size2);
911 if ( rv == 0 )
912 return 0;
913 ncp = (unsigned char *)getstringvalue(rv);
914
915 for ( i=0, j=0; i < len; i += size, j += size2 ) {
916 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
917 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
918 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
919
920 if ( size2 == 1 ) *CHARP(ncp, j) = (signed char)(val >> 8);
921 else if ( size2 == 2 ) *SHORTP(ncp, j) = (short)(val);
922 else if ( size2 == 4 ) *LONGP(ncp, j) = (long)(val<<16);
923 }
924 return rv;
925}
926
927static object *
Guido van Rossumb66efa01992-06-01 16:01:24 +0000928audioop_lin2ulaw(self, args)
929 object *self;
930 object *args;
931{
932 signed char *cp;
933 unsigned char *ncp;
934 int len, size, val;
935 object *rv;
936 int i;
937
938 if ( !getargs(args, "(s#i)",
939 &cp, &len, &size) )
940 return 0;
941
942 if ( size != 1 && size != 2 && size != 4) {
943 err_setstr(AudioopError, "Size should be 1, 2 or 4");
944 return 0;
945 }
946
947 rv = newsizedstringobject(NULL, len/size);
948 if ( rv == 0 )
949 return 0;
950 ncp = (unsigned char *)getstringvalue(rv);
951
952 for ( i=0; i < len; i += size ) {
953 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
954 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
955 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
956
957 *ncp++ = st_linear_to_ulaw(val);
958 }
959 return rv;
960}
961
962static object *
963audioop_ulaw2lin(self, args)
964 object *self;
965 object *args;
966{
967 unsigned char *cp;
968 unsigned char cval;
969 signed char *ncp;
970 int len, size, val;
971 object *rv;
972 int i;
973
974 if ( !getargs(args, "(s#i)",
975 &cp, &len, &size) )
976 return 0;
977
978 if ( size != 1 && size != 2 && size != 4) {
979 err_setstr(AudioopError, "Size should be 1, 2 or 4");
980 return 0;
981 }
982
983 rv = newsizedstringobject(NULL, len*size);
984 if ( rv == 0 )
985 return 0;
986 ncp = (signed char *)getstringvalue(rv);
987
988 for ( i=0; i < len*size; i += size ) {
989 cval = *cp++;
990 val = st_ulaw_to_linear(cval);
991
992 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val >> 8);
993 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val);
Guido van Rossumaad53441992-06-05 15:11:56 +0000994 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val<<16);
Guido van Rossumb66efa01992-06-01 16:01:24 +0000995 }
996 return rv;
997}
998
Guido van Rossum8e7a0f01992-06-23 15:23:57 +0000999static object *
Guido van Rossumb64e6351992-07-06 14:21:56 +00001000audioop_lin2adpcm3(self, args)
Guido van Rossum8e7a0f01992-06-23 15:23:57 +00001001 object *self;
1002 object *args;
1003{
1004 signed char *cp;
1005 signed char *ncp;
1006 int len, size, val, step, valprev, delta;
1007 object *rv, *state, *str;
1008 int i;
1009
1010 if ( !getargs(args, "(s#iO)",
1011 &cp, &len, &size, &state) )
1012 return 0;
1013
1014
1015 if ( size != 1 && size != 2 && size != 4) {
1016 err_setstr(AudioopError, "Size should be 1, 2 or 4");
1017 return 0;
1018 }
1019
Jack Jansendd8a6ea1993-02-17 14:21:09 +00001020 str = newsizedstringobject(NULL, len/size);
1021 if ( str == 0 )
1022 return 0;
1023 ncp = (signed char *)getstringvalue(str);
1024
Guido van Rossum8e7a0f01992-06-23 15:23:57 +00001025 /* Decode state, should have (value, step) */
1026 if ( state == None ) {
1027 /* First time, it seems. Set defaults */
1028 valprev = 0;
1029 step = 4; /* The '4' is magic. Dunno it's significance */
1030 } else if ( !getargs(state, "(ii)", &valprev, &step) )
1031 return 0;
1032
1033 for ( i=0; i < len; i += size ) {
1034 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
1035 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
1036 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
1037
1038 /* Step 1 - compute difference with previous value */
1039 delta = (val - valprev)/step;
1040
1041 /* Step 2 - Clamp */
1042 if ( delta < -4 )
1043 delta = -4;
1044 else if ( delta > 3 )
1045 delta = 3;
1046
1047 /* Step 3 - Update previous value */
1048 valprev += delta*step;
1049
1050 /* Step 4 - Clamp previous value to 16 bits */
1051 if ( valprev > 32767 )
1052 valprev = 32767;
1053 else if ( valprev < -32768 )
1054 valprev = -32768;
1055
1056 /* Step 5 - Update step value */
1057 step = step * newstep[abs(delta)];
1058 step++; /* Don't understand this. */
1059
1060 /* Step 6 - Output value (as a whole byte, currently) */
1061 *ncp++ = delta;
1062 }
1063 rv = mkvalue("(O(ii))", str, valprev, step);
1064 DECREF(str);
1065 return rv;
1066}
1067
1068static object *
Guido van Rossumb64e6351992-07-06 14:21:56 +00001069audioop_adpcm32lin(self, args)
Guido van Rossum8e7a0f01992-06-23 15:23:57 +00001070 object *self;
1071 object *args;
1072{
1073 signed char *cp;
1074 signed char *ncp;
1075 int len, size, val, valprev, step, delta;
1076 object *rv, *str, *state;
1077 int i;
1078
1079 if ( !getargs(args, "(s#iO)",
1080 &cp, &len, &size, &state) )
1081 return 0;
1082
1083 if ( size != 1 && size != 2 && size != 4) {
1084 err_setstr(AudioopError, "Size should be 1, 2 or 4");
1085 return 0;
1086 }
1087
1088 /* Decode state, should have (value, step) */
1089 if ( state == None ) {
1090 /* First time, it seems. Set defaults */
1091 valprev = 0;
1092 step = 4; /* The '4' is magic. Dunno it's significance */
1093 } else if ( !getargs(state, "(ii)", &valprev, &step) )
1094 return 0;
1095
1096 str = newsizedstringobject(NULL, len*size);
1097 if ( str == 0 )
1098 return 0;
1099 ncp = (signed char *)getstringvalue(str);
1100
1101 for ( i=0; i < len*size; i += size ) {
1102 /* Step 1 - get the delta value */
1103 delta = *cp++;
1104
1105 /* Step 2 - update output value */
1106 valprev = valprev + delta*step;
1107
1108 /* Step 3 - clamp output value */
1109 if ( valprev > 32767 )
1110 valprev = 32767;
1111 else if ( valprev < -32768 )
1112 valprev = -32768;
1113
1114 /* Step 4 - Update step value */
1115 step = step * newstep[abs(delta)];
1116 step++;
1117
1118 /* Step 5 - Output value */
1119 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valprev >> 8);
1120 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valprev);
1121 else if ( size == 4 ) *LONGP(ncp, i) = (long)(valprev<<16);
1122 }
1123
1124 rv = mkvalue("(O(ii))", str, valprev, step);
1125 DECREF(str);
1126 return rv;
1127}
1128
Guido van Rossumb64e6351992-07-06 14:21:56 +00001129static object *
1130audioop_lin2adpcm(self, args)
1131 object *self;
1132 object *args;
1133{
1134 signed char *cp;
1135 signed char *ncp;
Jack Jansend513f0b1993-01-08 14:40:53 +00001136 int len, size, val, step, valpred, delta, index, sign, vpdiff, diff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001137 object *rv, *state, *str;
1138 int i, outputbuffer, bufferstep;
1139
1140 if ( !getargs(args, "(s#iO)",
1141 &cp, &len, &size, &state) )
1142 return 0;
1143
1144
1145 if ( size != 1 && size != 2 && size != 4) {
1146 err_setstr(AudioopError, "Size should be 1, 2 or 4");
1147 return 0;
1148 }
1149
Jack Jansendd8a6ea1993-02-17 14:21:09 +00001150 str = newsizedstringobject(NULL, len/(size*2));
1151 if ( str == 0 )
1152 return 0;
1153 ncp = (signed char *)getstringvalue(str);
1154
Guido van Rossumb64e6351992-07-06 14:21:56 +00001155 /* Decode state, should have (value, step) */
1156 if ( state == None ) {
1157 /* First time, it seems. Set defaults */
Jack Jansend513f0b1993-01-08 14:40:53 +00001158 valpred = 0;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001159 step = 7;
1160 index = 0;
Jack Jansen55cea471993-02-10 13:21:59 +00001161 } else if ( !getargs(state, "(ii)", &valpred, &index) )
Guido van Rossumb64e6351992-07-06 14:21:56 +00001162 return 0;
1163
Jack Jansen55cea471993-02-10 13:21:59 +00001164 step = stepsizeTable[index];
Guido van Rossumb64e6351992-07-06 14:21:56 +00001165 bufferstep = 1;
1166
1167 for ( i=0; i < len; i += size ) {
1168 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
1169 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
1170 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
1171
1172 /* Step 1 - compute difference with previous value */
Jack Jansend513f0b1993-01-08 14:40:53 +00001173 diff = val - valpred;
1174 sign = (diff < 0) ? 8 : 0;
1175 if ( sign ) diff = (-diff);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001176
1177 /* Step 2 - Divide and clamp */
Jack Jansend513f0b1993-01-08 14:40:53 +00001178 /* Note:
1179 ** This code *approximately* computes:
1180 ** delta = diff*4/step;
1181 ** vpdiff = (delta+0.5)*step/4;
1182 ** but in shift step bits are dropped. The net result of this is
1183 ** that even if you have fast mul/div hardware you cannot put it to
1184 ** good use since the fixup would be too expensive.
1185 */
1186 delta = 0;
1187 vpdiff = (step >> 3);
1188
1189 if ( diff >= step ) {
1190 delta = 4;
1191 diff -= step;
1192 vpdiff += step;
1193 }
1194 step >>= 1;
1195 if ( diff >= step ) {
1196 delta |= 2;
1197 diff -= step;
1198 vpdiff += step;
1199 }
1200 step >>= 1;
1201 if ( diff >= step ) {
1202 delta |= 1;
1203 vpdiff += step;
1204 }
1205
Guido van Rossumb64e6351992-07-06 14:21:56 +00001206 /* Step 3 - Update previous value */
1207 if ( sign )
Jack Jansend513f0b1993-01-08 14:40:53 +00001208 valpred -= vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001209 else
Jack Jansend513f0b1993-01-08 14:40:53 +00001210 valpred += vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001211
1212 /* Step 4 - Clamp previous value to 16 bits */
Jack Jansend513f0b1993-01-08 14:40:53 +00001213 if ( valpred > 32767 )
1214 valpred = 32767;
1215 else if ( valpred < -32768 )
1216 valpred = -32768;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001217
1218 /* Step 5 - Assemble value, update index and step values */
1219 delta |= sign;
1220
1221 index += indexTable[delta];
1222 if ( index < 0 ) index = 0;
1223 if ( index > 88 ) index = 88;
1224 step = stepsizeTable[index];
1225
Jack Jansend513f0b1993-01-08 14:40:53 +00001226 /* Step 6 - Output value */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001227 if ( bufferstep ) {
Jack Jansend513f0b1993-01-08 14:40:53 +00001228 outputbuffer = (delta << 4) & 0xf0;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001229 } else {
Jack Jansend513f0b1993-01-08 14:40:53 +00001230 *ncp++ = (delta & 0x0f) | outputbuffer;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001231 }
1232 bufferstep = !bufferstep;
1233 }
Jack Jansen55cea471993-02-10 13:21:59 +00001234 rv = mkvalue("(O(ii))", str, valpred, index);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001235 DECREF(str);
1236 return rv;
1237}
1238
1239static object *
1240audioop_adpcm2lin(self, args)
1241 object *self;
1242 object *args;
1243{
1244 signed char *cp;
1245 signed char *ncp;
Jack Jansend513f0b1993-01-08 14:40:53 +00001246 int len, size, val, valpred, step, delta, index, sign, vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001247 object *rv, *str, *state;
1248 int i, inputbuffer, bufferstep;
1249
1250 if ( !getargs(args, "(s#iO)",
1251 &cp, &len, &size, &state) )
1252 return 0;
1253
1254 if ( size != 1 && size != 2 && size != 4) {
1255 err_setstr(AudioopError, "Size should be 1, 2 or 4");
1256 return 0;
1257 }
1258
1259 /* Decode state, should have (value, step) */
1260 if ( state == None ) {
1261 /* First time, it seems. Set defaults */
Jack Jansend513f0b1993-01-08 14:40:53 +00001262 valpred = 0;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001263 step = 7;
1264 index = 0;
Jack Jansen55cea471993-02-10 13:21:59 +00001265 } else if ( !getargs(state, "(ii)", &valpred, &index) )
Guido van Rossumb64e6351992-07-06 14:21:56 +00001266 return 0;
1267
1268 str = newsizedstringobject(NULL, len*size*2);
1269 if ( str == 0 )
1270 return 0;
1271 ncp = (signed char *)getstringvalue(str);
1272
Jack Jansen55cea471993-02-10 13:21:59 +00001273 step = stepsizeTable[index];
Guido van Rossumb64e6351992-07-06 14:21:56 +00001274 bufferstep = 0;
1275
1276 for ( i=0; i < len*size*2; i += size ) {
1277 /* Step 1 - get the delta value and compute next index */
1278 if ( bufferstep ) {
1279 delta = inputbuffer & 0xf;
1280 } else {
1281 inputbuffer = *cp++;
1282 delta = (inputbuffer >> 4) & 0xf;
1283 }
1284
1285 bufferstep = !bufferstep;
1286
Jack Jansend513f0b1993-01-08 14:40:53 +00001287 /* Step 2 - Find new index value (for later) */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001288 index += indexTable[delta];
1289 if ( index < 0 ) index = 0;
1290 if ( index > 88 ) index = 88;
1291
Jack Jansend513f0b1993-01-08 14:40:53 +00001292 /* Step 3 - Separate sign and magnitude */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001293 sign = delta & 8;
1294 delta = delta & 7;
1295
Jack Jansend513f0b1993-01-08 14:40:53 +00001296 /* Step 4 - Compute difference and new predicted value */
1297 /*
1298 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
1299 ** in adpcm_coder.
1300 */
1301 vpdiff = step >> 3;
1302 if ( delta & 4 ) vpdiff += step;
1303 if ( delta & 2 ) vpdiff += step>>1;
1304 if ( delta & 1 ) vpdiff += step>>2;
1305
Guido van Rossumb64e6351992-07-06 14:21:56 +00001306 if ( sign )
Jack Jansend513f0b1993-01-08 14:40:53 +00001307 valpred -= vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001308 else
Jack Jansend513f0b1993-01-08 14:40:53 +00001309 valpred += vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001310
Jack Jansend513f0b1993-01-08 14:40:53 +00001311 /* Step 5 - clamp output value */
1312 if ( valpred > 32767 )
1313 valpred = 32767;
1314 else if ( valpred < -32768 )
1315 valpred = -32768;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001316
Jack Jansend513f0b1993-01-08 14:40:53 +00001317 /* Step 6 - Update step value */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001318 step = stepsizeTable[index];
1319
1320 /* Step 6 - Output value */
Jack Jansend513f0b1993-01-08 14:40:53 +00001321 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valpred >> 8);
1322 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valpred);
1323 else if ( size == 4 ) *LONGP(ncp, i) = (long)(valpred<<16);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001324 }
1325
Jack Jansen55cea471993-02-10 13:21:59 +00001326 rv = mkvalue("(O(ii))", str, valpred, index);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001327 DECREF(str);
1328 return rv;
1329}
1330
Guido van Rossumb66efa01992-06-01 16:01:24 +00001331static struct methodlist audioop_methods[] = {
1332 { "max", audioop_max },
Sjoerd Mullenderc4801ed1993-12-13 12:06:27 +00001333 { "minmax", audioop_minmax },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001334 { "avg", audioop_avg },
Jack Jansene1b4d7c1992-08-24 14:36:31 +00001335 { "maxpp", audioop_maxpp },
1336 { "avgpp", audioop_avgpp },
1337 { "rms", audioop_rms },
Jack Jansena90805f1993-02-17 14:29:28 +00001338 { "findfit", audioop_findfit },
1339 { "findmax", audioop_findmax },
1340 { "findfactor", audioop_findfactor },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001341 { "cross", audioop_cross },
1342 { "mul", audioop_mul },
1343 { "add", audioop_add },
1344 { "bias", audioop_bias },
1345 { "ulaw2lin", audioop_ulaw2lin },
1346 { "lin2ulaw", audioop_lin2ulaw },
Jack Jansena90805f1993-02-17 14:29:28 +00001347 { "lin2lin", audioop_lin2lin },
Guido van Rossum8e7a0f01992-06-23 15:23:57 +00001348 { "adpcm2lin", audioop_adpcm2lin },
1349 { "lin2adpcm", audioop_lin2adpcm },
Guido van Rossumb64e6351992-07-06 14:21:56 +00001350 { "adpcm32lin", audioop_adpcm32lin },
1351 { "lin2adpcm3", audioop_lin2adpcm3 },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001352 { "tomono", audioop_tomono },
1353 { "tostereo", audioop_tostereo },
1354 { "getsample", audioop_getsample },
Jack Jansen337b20e1993-02-23 13:39:57 +00001355 { "reverse", audioop_reverse },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001356 { 0, 0 }
1357};
1358
1359
1360void
1361initaudioop()
1362{
1363 object *m, *d;
1364 m = initmodule("audioop", audioop_methods);
1365 d = getmoduledict(m);
1366 AudioopError = newstringobject("audioop.error");
1367 if ( AudioopError == NULL || dictinsert(d,"error",AudioopError) )
1368 fatal("can't define audioop.error");
1369}