blob: e4c37e6b661ea055a3834421ebfb9401e1cf1cf9 [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
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossumb66efa01992-06-01 16:01:24 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossumb66efa01992-06-01 16:01:24 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossumb66efa01992-06-01 16:01:24 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossumb66efa01992-06-01 16:01:24 +000029
30******************************************************************/
31
Guido van Rossumb6775db1994-08-01 11:34:53 +000032/* audioopmodule - Module to detect peak values in arrays */
Jack Jansene1b4d7c1992-08-24 14:36:31 +000033
Guido van Rossumb66efa01992-06-01 16:01:24 +000034#include "allobjects.h"
35#include "modsupport.h"
36
Guido van Rossum7b1e9741994-08-29 10:46:42 +000037#if defined(__CHAR_UNSIGNED__)
38#if defined(signed)
Guido van Rossumb6775db1994-08-01 11:34:53 +000039!ERROR!; READ THE SOURCE FILE!;
40/* This module currently does not work on systems where only unsigned
41 characters are available. Take it out of Setup. Sorry. */
42#endif
Guido van Rossum7b1e9741994-08-29 10:46:42 +000043#endif
Guido van Rossumb6775db1994-08-01 11:34:53 +000044
Guido van Rossuma320fd31995-03-09 12:14:15 +000045#include "mymath.h"
Guido van Rossumb6775db1994-08-01 11:34:53 +000046
Jack Jansena90805f1993-02-17 14:29:28 +000047/* Code shamelessly stolen from sox,
Guido van Rossumb66efa01992-06-01 16:01:24 +000048** (c) Craig Reese, Joe Campbell and Jeff Poskanzer 1989 */
49
50#define MINLIN -32768
51#define MAXLIN 32767
52#define LINCLIP(x) do { if ( x < MINLIN ) x = MINLIN ; else if ( x > MAXLIN ) x = MAXLIN; } while ( 0 )
53
Guido van Rossumcd938fc1995-01-17 16:13:48 +000054static unsigned char st_linear_to_ulaw( /* int sample */ );
Guido van Rossumb66efa01992-06-01 16:01:24 +000055
56/*
57** This macro converts from ulaw to 16 bit linear, faster.
58**
59** Jef Poskanzer
60** 23 October 1989
61**
62** Input: 8 bit ulaw sample
63** Output: signed 16 bit linear sample
64*/
65#define st_ulaw_to_linear(ulawbyte) ulaw_table[ulawbyte]
66
67static int ulaw_table[256] = {
68 -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
69 -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
70 -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
71 -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316,
72 -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
73 -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
74 -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
75 -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
76 -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
77 -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
78 -876, -844, -812, -780, -748, -716, -684, -652,
79 -620, -588, -556, -524, -492, -460, -428, -396,
80 -372, -356, -340, -324, -308, -292, -276, -260,
81 -244, -228, -212, -196, -180, -164, -148, -132,
82 -120, -112, -104, -96, -88, -80, -72, -64,
83 -56, -48, -40, -32, -24, -16, -8, 0,
84 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
85 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
86 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
87 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
88 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
89 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
90 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
91 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
92 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
93 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
94 876, 844, 812, 780, 748, 716, 684, 652,
95 620, 588, 556, 524, 492, 460, 428, 396,
96 372, 356, 340, 324, 308, 292, 276, 260,
97 244, 228, 212, 196, 180, 164, 148, 132,
98 120, 112, 104, 96, 88, 80, 72, 64,
99 56, 48, 40, 32, 24, 16, 8, 0 };
100
101#define ZEROTRAP /* turn on the trap as per the MIL-STD */
102#define BIAS 0x84 /* define the add-in bias for 16 bit samples */
103#define CLIP 32635
104
Guido van Rossumcd938fc1995-01-17 16:13:48 +0000105static unsigned char
Guido van Rossumb66efa01992-06-01 16:01:24 +0000106st_linear_to_ulaw( sample )
107int sample;
108 {
109 static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
110 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
111 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
112 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
113 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
114 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
115 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
116 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
117 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
118 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
119 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
120 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
121 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
122 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
123 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
124 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
125 int sign, exponent, mantissa;
126 unsigned char ulawbyte;
127
128 /* Get the sample into sign-magnitude. */
129 sign = (sample >> 8) & 0x80; /* set aside the sign */
130 if ( sign != 0 ) sample = -sample; /* get magnitude */
131 if ( sample > CLIP ) sample = CLIP; /* clip the magnitude */
132
133 /* Convert from 16 bit linear to ulaw. */
134 sample = sample + BIAS;
135 exponent = exp_lut[( sample >> 7 ) & 0xFF];
136 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
137 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
138#ifdef ZEROTRAP
139 if ( ulawbyte == 0 ) ulawbyte = 0x02; /* optional CCITT trap */
140#endif
141
142 return ulawbyte;
143 }
144/* End of code taken from sox */
145
Guido van Rossumb64e6351992-07-06 14:21:56 +0000146/* Intel ADPCM step variation table */
147static int indexTable[16] = {
148 -1, -1, -1, -1, 2, 4, 6, 8,
149 -1, -1, -1, -1, 2, 4, 6, 8,
150};
151
152static int stepsizeTable[89] = {
153 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
154 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
155 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
156 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
157 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
158 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
159 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
160 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
161 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
162};
163
Guido van Rossumb66efa01992-06-01 16:01:24 +0000164#define CHARP(cp, i) ((signed char *)(cp+i))
165#define SHORTP(cp, i) ((short *)(cp+i))
166#define LONGP(cp, i) ((long *)(cp+i))
167
168
169
170static object *AudioopError;
171
172static object *
173audioop_getsample(self, args)
174 object *self;
175 object *args;
176{
177 signed char *cp;
178 int len, size, val;
179 int i;
180
181 if ( !getargs(args, "(s#ii)", &cp, &len, &size, &i) )
182 return 0;
183 if ( size != 1 && size != 2 && size != 4 ) {
184 err_setstr(AudioopError, "Size should be 1, 2 or 4");
185 return 0;
186 }
187 if ( i < 0 || i >= len/size ) {
188 err_setstr(AudioopError, "Index out of range");
189 return 0;
190 }
191 if ( size == 1 ) val = (int)*CHARP(cp, i);
192 else if ( size == 2 ) val = (int)*SHORTP(cp, i*2);
193 else if ( size == 4 ) val = (int)*LONGP(cp, i*4);
194 return newintobject(val);
195}
196
197static object *
198audioop_max(self, args)
199 object *self;
200 object *args;
201{
202 signed char *cp;
203 int len, size, val;
204 int i;
205 int max = 0;
206
207 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
208 return 0;
209 if ( size != 1 && size != 2 && size != 4 ) {
210 err_setstr(AudioopError, "Size should be 1, 2 or 4");
211 return 0;
212 }
213 for ( i=0; i<len; i+= size) {
214 if ( size == 1 ) val = (int)*CHARP(cp, i);
215 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
216 else if ( size == 4 ) val = (int)*LONGP(cp, i);
217 if ( val < 0 ) val = (-val);
218 if ( val > max ) max = val;
219 }
220 return newintobject(max);
221}
222
223static object *
Sjoerd Mullendera1426131994-09-06 16:19:33 +0000224audioop_minmax(self, args)
225 object *self;
226 object *args;
227{
228 signed char *cp;
229 int len, size, val;
230 int i;
231 int min = 0x7fffffff, max = -0x7fffffff;
232
233 if (!getargs(args, "(s#i)", &cp, &len, &size))
234 return NULL;
235 if (size != 1 && size != 2 && size != 4) {
236 err_setstr(AudioopError, "Size should be 1, 2 or 4");
237 return NULL;
238 }
239 for (i = 0; i < len; i += size) {
240 if (size == 1) val = (int) *CHARP(cp, i);
241 else if (size == 2) val = (int) *SHORTP(cp, i);
242 else if (size == 4) val = (int) *LONGP(cp, i);
243 if (val > max) max = val;
244 if (val < min) min = val;
245 }
246 return mkvalue("(ii)", min, max);
247}
248
249static object *
Guido van Rossumb66efa01992-06-01 16:01:24 +0000250audioop_avg(self, args)
251 object *self;
252 object *args;
253{
254 signed char *cp;
255 int len, size, val;
256 int i;
257 float avg = 0.0;
258
259 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
260 return 0;
261 if ( size != 1 && size != 2 && size != 4 ) {
262 err_setstr(AudioopError, "Size should be 1, 2 or 4");
263 return 0;
264 }
265 for ( i=0; i<len; i+= size) {
266 if ( size == 1 ) val = (int)*CHARP(cp, i);
267 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
268 else if ( size == 4 ) val = (int)*LONGP(cp, i);
269 avg += val;
270 }
271 if ( len == 0 )
272 val = 0;
273 else
274 val = (int)(avg / (float)(len/size));
275 return newintobject(val);
276}
277
278static object *
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000279audioop_rms(self, args)
280 object *self;
281 object *args;
282{
283 signed char *cp;
284 int len, size, val;
285 int i;
286 float sum_squares = 0.0;
287
288 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
289 return 0;
290 if ( size != 1 && size != 2 && size != 4 ) {
291 err_setstr(AudioopError, "Size should be 1, 2 or 4");
292 return 0;
293 }
294 for ( i=0; i<len; i+= size) {
295 if ( size == 1 ) val = (int)*CHARP(cp, i);
296 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
297 else if ( size == 4 ) val = (int)*LONGP(cp, i);
298 sum_squares += (float)val*(float)val;
299 }
300 if ( len == 0 )
301 val = 0;
302 else
303 val = (int)sqrt(sum_squares / (float)(len/size));
304 return newintobject(val);
305}
306
Guido van Rossumcd938fc1995-01-17 16:13:48 +0000307static double _sum2(a, b, len)
Jack Jansena90805f1993-02-17 14:29:28 +0000308 short *a;
309 short *b;
310 int len;
311{
312 int i;
313 double sum = 0.0;
314
315 for( i=0; i<len; i++) {
316 sum = sum + (double)a[i]*(double)b[i];
317 }
318 return sum;
319}
320
321/*
322** Findfit tries to locate a sample within another sample. Its main use
323** is in echo-cancellation (to find the feedback of the output signal in
324** the input signal).
325** The method used is as follows:
326**
327** let R be the reference signal (length n) and A the input signal (length N)
328** with N > n, and let all sums be over i from 0 to n-1.
329**
330** Now, for each j in {0..N-n} we compute a factor fj so that -fj*R matches A
331** as good as possible, i.e. sum( (A[j+i]+fj*R[i])^2 ) is minimal. This
332** equation gives fj = sum( A[j+i]R[i] ) / sum(R[i]^2).
333**
334** Next, we compute the relative distance between the original signal and
335** the modified signal and minimize that over j:
336** vj = sum( (A[j+i]-fj*R[i])^2 ) / sum( A[j+i]^2 ) =>
337** vj = ( sum(A[j+i]^2)*sum(R[i]^2) - sum(A[j+i]R[i])^2 ) / sum( A[j+i]^2 )
338**
339** In the code variables correspond as follows:
340** cp1 A
341** cp2 R
342** len1 N
343** len2 n
344** aj_m1 A[j-1]
345** aj_lm1 A[j+n-1]
346** sum_ri_2 sum(R[i]^2)
347** sum_aij_2 sum(A[i+j]^2)
348** sum_aij_ri sum(A[i+j]R[i])
349**
350** sum_ri is calculated once, sum_aij_2 is updated each step and sum_aij_ri
351** is completely recalculated each step.
352*/
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000353static object *
Jack Jansena90805f1993-02-17 14:29:28 +0000354audioop_findfit(self, args)
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000355 object *self;
356 object *args;
357{
Jack Jansena90805f1993-02-17 14:29:28 +0000358 short *cp1, *cp2;
359 int len1, len2;
360 int j, best_j;
361 double aj_m1, aj_lm1;
362 double sum_ri_2, sum_aij_2, sum_aij_ri, result, best_result, factor;
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000363
Jack Jansena90805f1993-02-17 14:29:28 +0000364 if ( !getargs(args, "(s#s#)", &cp1, &len1, &cp2, &len2) )
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000365 return 0;
Jack Jansena90805f1993-02-17 14:29:28 +0000366 if ( len1 & 1 || len2 & 1 ) {
367 err_setstr(AudioopError, "Strings should be even-sized");
368 return 0;
369 }
370 len1 >>= 1;
371 len2 >>= 1;
372
373 if ( len1 < len2 ) {
374 err_setstr(AudioopError, "First sample should be longer");
375 return 0;
376 }
377 sum_ri_2 = _sum2(cp2, cp2, len2);
378 sum_aij_2 = _sum2(cp1, cp1, len2);
379 sum_aij_ri = _sum2(cp1, cp2, len2);
380
381 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
382
383 best_result = result;
384 best_j = 0;
385 j = 0;
386
387 for ( j=1; j<=len1-len2; j++) {
388 aj_m1 = (double)cp1[j-1];
389 aj_lm1 = (double)cp1[j+len2-1];
390
391 sum_aij_2 = sum_aij_2 + aj_lm1*aj_lm1 - aj_m1*aj_m1;
392 sum_aij_ri = _sum2(cp1+j, cp2, len2);
393
394 result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
395
396 if ( result < best_result ) {
397 best_result = result;
398 best_j = j;
399 }
400
401 }
402
403 factor = _sum2(cp1+best_j, cp2, len2) / sum_ri_2;
404
405 return mkvalue("(if)", best_j, factor);
406}
407
408/*
409** findfactor finds a factor f so that the energy in A-fB is minimal.
410** See the comment for findfit for details.
411*/
412static object *
413audioop_findfactor(self, args)
414 object *self;
415 object *args;
416{
417 short *cp1, *cp2;
418 int len1, len2;
419 double sum_ri_2, sum_aij_ri, result;
420
421 if ( !getargs(args, "(s#s#)", &cp1, &len1, &cp2, &len2) )
422 return 0;
423 if ( len1 & 1 || len2 & 1 ) {
424 err_setstr(AudioopError, "Strings should be even-sized");
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000425 return 0;
426 }
427 if ( len1 != len2 ) {
428 err_setstr(AudioopError, "Samples should be same size");
429 return 0;
430 }
Jack Jansena90805f1993-02-17 14:29:28 +0000431 len2 >>= 1;
432 sum_ri_2 = _sum2(cp2, cp2, len2);
433 sum_aij_ri = _sum2(cp1, cp2, len2);
434
435 result = sum_aij_ri / sum_ri_2;
436
437 return newfloatobject(result);
438}
439
440/*
441** findmax returns the index of the n-sized segment of the input sample
442** that contains the most energy.
443*/
444static object *
445audioop_findmax(self, args)
446 object *self;
447 object *args;
448{
449 short *cp1;
450 int len1, len2;
451 int j, best_j;
452 double aj_m1, aj_lm1;
453 double result, best_result;
454
455 if ( !getargs(args, "(s#i)", &cp1, &len1, &len2) )
456 return 0;
457 if ( len1 & 1 ) {
458 err_setstr(AudioopError, "Strings should be even-sized");
459 return 0;
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000460 }
Jack Jansena90805f1993-02-17 14:29:28 +0000461 len1 >>= 1;
462
463 if ( len1 < len2 ) {
464 err_setstr(AudioopError, "Input sample should be longer");
465 return 0;
466 }
467
468 result = _sum2(cp1, cp1, len2);
469
470 best_result = result;
471 best_j = 0;
472 j = 0;
473
474 for ( j=1; j<=len1-len2; j++) {
475 aj_m1 = (double)cp1[j-1];
476 aj_lm1 = (double)cp1[j+len2-1];
477
478 result = result + aj_lm1*aj_lm1 - aj_m1*aj_m1;
479
480 if ( result > best_result ) {
481 best_result = result;
482 best_j = j;
483 }
484
485 }
486
487 return newintobject(best_j);
Jack Jansendd8a6ea1993-02-17 14:21:09 +0000488}
489
490static object *
Jack Jansene1b4d7c1992-08-24 14:36:31 +0000491audioop_avgpp(self, args)
492 object *self;
493 object *args;
494{
495 signed char *cp;
496 int len, size, val, prevval, prevextremevalid = 0, prevextreme;
497 int i;
498 float avg = 0.0;
499 int diff, prevdiff, extremediff, nextreme = 0;
500
501 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
502 return 0;
503 if ( size != 1 && size != 2 && size != 4 ) {
504 err_setstr(AudioopError, "Size should be 1, 2 or 4");
505 return 0;
506 }
507 /* Compute first delta value ahead. Also automatically makes us
508 ** skip the first extreme value
509 */
510 if ( size == 1 ) prevval = (int)*CHARP(cp, 0);
511 else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
512 else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
513 if ( size == 1 ) val = (int)*CHARP(cp, size);
514 else if ( size == 2 ) val = (int)*SHORTP(cp, size);
515 else if ( size == 4 ) val = (int)*LONGP(cp, size);
516 prevdiff = val - prevval;
517
518 for ( i=size; i<len; i+= size) {
519 if ( size == 1 ) val = (int)*CHARP(cp, i);
520 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
521 else if ( size == 4 ) val = (int)*LONGP(cp, i);
522 diff = val - prevval;
523 if ( diff*prevdiff < 0 ) {
524 /* Derivative changed sign. Compute difference to last extreme
525 ** value and remember.
526 */
527 if ( prevextremevalid ) {
528 extremediff = prevval - prevextreme;
529 if ( extremediff < 0 )
530 extremediff = -extremediff;
531 avg += extremediff;
532 nextreme++;
533 }
534 prevextremevalid = 1;
535 prevextreme = prevval;
536 }
537 prevval = val;
538 if ( diff != 0 )
539 prevdiff = diff;
540 }
541 if ( nextreme == 0 )
542 val = 0;
543 else
544 val = (int)(avg / (float)nextreme);
545 return newintobject(val);
546}
547
548static object *
549audioop_maxpp(self, args)
550 object *self;
551 object *args;
552{
553 signed char *cp;
554 int len, size, val, prevval, prevextremevalid = 0, prevextreme;
555 int i;
556 int max = 0;
557 int diff, prevdiff, extremediff;
558
559 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
560 return 0;
561 if ( size != 1 && size != 2 && size != 4 ) {
562 err_setstr(AudioopError, "Size should be 1, 2 or 4");
563 return 0;
564 }
565 /* Compute first delta value ahead. Also automatically makes us
566 ** skip the first extreme value
567 */
568 if ( size == 1 ) prevval = (int)*CHARP(cp, 0);
569 else if ( size == 2 ) prevval = (int)*SHORTP(cp, 0);
570 else if ( size == 4 ) prevval = (int)*LONGP(cp, 0);
571 if ( size == 1 ) val = (int)*CHARP(cp, size);
572 else if ( size == 2 ) val = (int)*SHORTP(cp, size);
573 else if ( size == 4 ) val = (int)*LONGP(cp, size);
574 prevdiff = val - prevval;
575
576 for ( i=size; i<len; i+= size) {
577 if ( size == 1 ) val = (int)*CHARP(cp, i);
578 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
579 else if ( size == 4 ) val = (int)*LONGP(cp, i);
580 diff = val - prevval;
581 if ( diff*prevdiff < 0 ) {
582 /* Derivative changed sign. Compute difference to last extreme
583 ** value and remember.
584 */
585 if ( prevextremevalid ) {
586 extremediff = prevval - prevextreme;
587 if ( extremediff < 0 )
588 extremediff = -extremediff;
589 if ( extremediff > max )
590 max = extremediff;
591 }
592 prevextremevalid = 1;
593 prevextreme = prevval;
594 }
595 prevval = val;
596 if ( diff != 0 )
597 prevdiff = diff;
598 }
599 return newintobject(max);
600}
601
602static object *
Guido van Rossumb66efa01992-06-01 16:01:24 +0000603audioop_cross(self, args)
604 object *self;
605 object *args;
606{
607 signed char *cp;
608 int len, size, val;
609 int i;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000610 int prevval, ncross;
Guido van Rossumb66efa01992-06-01 16:01:24 +0000611
612 if ( !getargs(args, "(s#i)", &cp, &len, &size) )
613 return 0;
614 if ( size != 1 && size != 2 && size != 4 ) {
615 err_setstr(AudioopError, "Size should be 1, 2 or 4");
616 return 0;
617 }
618 ncross = -1;
619 prevval = 17; /* Anything <> 0,1 */
620 for ( i=0; i<len; i+= size) {
621 if ( size == 1 ) val = ((int)*CHARP(cp, i)) >> 7;
622 else if ( size == 2 ) val = ((int)*SHORTP(cp, i)) >> 15;
623 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 31;
624 val = val & 1;
625 if ( val != prevval ) ncross++;
626 prevval = val;
627 }
628 return newintobject(ncross);
629}
630
631static object *
632audioop_mul(self, args)
633 object *self;
634 object *args;
635{
636 signed char *cp, *ncp;
637 int len, size, val;
638 double factor, fval, maxval;
639 object *rv;
640 int i;
641
642 if ( !getargs(args, "(s#id)", &cp, &len, &size, &factor ) )
643 return 0;
644
645 if ( size == 1 ) maxval = (double) 0x7f;
646 else if ( size == 2 ) maxval = (double) 0x7fff;
647 else if ( size == 4 ) maxval = (double) 0x7fffffff;
648 else {
649 err_setstr(AudioopError, "Size should be 1, 2 or 4");
650 return 0;
651 }
652
653 rv = newsizedstringobject(NULL, len);
654 if ( rv == 0 )
655 return 0;
656 ncp = (signed char *)getstringvalue(rv);
657
658
659 for ( i=0; i < len; i += size ) {
660 if ( size == 1 ) val = (int)*CHARP(cp, i);
661 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
662 else if ( size == 4 ) val = (int)*LONGP(cp, i);
663 fval = (double)val*factor;
664 if ( fval > maxval ) fval = maxval;
665 else if ( fval < -maxval ) fval = -maxval;
666 val = (int)fval;
667 if ( size == 1 ) *CHARP(ncp, i) = (signed char)val;
668 else if ( size == 2 ) *SHORTP(ncp, i) = (short)val;
669 else if ( size == 4 ) *LONGP(ncp, i) = (long)val;
670 }
671 return rv;
672}
673
674static object *
675audioop_tomono(self, args)
676 object *self;
677 object *args;
678{
679 signed char *cp, *ncp;
680 int len, size, val1, val2;
681 double fac1, fac2, fval, maxval;
682 object *rv;
683 int i;
684
685 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
686 return 0;
687
688 if ( size == 1 ) maxval = (double) 0x7f;
689 else if ( size == 2 ) maxval = (double) 0x7fff;
690 else if ( size == 4 ) maxval = (double) 0x7fffffff;
691 else {
692 err_setstr(AudioopError, "Size should be 1, 2 or 4");
693 return 0;
694 }
695
696 rv = newsizedstringobject(NULL, len/2);
697 if ( rv == 0 )
698 return 0;
699 ncp = (signed char *)getstringvalue(rv);
700
701
702 for ( i=0; i < len; i += size*2 ) {
703 if ( size == 1 ) val1 = (int)*CHARP(cp, i);
704 else if ( size == 2 ) val1 = (int)*SHORTP(cp, i);
705 else if ( size == 4 ) val1 = (int)*LONGP(cp, i);
706 if ( size == 1 ) val2 = (int)*CHARP(cp, i+1);
707 else if ( size == 2 ) val2 = (int)*SHORTP(cp, i+2);
708 else if ( size == 4 ) val2 = (int)*LONGP(cp, i+4);
709 fval = (double)val1*fac1 + (double)val2*fac2;
710 if ( fval > maxval ) fval = maxval;
711 else if ( fval < -maxval ) fval = -maxval;
712 val1 = (int)fval;
713 if ( size == 1 ) *CHARP(ncp, i/2) = (signed char)val1;
714 else if ( size == 2 ) *SHORTP(ncp, i/2) = (short)val1;
715 else if ( size == 4 ) *LONGP(ncp, i/2)= (long)val1;
716 }
717 return rv;
718}
719
720static object *
721audioop_tostereo(self, args)
722 object *self;
723 object *args;
724{
725 signed char *cp, *ncp;
726 int len, size, val1, val2, val;
727 double fac1, fac2, fval, maxval;
728 object *rv;
729 int i;
730
731 if ( !getargs(args, "(s#idd)", &cp, &len, &size, &fac1, &fac2 ) )
732 return 0;
733
734 if ( size == 1 ) maxval = (double) 0x7f;
735 else if ( size == 2 ) maxval = (double) 0x7fff;
736 else if ( size == 4 ) maxval = (double) 0x7fffffff;
737 else {
738 err_setstr(AudioopError, "Size should be 1, 2 or 4");
739 return 0;
740 }
741
742 rv = newsizedstringobject(NULL, len*2);
743 if ( rv == 0 )
744 return 0;
745 ncp = (signed char *)getstringvalue(rv);
746
747
748 for ( i=0; i < len; i += size ) {
749 if ( size == 1 ) val = (int)*CHARP(cp, i);
750 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
751 else if ( size == 4 ) val = (int)*LONGP(cp, i);
752
753 fval = (double)val*fac1;
754 if ( fval > maxval ) fval = maxval;
755 else if ( fval < -maxval ) fval = -maxval;
756 val1 = (int)fval;
757
758 fval = (double)val*fac2;
759 if ( fval > maxval ) fval = maxval;
760 else if ( fval < -maxval ) fval = -maxval;
761 val2 = (int)fval;
762
763 if ( size == 1 ) *CHARP(ncp, i*2) = (signed char)val1;
764 else if ( size == 2 ) *SHORTP(ncp, i*2) = (short)val1;
765 else if ( size == 4 ) *LONGP(ncp, i*2) = (long)val1;
766
767 if ( size == 1 ) *CHARP(ncp, i*2+1) = (signed char)val2;
768 else if ( size == 2 ) *SHORTP(ncp, i*2+2) = (short)val2;
769 else if ( size == 4 ) *LONGP(ncp, i*2+4) = (long)val2;
770 }
771 return rv;
772}
773
774static object *
775audioop_add(self, args)
776 object *self;
777 object *args;
778{
779 signed char *cp1, *cp2, *ncp;
780 int len1, len2, size, val1, val2;
781 object *rv;
782 int i;
783
784 if ( !getargs(args, "(s#s#i)",
785 &cp1, &len1, &cp2, &len2, &size ) )
786 return 0;
787
788 if ( len1 != len2 ) {
789 err_setstr(AudioopError, "Lengths should be the same");
790 return 0;
791 }
792
793 if ( size != 1 && size != 2 && size != 4) {
794 err_setstr(AudioopError, "Size should be 1, 2 or 4");
795 return 0;
796 }
797
798 rv = newsizedstringobject(NULL, len1);
799 if ( rv == 0 )
800 return 0;
801 ncp = (signed char *)getstringvalue(rv);
802
803
804 for ( i=0; i < len1; i += size ) {
805 if ( size == 1 ) val1 = (int)*CHARP(cp1, i);
806 else if ( size == 2 ) val1 = (int)*SHORTP(cp1, i);
807 else if ( size == 4 ) val1 = (int)*LONGP(cp1, i);
808
809 if ( size == 1 ) val2 = (int)*CHARP(cp2, i);
810 else if ( size == 2 ) val2 = (int)*SHORTP(cp2, i);
811 else if ( size == 4 ) val2 = (int)*LONGP(cp2, i);
812
813 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val1+val2);
814 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val1+val2);
815 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val1+val2);
816 }
817 return rv;
818}
819
820static object *
821audioop_bias(self, args)
822 object *self;
823 object *args;
824{
825 signed char *cp, *ncp;
826 int len, size, val;
827 object *rv;
828 int i;
829 int bias;
830
831 if ( !getargs(args, "(s#ii)",
832 &cp, &len, &size , &bias) )
833 return 0;
834
835 if ( size != 1 && size != 2 && size != 4) {
836 err_setstr(AudioopError, "Size should be 1, 2 or 4");
837 return 0;
838 }
839
840 rv = newsizedstringobject(NULL, len);
841 if ( rv == 0 )
842 return 0;
843 ncp = (signed char *)getstringvalue(rv);
844
845
846 for ( i=0; i < len; i += size ) {
847 if ( size == 1 ) val = (int)*CHARP(cp, i);
848 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
849 else if ( size == 4 ) val = (int)*LONGP(cp, i);
850
851 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val+bias);
852 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val+bias);
853 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val+bias);
854 }
855 return rv;
856}
857
858static object *
Jack Jansen337b20e1993-02-23 13:39:57 +0000859audioop_reverse(self, args)
860 object *self;
861 object *args;
862{
863 signed char *cp;
864 unsigned char *ncp;
865 int len, size, val;
866 object *rv;
867 int i, j;
868
869 if ( !getargs(args, "(s#i)",
870 &cp, &len, &size) )
871 return 0;
872
873 if ( size != 1 && size != 2 && size != 4 ) {
874 err_setstr(AudioopError, "Size should be 1, 2 or 4");
875 return 0;
876 }
877
878 rv = newsizedstringobject(NULL, len);
879 if ( rv == 0 )
880 return 0;
881 ncp = (unsigned char *)getstringvalue(rv);
882
883 for ( i=0; i < len; i += size ) {
884 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
885 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
886 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
887
888 j = len - i - size;
889
890 if ( size == 1 ) *CHARP(ncp, j) = (signed char)(val >> 8);
891 else if ( size == 2 ) *SHORTP(ncp, j) = (short)(val);
892 else if ( size == 4 ) *LONGP(ncp, j) = (long)(val<<16);
893 }
894 return rv;
895}
896
897static object *
Jack Jansena90805f1993-02-17 14:29:28 +0000898audioop_lin2lin(self, args)
899 object *self;
900 object *args;
901{
902 signed char *cp;
903 unsigned char *ncp;
904 int len, size, size2, val;
905 object *rv;
906 int i, j;
907
908 if ( !getargs(args, "(s#ii)",
909 &cp, &len, &size, &size2) )
910 return 0;
911
912 if ( (size != 1 && size != 2 && size != 4) ||
913 (size2 != 1 && size2 != 2 && size2 != 4)) {
914 err_setstr(AudioopError, "Size should be 1, 2 or 4");
915 return 0;
916 }
917
918 rv = newsizedstringobject(NULL, (len/size)*size2);
919 if ( rv == 0 )
920 return 0;
921 ncp = (unsigned char *)getstringvalue(rv);
922
923 for ( i=0, j=0; i < len; i += size, j += size2 ) {
924 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
925 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
926 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
927
928 if ( size2 == 1 ) *CHARP(ncp, j) = (signed char)(val >> 8);
929 else if ( size2 == 2 ) *SHORTP(ncp, j) = (short)(val);
930 else if ( size2 == 4 ) *LONGP(ncp, j) = (long)(val<<16);
931 }
932 return rv;
933}
934
935static object *
Guido van Rossumb66efa01992-06-01 16:01:24 +0000936audioop_lin2ulaw(self, args)
937 object *self;
938 object *args;
939{
940 signed char *cp;
941 unsigned char *ncp;
942 int len, size, val;
943 object *rv;
944 int i;
945
946 if ( !getargs(args, "(s#i)",
947 &cp, &len, &size) )
948 return 0;
949
950 if ( size != 1 && size != 2 && size != 4) {
951 err_setstr(AudioopError, "Size should be 1, 2 or 4");
952 return 0;
953 }
954
955 rv = newsizedstringobject(NULL, len/size);
956 if ( rv == 0 )
957 return 0;
958 ncp = (unsigned char *)getstringvalue(rv);
959
960 for ( i=0; i < len; i += size ) {
961 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
962 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
963 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
964
965 *ncp++ = st_linear_to_ulaw(val);
966 }
967 return rv;
968}
969
970static object *
971audioop_ulaw2lin(self, args)
972 object *self;
973 object *args;
974{
975 unsigned char *cp;
976 unsigned char cval;
977 signed char *ncp;
978 int len, size, val;
979 object *rv;
980 int i;
981
982 if ( !getargs(args, "(s#i)",
983 &cp, &len, &size) )
984 return 0;
985
986 if ( size != 1 && size != 2 && size != 4) {
987 err_setstr(AudioopError, "Size should be 1, 2 or 4");
988 return 0;
989 }
990
991 rv = newsizedstringobject(NULL, len*size);
992 if ( rv == 0 )
993 return 0;
994 ncp = (signed char *)getstringvalue(rv);
995
996 for ( i=0; i < len*size; i += size ) {
997 cval = *cp++;
998 val = st_ulaw_to_linear(cval);
999
1000 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(val >> 8);
1001 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val);
Guido van Rossumaad53441992-06-05 15:11:56 +00001002 else if ( size == 4 ) *LONGP(ncp, i) = (long)(val<<16);
Guido van Rossumb66efa01992-06-01 16:01:24 +00001003 }
1004 return rv;
1005}
1006
Guido van Rossum8e7a0f01992-06-23 15:23:57 +00001007static object *
Guido van Rossumb64e6351992-07-06 14:21:56 +00001008audioop_lin2adpcm(self, args)
1009 object *self;
1010 object *args;
1011{
1012 signed char *cp;
1013 signed char *ncp;
Jack Jansend513f0b1993-01-08 14:40:53 +00001014 int len, size, val, step, valpred, delta, index, sign, vpdiff, diff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001015 object *rv, *state, *str;
1016 int i, outputbuffer, bufferstep;
1017
1018 if ( !getargs(args, "(s#iO)",
1019 &cp, &len, &size, &state) )
1020 return 0;
1021
1022
1023 if ( size != 1 && size != 2 && size != 4) {
1024 err_setstr(AudioopError, "Size should be 1, 2 or 4");
1025 return 0;
1026 }
1027
Jack Jansendd8a6ea1993-02-17 14:21:09 +00001028 str = newsizedstringobject(NULL, len/(size*2));
1029 if ( str == 0 )
1030 return 0;
1031 ncp = (signed char *)getstringvalue(str);
1032
Guido van Rossumb64e6351992-07-06 14:21:56 +00001033 /* Decode state, should have (value, step) */
1034 if ( state == None ) {
1035 /* First time, it seems. Set defaults */
Jack Jansend513f0b1993-01-08 14:40:53 +00001036 valpred = 0;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001037 step = 7;
1038 index = 0;
Jack Jansen55cea471993-02-10 13:21:59 +00001039 } else if ( !getargs(state, "(ii)", &valpred, &index) )
Guido van Rossumb64e6351992-07-06 14:21:56 +00001040 return 0;
1041
Jack Jansen55cea471993-02-10 13:21:59 +00001042 step = stepsizeTable[index];
Guido van Rossumb64e6351992-07-06 14:21:56 +00001043 bufferstep = 1;
1044
1045 for ( i=0; i < len; i += size ) {
1046 if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
1047 else if ( size == 2 ) val = (int)*SHORTP(cp, i);
1048 else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
1049
1050 /* Step 1 - compute difference with previous value */
Jack Jansend513f0b1993-01-08 14:40:53 +00001051 diff = val - valpred;
1052 sign = (diff < 0) ? 8 : 0;
1053 if ( sign ) diff = (-diff);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001054
1055 /* Step 2 - Divide and clamp */
Jack Jansend513f0b1993-01-08 14:40:53 +00001056 /* Note:
1057 ** This code *approximately* computes:
1058 ** delta = diff*4/step;
1059 ** vpdiff = (delta+0.5)*step/4;
1060 ** but in shift step bits are dropped. The net result of this is
1061 ** that even if you have fast mul/div hardware you cannot put it to
1062 ** good use since the fixup would be too expensive.
1063 */
1064 delta = 0;
1065 vpdiff = (step >> 3);
1066
1067 if ( diff >= step ) {
1068 delta = 4;
1069 diff -= step;
1070 vpdiff += step;
1071 }
1072 step >>= 1;
1073 if ( diff >= step ) {
1074 delta |= 2;
1075 diff -= step;
1076 vpdiff += step;
1077 }
1078 step >>= 1;
1079 if ( diff >= step ) {
1080 delta |= 1;
1081 vpdiff += step;
1082 }
1083
Guido van Rossumb64e6351992-07-06 14:21:56 +00001084 /* Step 3 - Update previous value */
1085 if ( sign )
Jack Jansend513f0b1993-01-08 14:40:53 +00001086 valpred -= vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001087 else
Jack Jansend513f0b1993-01-08 14:40:53 +00001088 valpred += vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001089
1090 /* Step 4 - Clamp previous value to 16 bits */
Jack Jansend513f0b1993-01-08 14:40:53 +00001091 if ( valpred > 32767 )
1092 valpred = 32767;
1093 else if ( valpred < -32768 )
1094 valpred = -32768;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001095
1096 /* Step 5 - Assemble value, update index and step values */
1097 delta |= sign;
1098
1099 index += indexTable[delta];
1100 if ( index < 0 ) index = 0;
1101 if ( index > 88 ) index = 88;
1102 step = stepsizeTable[index];
1103
Jack Jansend513f0b1993-01-08 14:40:53 +00001104 /* Step 6 - Output value */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001105 if ( bufferstep ) {
Jack Jansend513f0b1993-01-08 14:40:53 +00001106 outputbuffer = (delta << 4) & 0xf0;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001107 } else {
Jack Jansend513f0b1993-01-08 14:40:53 +00001108 *ncp++ = (delta & 0x0f) | outputbuffer;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001109 }
1110 bufferstep = !bufferstep;
1111 }
Jack Jansen55cea471993-02-10 13:21:59 +00001112 rv = mkvalue("(O(ii))", str, valpred, index);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001113 DECREF(str);
1114 return rv;
1115}
1116
1117static object *
1118audioop_adpcm2lin(self, args)
1119 object *self;
1120 object *args;
1121{
1122 signed char *cp;
1123 signed char *ncp;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +00001124 int len, size, valpred, step, delta, index, sign, vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001125 object *rv, *str, *state;
1126 int i, inputbuffer, bufferstep;
1127
1128 if ( !getargs(args, "(s#iO)",
1129 &cp, &len, &size, &state) )
1130 return 0;
1131
1132 if ( size != 1 && size != 2 && size != 4) {
1133 err_setstr(AudioopError, "Size should be 1, 2 or 4");
1134 return 0;
1135 }
1136
1137 /* Decode state, should have (value, step) */
1138 if ( state == None ) {
1139 /* First time, it seems. Set defaults */
Jack Jansend513f0b1993-01-08 14:40:53 +00001140 valpred = 0;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001141 step = 7;
1142 index = 0;
Jack Jansen55cea471993-02-10 13:21:59 +00001143 } else if ( !getargs(state, "(ii)", &valpred, &index) )
Guido van Rossumb64e6351992-07-06 14:21:56 +00001144 return 0;
1145
1146 str = newsizedstringobject(NULL, len*size*2);
1147 if ( str == 0 )
1148 return 0;
1149 ncp = (signed char *)getstringvalue(str);
1150
Jack Jansen55cea471993-02-10 13:21:59 +00001151 step = stepsizeTable[index];
Guido van Rossumb64e6351992-07-06 14:21:56 +00001152 bufferstep = 0;
1153
1154 for ( i=0; i < len*size*2; i += size ) {
1155 /* Step 1 - get the delta value and compute next index */
1156 if ( bufferstep ) {
1157 delta = inputbuffer & 0xf;
1158 } else {
1159 inputbuffer = *cp++;
1160 delta = (inputbuffer >> 4) & 0xf;
1161 }
1162
1163 bufferstep = !bufferstep;
1164
Jack Jansend513f0b1993-01-08 14:40:53 +00001165 /* Step 2 - Find new index value (for later) */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001166 index += indexTable[delta];
1167 if ( index < 0 ) index = 0;
1168 if ( index > 88 ) index = 88;
1169
Jack Jansend513f0b1993-01-08 14:40:53 +00001170 /* Step 3 - Separate sign and magnitude */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001171 sign = delta & 8;
1172 delta = delta & 7;
1173
Jack Jansend513f0b1993-01-08 14:40:53 +00001174 /* Step 4 - Compute difference and new predicted value */
1175 /*
1176 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
1177 ** in adpcm_coder.
1178 */
1179 vpdiff = step >> 3;
1180 if ( delta & 4 ) vpdiff += step;
1181 if ( delta & 2 ) vpdiff += step>>1;
1182 if ( delta & 1 ) vpdiff += step>>2;
1183
Guido van Rossumb64e6351992-07-06 14:21:56 +00001184 if ( sign )
Jack Jansend513f0b1993-01-08 14:40:53 +00001185 valpred -= vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001186 else
Jack Jansend513f0b1993-01-08 14:40:53 +00001187 valpred += vpdiff;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001188
Jack Jansend513f0b1993-01-08 14:40:53 +00001189 /* Step 5 - clamp output value */
1190 if ( valpred > 32767 )
1191 valpred = 32767;
1192 else if ( valpred < -32768 )
1193 valpred = -32768;
Guido van Rossumb64e6351992-07-06 14:21:56 +00001194
Jack Jansend513f0b1993-01-08 14:40:53 +00001195 /* Step 6 - Update step value */
Guido van Rossumb64e6351992-07-06 14:21:56 +00001196 step = stepsizeTable[index];
1197
1198 /* Step 6 - Output value */
Jack Jansend513f0b1993-01-08 14:40:53 +00001199 if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valpred >> 8);
1200 else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valpred);
1201 else if ( size == 4 ) *LONGP(ncp, i) = (long)(valpred<<16);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001202 }
1203
Jack Jansen55cea471993-02-10 13:21:59 +00001204 rv = mkvalue("(O(ii))", str, valpred, index);
Guido van Rossumb64e6351992-07-06 14:21:56 +00001205 DECREF(str);
1206 return rv;
1207}
1208
Guido van Rossumb66efa01992-06-01 16:01:24 +00001209static struct methodlist audioop_methods[] = {
1210 { "max", audioop_max },
Sjoerd Mullendera1426131994-09-06 16:19:33 +00001211 { "minmax", audioop_minmax },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001212 { "avg", audioop_avg },
Jack Jansene1b4d7c1992-08-24 14:36:31 +00001213 { "maxpp", audioop_maxpp },
1214 { "avgpp", audioop_avgpp },
1215 { "rms", audioop_rms },
Jack Jansena90805f1993-02-17 14:29:28 +00001216 { "findfit", audioop_findfit },
1217 { "findmax", audioop_findmax },
1218 { "findfactor", audioop_findfactor },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001219 { "cross", audioop_cross },
1220 { "mul", audioop_mul },
1221 { "add", audioop_add },
1222 { "bias", audioop_bias },
1223 { "ulaw2lin", audioop_ulaw2lin },
1224 { "lin2ulaw", audioop_lin2ulaw },
Jack Jansena90805f1993-02-17 14:29:28 +00001225 { "lin2lin", audioop_lin2lin },
Guido van Rossum8e7a0f01992-06-23 15:23:57 +00001226 { "adpcm2lin", audioop_adpcm2lin },
1227 { "lin2adpcm", audioop_lin2adpcm },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001228 { "tomono", audioop_tomono },
1229 { "tostereo", audioop_tostereo },
1230 { "getsample", audioop_getsample },
Jack Jansen337b20e1993-02-23 13:39:57 +00001231 { "reverse", audioop_reverse },
Guido van Rossumb66efa01992-06-01 16:01:24 +00001232 { 0, 0 }
1233};
1234
1235
1236void
1237initaudioop()
1238{
1239 object *m, *d;
1240 m = initmodule("audioop", audioop_methods);
1241 d = getmoduledict(m);
1242 AudioopError = newstringobject("audioop.error");
1243 if ( AudioopError == NULL || dictinsert(d,"error",AudioopError) )
1244 fatal("can't define audioop.error");
1245}