1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 /* audioopmodule - Module to detect peak values in arrays */
27 #include "allobjects.h"
28 #include "modsupport.h"
30 #if defined(__CHAR_UNSIGNED__)
32 !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. */
40 /* Code shamelessly stolen from sox,
41 ** (c) Craig Reese, Joe Campbell and Jeff Poskanzer 1989 */
45 #define LINCLIP(x) do { if ( x < MINLIN ) x = MINLIN ; else if ( x > MAXLIN ) x = MAXLIN; } while ( 0 )
47 static unsigned char st_linear_to_ulaw( /* int sample */ );
50 ** This macro converts from ulaw to 16 bit linear, faster.
55 ** Input: 8 bit ulaw sample
56 ** Output: signed 16 bit linear sample
58 #define st_ulaw_to_linear(ulawbyte) ulaw_table[ulawbyte]
60 static 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 };
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 */
99 st_linear_to_ulaw( sample
)
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
;
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 */
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
);
132 if ( ulawbyte
== 0 ) ulawbyte
= 0x02; /* optional CCITT trap */
137 /* End of code taken from sox */
139 /* Intel ADPCM step variation table */
140 static int indexTable
[16] = {
141 -1, -1, -1, -1, 2, 4, 6, 8,
142 -1, -1, -1, -1, 2, 4, 6, 8,
145 static 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
157 #define CHARP(cp, i) ((signed char *)(cp+i))
158 #define SHORTP(cp, i) ((short *)(cp+i))
159 #define LONGP(cp, i) ((long *)(cp+i))
163 static object
*AudioopError
;
166 audioop_getsample(self
, args
)
174 if ( !getargs(args
, "(s#ii)", &cp
, &len
, &size
, &i
) )
176 if ( size
!= 1 && size
!= 2 && size
!= 4 ) {
177 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
180 if ( i
< 0 || i
>= len
/size
) {
181 err_setstr(AudioopError
, "Index out of range");
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
);
191 audioop_max(self
, args
)
200 if ( !getargs(args
, "(s#i)", &cp
, &len
, &size
) )
202 if ( size
!= 1 && size
!= 2 && size
!= 4 ) {
203 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
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
;
213 return newintobject(max
);
217 audioop_minmax(self
, args
)
224 int min
= 0x7fffffff, max
= -0x7fffffff;
226 if (!getargs(args
, "(s#i)", &cp
, &len
, &size
))
228 if (size
!= 1 && size
!= 2 && size
!= 4) {
229 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
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
;
239 return mkvalue("(ii)", min
, max
);
243 audioop_avg(self
, args
)
252 if ( !getargs(args
, "(s#i)", &cp
, &len
, &size
) )
254 if ( size
!= 1 && size
!= 2 && size
!= 4 ) {
255 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
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
);
267 val
= (int)(avg
/ (float)(len
/size
));
268 return newintobject(val
);
272 audioop_rms(self
, args
)
279 float sum_squares
= 0.0;
281 if ( !getargs(args
, "(s#i)", &cp
, &len
, &size
) )
283 if ( size
!= 1 && size
!= 2 && size
!= 4 ) {
284 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
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
;
296 val
= (int)sqrt(sum_squares
/ (float)(len
/size
));
297 return newintobject(val
);
300 static double _sum2(a
, b
, len
)
308 for( i
=0; i
<len
; i
++) {
309 sum
= sum
+ (double)a
[i
]*(double)b
[i
];
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:
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.
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).
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 )
332 ** In the code variables correspond as follows:
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])
343 ** sum_ri is calculated once, sum_aij_2 is updated each step and sum_aij_ri
344 ** is completely recalculated each step.
347 audioop_findfit(self
, args
)
354 double aj_m1
, aj_lm1
;
355 double sum_ri_2
, sum_aij_2
, sum_aij_ri
, result
, best_result
, factor
;
357 if ( !getargs(args
, "(s#s#)", &cp1
, &len1
, &cp2
, &len2
) )
359 if ( len1
& 1 || len2
& 1 ) {
360 err_setstr(AudioopError
, "Strings should be even-sized");
367 err_setstr(AudioopError
, "First sample should be longer");
370 sum_ri_2
= _sum2(cp2
, cp2
, len2
);
371 sum_aij_2
= _sum2(cp1
, cp1
, len2
);
372 sum_aij_ri
= _sum2(cp1
, cp2
, len2
);
374 result
= (sum_ri_2
*sum_aij_2
- sum_aij_ri
*sum_aij_ri
) / sum_aij_2
;
376 best_result
= result
;
380 for ( j
=1; j
<=len1
-len2
; j
++) {
381 aj_m1
= (double)cp1
[j
-1];
382 aj_lm1
= (double)cp1
[j
+len2
-1];
384 sum_aij_2
= sum_aij_2
+ aj_lm1
*aj_lm1
- aj_m1
*aj_m1
;
385 sum_aij_ri
= _sum2(cp1
+j
, cp2
, len2
);
387 result
= (sum_ri_2
*sum_aij_2
- sum_aij_ri
*sum_aij_ri
) / sum_aij_2
;
389 if ( result
< best_result
) {
390 best_result
= result
;
396 factor
= _sum2(cp1
+best_j
, cp2
, len2
) / sum_ri_2
;
398 return mkvalue("(if)", best_j
, factor
);
402 ** findfactor finds a factor f so that the energy in A-fB is minimal.
403 ** See the comment for findfit for details.
406 audioop_findfactor(self
, args
)
412 double sum_ri_2
, sum_aij_ri
, result
;
414 if ( !getargs(args
, "(s#s#)", &cp1
, &len1
, &cp2
, &len2
) )
416 if ( len1
& 1 || len2
& 1 ) {
417 err_setstr(AudioopError
, "Strings should be even-sized");
420 if ( len1
!= len2
) {
421 err_setstr(AudioopError
, "Samples should be same size");
425 sum_ri_2
= _sum2(cp2
, cp2
, len2
);
426 sum_aij_ri
= _sum2(cp1
, cp2
, len2
);
428 result
= sum_aij_ri
/ sum_ri_2
;
430 return newfloatobject(result
);
434 ** findmax returns the index of the n-sized segment of the input sample
435 ** that contains the most energy.
438 audioop_findmax(self
, args
)
445 double aj_m1
, aj_lm1
;
446 double result
, best_result
;
448 if ( !getargs(args
, "(s#i)", &cp1
, &len1
, &len2
) )
451 err_setstr(AudioopError
, "Strings should be even-sized");
457 err_setstr(AudioopError
, "Input sample should be longer");
461 result
= _sum2(cp1
, cp1
, len2
);
463 best_result
= result
;
467 for ( j
=1; j
<=len1
-len2
; j
++) {
468 aj_m1
= (double)cp1
[j
-1];
469 aj_lm1
= (double)cp1
[j
+len2
-1];
471 result
= result
+ aj_lm1
*aj_lm1
- aj_m1
*aj_m1
;
473 if ( result
> best_result
) {
474 best_result
= result
;
480 return newintobject(best_j
);
484 audioop_avgpp(self
, args
)
489 int len
, size
, val
, prevval
, prevextremevalid
= 0, prevextreme
;
492 int diff
, prevdiff
, extremediff
, nextreme
= 0;
494 if ( !getargs(args
, "(s#i)", &cp
, &len
, &size
) )
496 if ( size
!= 1 && size
!= 2 && size
!= 4 ) {
497 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
500 /* Compute first delta value ahead. Also automatically makes us
501 ** skip the first extreme value
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
;
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.
520 if ( prevextremevalid
) {
521 extremediff
= prevval
- prevextreme
;
522 if ( extremediff
< 0 )
523 extremediff
= -extremediff
;
527 prevextremevalid
= 1;
528 prevextreme
= prevval
;
537 val
= (int)(avg
/ (float)nextreme
);
538 return newintobject(val
);
542 audioop_maxpp(self
, args
)
547 int len
, size
, val
, prevval
, prevextremevalid
= 0, prevextreme
;
550 int diff
, prevdiff
, extremediff
;
552 if ( !getargs(args
, "(s#i)", &cp
, &len
, &size
) )
554 if ( size
!= 1 && size
!= 2 && size
!= 4 ) {
555 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
558 /* Compute first delta value ahead. Also automatically makes us
559 ** skip the first extreme value
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
;
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.
578 if ( prevextremevalid
) {
579 extremediff
= prevval
- prevextreme
;
580 if ( extremediff
< 0 )
581 extremediff
= -extremediff
;
582 if ( extremediff
> max
)
585 prevextremevalid
= 1;
586 prevextreme
= prevval
;
592 return newintobject(max
);
596 audioop_cross(self
, args
)
605 if ( !getargs(args
, "(s#i)", &cp
, &len
, &size
) )
607 if ( size
!= 1 && size
!= 2 && size
!= 4 ) {
608 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
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;
618 if ( val
!= prevval
) ncross
++;
621 return newintobject(ncross
);
625 audioop_mul(self
, args
)
629 signed char *cp
, *ncp
;
631 double factor
, fval
, maxval
;
635 if ( !getargs(args
, "(s#id)", &cp
, &len
, &size
, &factor
) )
638 if ( size
== 1 ) maxval
= (double) 0x7f;
639 else if ( size
== 2 ) maxval
= (double) 0x7fff;
640 else if ( size
== 4 ) maxval
= (double) 0x7fffffff;
642 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
646 rv
= newsizedstringobject(NULL
, len
);
649 ncp
= (signed char *)getstringvalue(rv
);
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
;
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
;
668 audioop_tomono(self
, args
)
672 signed char *cp
, *ncp
;
673 int len
, size
, val1
, val2
;
674 double fac1
, fac2
, fval
, maxval
;
678 if ( !getargs(args
, "(s#idd)", &cp
, &len
, &size
, &fac1
, &fac2
) )
681 if ( size
== 1 ) maxval
= (double) 0x7f;
682 else if ( size
== 2 ) maxval
= (double) 0x7fff;
683 else if ( size
== 4 ) maxval
= (double) 0x7fffffff;
685 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
689 rv
= newsizedstringobject(NULL
, len
/2);
692 ncp
= (signed char *)getstringvalue(rv
);
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
;
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
;
714 audioop_tostereo(self
, args
)
718 signed char *cp
, *ncp
;
719 int len
, size
, val1
, val2
, val
;
720 double fac1
, fac2
, fval
, maxval
;
724 if ( !getargs(args
, "(s#idd)", &cp
, &len
, &size
, &fac1
, &fac2
) )
727 if ( size
== 1 ) maxval
= (double) 0x7f;
728 else if ( size
== 2 ) maxval
= (double) 0x7fff;
729 else if ( size
== 4 ) maxval
= (double) 0x7fffffff;
731 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
735 rv
= newsizedstringobject(NULL
, len
*2);
738 ncp
= (signed char *)getstringvalue(rv
);
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
);
746 fval
= (double)val
*fac1
;
747 if ( fval
> maxval
) fval
= maxval
;
748 else if ( fval
< -maxval
) fval
= -maxval
;
751 fval
= (double)val
*fac2
;
752 if ( fval
> maxval
) fval
= maxval
;
753 else if ( fval
< -maxval
) fval
= -maxval
;
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
;
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
;
768 audioop_add(self
, args
)
772 signed char *cp1
, *cp2
, *ncp
;
773 int len1
, len2
, size
, val1
, val2
;
777 if ( !getargs(args
, "(s#s#i)",
778 &cp1
, &len1
, &cp2
, &len2
, &size
) )
781 if ( len1
!= len2
) {
782 err_setstr(AudioopError
, "Lengths should be the same");
786 if ( size
!= 1 && size
!= 2 && size
!= 4) {
787 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
791 rv
= newsizedstringobject(NULL
, len1
);
794 ncp
= (signed char *)getstringvalue(rv
);
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
);
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
);
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
);
814 audioop_bias(self
, args
)
818 signed char *cp
, *ncp
;
824 if ( !getargs(args
, "(s#ii)",
825 &cp
, &len
, &size
, &bias
) )
828 if ( size
!= 1 && size
!= 2 && size
!= 4) {
829 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
833 rv
= newsizedstringobject(NULL
, len
);
836 ncp
= (signed char *)getstringvalue(rv
);
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
);
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
);
852 audioop_reverse(self
, args
)
862 if ( !getargs(args
, "(s#i)",
866 if ( size
!= 1 && size
!= 2 && size
!= 4 ) {
867 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
871 rv
= newsizedstringobject(NULL
, len
);
874 ncp
= (unsigned char *)getstringvalue(rv
);
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;
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);
891 audioop_lin2lin(self
, args
)
897 int len
, size
, size2
, val
;
901 if ( !getargs(args
, "(s#ii)",
902 &cp
, &len
, &size
, &size2
) )
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");
911 rv
= newsizedstringobject(NULL
, (len
/size
)*size2
);
914 ncp
= (unsigned char *)getstringvalue(rv
);
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;
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);
929 audioop_lin2ulaw(self
, args
)
939 if ( !getargs(args
, "(s#i)",
943 if ( size
!= 1 && size
!= 2 && size
!= 4) {
944 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
948 rv
= newsizedstringobject(NULL
, len
/size
);
951 ncp
= (unsigned char *)getstringvalue(rv
);
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;
958 *ncp
++ = st_linear_to_ulaw(val
);
964 audioop_ulaw2lin(self
, args
)
975 if ( !getargs(args
, "(s#i)",
979 if ( size
!= 1 && size
!= 2 && size
!= 4) {
980 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
984 rv
= newsizedstringobject(NULL
, len
*size
);
987 ncp
= (signed char *)getstringvalue(rv
);
989 for ( i
=0; i
< len
*size
; i
+= size
) {
991 val
= st_ulaw_to_linear(cval
);
993 if ( size
== 1 ) *CHARP(ncp
, i
) = (signed char)(val
>> 8);
994 else if ( size
== 2 ) *SHORTP(ncp
, i
) = (short)(val
);
995 else if ( size
== 4 ) *LONGP(ncp
, i
) = (long)(val
<<16);
1001 audioop_lin2adpcm(self
, args
)
1007 int len
, size
, val
, step
, valpred
, delta
, index
, sign
, vpdiff
, diff
;
1008 object
*rv
, *state
, *str
;
1009 int i
, outputbuffer
, bufferstep
;
1011 if ( !getargs(args
, "(s#iO)",
1012 &cp
, &len
, &size
, &state
) )
1016 if ( size
!= 1 && size
!= 2 && size
!= 4) {
1017 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
1021 str
= newsizedstringobject(NULL
, len
/(size
*2));
1024 ncp
= (signed char *)getstringvalue(str
);
1026 /* Decode state, should have (value, step) */
1027 if ( state
== None
) {
1028 /* First time, it seems. Set defaults */
1032 } else if ( !getargs(state
, "(ii)", &valpred
, &index
) )
1035 step
= stepsizeTable
[index
];
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;
1043 /* Step 1 - compute difference with previous value */
1044 diff
= val
- valpred
;
1045 sign
= (diff
< 0) ? 8 : 0;
1046 if ( sign
) diff
= (-diff
);
1048 /* Step 2 - Divide and clamp */
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.
1058 vpdiff
= (step
>> 3);
1060 if ( diff
>= step
) {
1066 if ( diff
>= step
) {
1072 if ( diff
>= step
) {
1077 /* Step 3 - Update previous value */
1083 /* Step 4 - Clamp previous value to 16 bits */
1084 if ( valpred
> 32767 )
1086 else if ( valpred
< -32768 )
1089 /* Step 5 - Assemble value, update index and step values */
1092 index
+= indexTable
[delta
];
1093 if ( index
< 0 ) index
= 0;
1094 if ( index
> 88 ) index
= 88;
1095 step
= stepsizeTable
[index
];
1097 /* Step 6 - Output value */
1099 outputbuffer
= (delta
<< 4) & 0xf0;
1101 *ncp
++ = (delta
& 0x0f) | outputbuffer
;
1103 bufferstep
= !bufferstep
;
1105 rv
= mkvalue("(O(ii))", str
, valpred
, index
);
1111 audioop_adpcm2lin(self
, args
)
1117 int len
, size
, valpred
, step
, delta
, index
, sign
, vpdiff
;
1118 object
*rv
, *str
, *state
;
1119 int i
, inputbuffer
, bufferstep
;
1121 if ( !getargs(args
, "(s#iO)",
1122 &cp
, &len
, &size
, &state
) )
1125 if ( size
!= 1 && size
!= 2 && size
!= 4) {
1126 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
1130 /* Decode state, should have (value, step) */
1131 if ( state
== None
) {
1132 /* First time, it seems. Set defaults */
1136 } else if ( !getargs(state
, "(ii)", &valpred
, &index
) )
1139 str
= newsizedstringobject(NULL
, len
*size
*2);
1142 ncp
= (signed char *)getstringvalue(str
);
1144 step
= stepsizeTable
[index
];
1147 for ( i
=0; i
< len
*size
*2; i
+= size
) {
1148 /* Step 1 - get the delta value and compute next index */
1150 delta
= inputbuffer
& 0xf;
1152 inputbuffer
= *cp
++;
1153 delta
= (inputbuffer
>> 4) & 0xf;
1156 bufferstep
= !bufferstep
;
1158 /* Step 2 - Find new index value (for later) */
1159 index
+= indexTable
[delta
];
1160 if ( index
< 0 ) index
= 0;
1161 if ( index
> 88 ) index
= 88;
1163 /* Step 3 - Separate sign and magnitude */
1167 /* Step 4 - Compute difference and new predicted value */
1169 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
1173 if ( delta
& 4 ) vpdiff
+= step
;
1174 if ( delta
& 2 ) vpdiff
+= step
>>1;
1175 if ( delta
& 1 ) vpdiff
+= step
>>2;
1182 /* Step 5 - clamp output value */
1183 if ( valpred
> 32767 )
1185 else if ( valpred
< -32768 )
1188 /* Step 6 - Update step value */
1189 step
= stepsizeTable
[index
];
1191 /* Step 6 - Output value */
1192 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);
1197 rv
= mkvalue("(O(ii))", str
, valpred
, index
);
1202 static struct methodlist audioop_methods
[] = {
1203 { "max", audioop_max
},
1204 { "minmax", audioop_minmax
},
1205 { "avg", audioop_avg
},
1206 { "maxpp", audioop_maxpp
},
1207 { "avgpp", audioop_avgpp
},
1208 { "rms", audioop_rms
},
1209 { "findfit", audioop_findfit
},
1210 { "findmax", audioop_findmax
},
1211 { "findfactor", audioop_findfactor
},
1212 { "cross", audioop_cross
},
1213 { "mul", audioop_mul
},
1214 { "add", audioop_add
},
1215 { "bias", audioop_bias
},
1216 { "ulaw2lin", audioop_ulaw2lin
},
1217 { "lin2ulaw", audioop_lin2ulaw
},
1218 { "lin2lin", audioop_lin2lin
},
1219 { "adpcm2lin", audioop_adpcm2lin
},
1220 { "lin2adpcm", audioop_lin2adpcm
},
1221 { "tomono", audioop_tomono
},
1222 { "tostereo", audioop_tostereo
},
1223 { "getsample", audioop_getsample
},
1224 { "reverse", audioop_reverse
},
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");