1 /***********************************************************
2 Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
3 Amsterdam, The Netherlands.
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__) && defined(signed)
31 !ERROR
!; READ THE SOURCE
FILE!;
32 /* This module currently does not work on systems where only unsigned
33 characters are available. Take it out of Setup. Sorry. */
38 /* Code shamelessly stolen from sox,
39 ** (c) Craig Reese, Joe Campbell and Jeff Poskanzer 1989 */
43 #define LINCLIP(x) do { if ( x < MINLIN ) x = MINLIN ; else if ( x > MAXLIN ) x = MAXLIN; } while ( 0 )
45 unsigned char st_linear_to_ulaw( /* int sample */ );
48 ** This macro converts from ulaw to 16 bit linear, faster.
53 ** Input: 8 bit ulaw sample
54 ** Output: signed 16 bit linear sample
56 #define st_ulaw_to_linear(ulawbyte) ulaw_table[ulawbyte]
58 static int ulaw_table
[256] = {
59 -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
60 -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
61 -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
62 -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316,
63 -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
64 -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
65 -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
66 -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
67 -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
68 -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
69 -876, -844, -812, -780, -748, -716, -684, -652,
70 -620, -588, -556, -524, -492, -460, -428, -396,
71 -372, -356, -340, -324, -308, -292, -276, -260,
72 -244, -228, -212, -196, -180, -164, -148, -132,
73 -120, -112, -104, -96, -88, -80, -72, -64,
74 -56, -48, -40, -32, -24, -16, -8, 0,
75 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
76 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
77 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
78 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
79 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
80 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
81 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
82 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
83 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
84 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
85 876, 844, 812, 780, 748, 716, 684, 652,
86 620, 588, 556, 524, 492, 460, 428, 396,
87 372, 356, 340, 324, 308, 292, 276, 260,
88 244, 228, 212, 196, 180, 164, 148, 132,
89 120, 112, 104, 96, 88, 80, 72, 64,
90 56, 48, 40, 32, 24, 16, 8, 0 };
92 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
93 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
97 st_linear_to_ulaw( sample
)
100 static int exp_lut
[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
101 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
102 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
103 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
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 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 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 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 int sign
, exponent
, mantissa
;
117 unsigned char ulawbyte
;
119 /* Get the sample into sign-magnitude. */
120 sign
= (sample
>> 8) & 0x80; /* set aside the sign */
121 if ( sign
!= 0 ) sample
= -sample
; /* get magnitude */
122 if ( sample
> CLIP
) sample
= CLIP
; /* clip the magnitude */
124 /* Convert from 16 bit linear to ulaw. */
125 sample
= sample
+ BIAS
;
126 exponent
= exp_lut
[( sample
>> 7 ) & 0xFF];
127 mantissa
= ( sample
>> ( exponent
+ 3 ) ) & 0x0F;
128 ulawbyte
= ~ ( sign
| ( exponent
<< 4 ) | mantissa
);
130 if ( ulawbyte
== 0 ) ulawbyte
= 0x02; /* optional CCITT trap */
135 /* End of code taken from sox */
137 /* ADPCM-3 step variation table */
138 static float newstep
[5] = { 0.8, 0.9, 1.0, 1.75, 1.75 };
140 /* Intel ADPCM step variation table */
141 static int indexTable
[16] = {
142 -1, -1, -1, -1, 2, 4, 6, 8,
143 -1, -1, -1, -1, 2, 4, 6, 8,
146 static int stepsizeTable
[89] = {
147 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
148 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
149 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
150 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
151 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
152 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
153 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
154 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
155 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
158 #define CHARP(cp, i) ((signed char *)(cp+i))
159 #define SHORTP(cp, i) ((short *)(cp+i))
160 #define LONGP(cp, i) ((long *)(cp+i))
164 static object
*AudioopError
;
167 audioop_getsample(self
, args
)
175 if ( !getargs(args
, "(s#ii)", &cp
, &len
, &size
, &i
) )
177 if ( size
!= 1 && size
!= 2 && size
!= 4 ) {
178 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
181 if ( i
< 0 || i
>= len
/size
) {
182 err_setstr(AudioopError
, "Index out of range");
185 if ( size
== 1 ) val
= (int)*CHARP(cp
, i
);
186 else if ( size
== 2 ) val
= (int)*SHORTP(cp
, i
*2);
187 else if ( size
== 4 ) val
= (int)*LONGP(cp
, i
*4);
188 return newintobject(val
);
192 audioop_max(self
, args
)
201 if ( !getargs(args
, "(s#i)", &cp
, &len
, &size
) )
203 if ( size
!= 1 && size
!= 2 && size
!= 4 ) {
204 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
207 for ( i
=0; i
<len
; i
+= size
) {
208 if ( size
== 1 ) val
= (int)*CHARP(cp
, i
);
209 else if ( size
== 2 ) val
= (int)*SHORTP(cp
, i
);
210 else if ( size
== 4 ) val
= (int)*LONGP(cp
, i
);
211 if ( val
< 0 ) val
= (-val
);
212 if ( val
> max
) max
= val
;
214 return newintobject(max
);
218 audioop_avg(self
, args
)
227 if ( !getargs(args
, "(s#i)", &cp
, &len
, &size
) )
229 if ( size
!= 1 && size
!= 2 && size
!= 4 ) {
230 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
233 for ( i
=0; i
<len
; i
+= size
) {
234 if ( size
== 1 ) val
= (int)*CHARP(cp
, i
);
235 else if ( size
== 2 ) val
= (int)*SHORTP(cp
, i
);
236 else if ( size
== 4 ) val
= (int)*LONGP(cp
, i
);
242 val
= (int)(avg
/ (float)(len
/size
));
243 return newintobject(val
);
247 audioop_rms(self
, args
)
254 float sum_squares
= 0.0;
256 if ( !getargs(args
, "(s#i)", &cp
, &len
, &size
) )
258 if ( size
!= 1 && size
!= 2 && size
!= 4 ) {
259 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
262 for ( i
=0; i
<len
; i
+= size
) {
263 if ( size
== 1 ) val
= (int)*CHARP(cp
, i
);
264 else if ( size
== 2 ) val
= (int)*SHORTP(cp
, i
);
265 else if ( size
== 4 ) val
= (int)*LONGP(cp
, i
);
266 sum_squares
+= (float)val
*(float)val
;
271 val
= (int)sqrt(sum_squares
/ (float)(len
/size
));
272 return newintobject(val
);
275 double _sum2(a
, b
, len
)
283 for( i
=0; i
<len
; i
++) {
284 sum
= sum
+ (double)a
[i
]*(double)b
[i
];
290 ** Findfit tries to locate a sample within another sample. Its main use
291 ** is in echo-cancellation (to find the feedback of the output signal in
292 ** the input signal).
293 ** The method used is as follows:
295 ** let R be the reference signal (length n) and A the input signal (length N)
296 ** with N > n, and let all sums be over i from 0 to n-1.
298 ** Now, for each j in {0..N-n} we compute a factor fj so that -fj*R matches A
299 ** as good as possible, i.e. sum( (A[j+i]+fj*R[i])^2 ) is minimal. This
300 ** equation gives fj = sum( A[j+i]R[i] ) / sum(R[i]^2).
302 ** Next, we compute the relative distance between the original signal and
303 ** the modified signal and minimize that over j:
304 ** vj = sum( (A[j+i]-fj*R[i])^2 ) / sum( A[j+i]^2 ) =>
305 ** vj = ( sum(A[j+i]^2)*sum(R[i]^2) - sum(A[j+i]R[i])^2 ) / sum( A[j+i]^2 )
307 ** In the code variables correspond as follows:
314 ** sum_ri_2 sum(R[i]^2)
315 ** sum_aij_2 sum(A[i+j]^2)
316 ** sum_aij_ri sum(A[i+j]R[i])
318 ** sum_ri is calculated once, sum_aij_2 is updated each step and sum_aij_ri
319 ** is completely recalculated each step.
322 audioop_findfit(self
, args
)
329 double aj_m1
, aj_lm1
;
330 double sum_ri_2
, sum_aij_2
, sum_aij_ri
, result
, best_result
, factor
;
332 if ( !getargs(args
, "(s#s#)", &cp1
, &len1
, &cp2
, &len2
) )
334 if ( len1
& 1 || len2
& 1 ) {
335 err_setstr(AudioopError
, "Strings should be even-sized");
342 err_setstr(AudioopError
, "First sample should be longer");
345 sum_ri_2
= _sum2(cp2
, cp2
, len2
);
346 sum_aij_2
= _sum2(cp1
, cp1
, len2
);
347 sum_aij_ri
= _sum2(cp1
, cp2
, len2
);
349 result
= (sum_ri_2
*sum_aij_2
- sum_aij_ri
*sum_aij_ri
) / sum_aij_2
;
351 best_result
= result
;
355 for ( j
=1; j
<=len1
-len2
; j
++) {
356 aj_m1
= (double)cp1
[j
-1];
357 aj_lm1
= (double)cp1
[j
+len2
-1];
359 sum_aij_2
= sum_aij_2
+ aj_lm1
*aj_lm1
- aj_m1
*aj_m1
;
360 sum_aij_ri
= _sum2(cp1
+j
, cp2
, len2
);
362 result
= (sum_ri_2
*sum_aij_2
- sum_aij_ri
*sum_aij_ri
) / sum_aij_2
;
364 if ( result
< best_result
) {
365 best_result
= result
;
371 factor
= _sum2(cp1
+best_j
, cp2
, len2
) / sum_ri_2
;
373 return mkvalue("(if)", best_j
, factor
);
377 ** findfactor finds a factor f so that the energy in A-fB is minimal.
378 ** See the comment for findfit for details.
381 audioop_findfactor(self
, args
)
387 double sum_ri_2
, sum_aij_ri
, result
;
389 if ( !getargs(args
, "(s#s#)", &cp1
, &len1
, &cp2
, &len2
) )
391 if ( len1
& 1 || len2
& 1 ) {
392 err_setstr(AudioopError
, "Strings should be even-sized");
395 if ( len1
!= len2
) {
396 err_setstr(AudioopError
, "Samples should be same size");
400 sum_ri_2
= _sum2(cp2
, cp2
, len2
);
401 sum_aij_ri
= _sum2(cp1
, cp2
, len2
);
403 result
= sum_aij_ri
/ sum_ri_2
;
405 return newfloatobject(result
);
409 ** findmax returns the index of the n-sized segment of the input sample
410 ** that contains the most energy.
413 audioop_findmax(self
, args
)
420 double aj_m1
, aj_lm1
;
421 double result
, best_result
;
423 if ( !getargs(args
, "(s#i)", &cp1
, &len1
, &len2
) )
426 err_setstr(AudioopError
, "Strings should be even-sized");
432 err_setstr(AudioopError
, "Input sample should be longer");
436 result
= _sum2(cp1
, cp1
, len2
);
438 best_result
= result
;
442 for ( j
=1; j
<=len1
-len2
; j
++) {
443 aj_m1
= (double)cp1
[j
-1];
444 aj_lm1
= (double)cp1
[j
+len2
-1];
446 result
= result
+ aj_lm1
*aj_lm1
- aj_m1
*aj_m1
;
448 if ( result
> best_result
) {
449 best_result
= result
;
455 return newintobject(best_j
);
459 audioop_avgpp(self
, args
)
464 int len
, size
, val
, prevval
, prevextremevalid
= 0, prevextreme
;
467 int diff
, prevdiff
, extremediff
, nextreme
= 0;
469 if ( !getargs(args
, "(s#i)", &cp
, &len
, &size
) )
471 if ( size
!= 1 && size
!= 2 && size
!= 4 ) {
472 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
475 /* Compute first delta value ahead. Also automatically makes us
476 ** skip the first extreme value
478 if ( size
== 1 ) prevval
= (int)*CHARP(cp
, 0);
479 else if ( size
== 2 ) prevval
= (int)*SHORTP(cp
, 0);
480 else if ( size
== 4 ) prevval
= (int)*LONGP(cp
, 0);
481 if ( size
== 1 ) val
= (int)*CHARP(cp
, size
);
482 else if ( size
== 2 ) val
= (int)*SHORTP(cp
, size
);
483 else if ( size
== 4 ) val
= (int)*LONGP(cp
, size
);
484 prevdiff
= val
- prevval
;
486 for ( i
=size
; i
<len
; i
+= size
) {
487 if ( size
== 1 ) val
= (int)*CHARP(cp
, i
);
488 else if ( size
== 2 ) val
= (int)*SHORTP(cp
, i
);
489 else if ( size
== 4 ) val
= (int)*LONGP(cp
, i
);
490 diff
= val
- prevval
;
491 if ( diff
*prevdiff
< 0 ) {
492 /* Derivative changed sign. Compute difference to last extreme
493 ** value and remember.
495 if ( prevextremevalid
) {
496 extremediff
= prevval
- prevextreme
;
497 if ( extremediff
< 0 )
498 extremediff
= -extremediff
;
502 prevextremevalid
= 1;
503 prevextreme
= prevval
;
512 val
= (int)(avg
/ (float)nextreme
);
513 return newintobject(val
);
517 audioop_maxpp(self
, args
)
522 int len
, size
, val
, prevval
, prevextremevalid
= 0, prevextreme
;
525 int diff
, prevdiff
, extremediff
;
527 if ( !getargs(args
, "(s#i)", &cp
, &len
, &size
) )
529 if ( size
!= 1 && size
!= 2 && size
!= 4 ) {
530 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
533 /* Compute first delta value ahead. Also automatically makes us
534 ** skip the first extreme value
536 if ( size
== 1 ) prevval
= (int)*CHARP(cp
, 0);
537 else if ( size
== 2 ) prevval
= (int)*SHORTP(cp
, 0);
538 else if ( size
== 4 ) prevval
= (int)*LONGP(cp
, 0);
539 if ( size
== 1 ) val
= (int)*CHARP(cp
, size
);
540 else if ( size
== 2 ) val
= (int)*SHORTP(cp
, size
);
541 else if ( size
== 4 ) val
= (int)*LONGP(cp
, size
);
542 prevdiff
= val
- prevval
;
544 for ( i
=size
; i
<len
; i
+= size
) {
545 if ( size
== 1 ) val
= (int)*CHARP(cp
, i
);
546 else if ( size
== 2 ) val
= (int)*SHORTP(cp
, i
);
547 else if ( size
== 4 ) val
= (int)*LONGP(cp
, i
);
548 diff
= val
- prevval
;
549 if ( diff
*prevdiff
< 0 ) {
550 /* Derivative changed sign. Compute difference to last extreme
551 ** value and remember.
553 if ( prevextremevalid
) {
554 extremediff
= prevval
- prevextreme
;
555 if ( extremediff
< 0 )
556 extremediff
= -extremediff
;
557 if ( extremediff
> max
)
560 prevextremevalid
= 1;
561 prevextreme
= prevval
;
567 return newintobject(max
);
571 audioop_cross(self
, args
)
578 int cross
, prevval
, ncross
;
580 if ( !getargs(args
, "(s#i)", &cp
, &len
, &size
) )
582 if ( size
!= 1 && size
!= 2 && size
!= 4 ) {
583 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
587 prevval
= 17; /* Anything <> 0,1 */
588 for ( i
=0; i
<len
; i
+= size
) {
589 if ( size
== 1 ) val
= ((int)*CHARP(cp
, i
)) >> 7;
590 else if ( size
== 2 ) val
= ((int)*SHORTP(cp
, i
)) >> 15;
591 else if ( size
== 4 ) val
= ((int)*LONGP(cp
, i
)) >> 31;
593 if ( val
!= prevval
) ncross
++;
596 return newintobject(ncross
);
600 audioop_mul(self
, args
)
604 signed char *cp
, *ncp
;
606 double factor
, fval
, maxval
;
610 if ( !getargs(args
, "(s#id)", &cp
, &len
, &size
, &factor
) )
613 if ( size
== 1 ) maxval
= (double) 0x7f;
614 else if ( size
== 2 ) maxval
= (double) 0x7fff;
615 else if ( size
== 4 ) maxval
= (double) 0x7fffffff;
617 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
621 rv
= newsizedstringobject(NULL
, len
);
624 ncp
= (signed char *)getstringvalue(rv
);
627 for ( i
=0; i
< len
; i
+= size
) {
628 if ( size
== 1 ) val
= (int)*CHARP(cp
, i
);
629 else if ( size
== 2 ) val
= (int)*SHORTP(cp
, i
);
630 else if ( size
== 4 ) val
= (int)*LONGP(cp
, i
);
631 fval
= (double)val
*factor
;
632 if ( fval
> maxval
) fval
= maxval
;
633 else if ( fval
< -maxval
) fval
= -maxval
;
635 if ( size
== 1 ) *CHARP(ncp
, i
) = (signed char)val
;
636 else if ( size
== 2 ) *SHORTP(ncp
, i
) = (short)val
;
637 else if ( size
== 4 ) *LONGP(ncp
, i
) = (long)val
;
643 audioop_tomono(self
, args
)
647 signed char *cp
, *ncp
;
648 int len
, size
, val1
, val2
;
649 double fac1
, fac2
, fval
, maxval
;
653 if ( !getargs(args
, "(s#idd)", &cp
, &len
, &size
, &fac1
, &fac2
) )
656 if ( size
== 1 ) maxval
= (double) 0x7f;
657 else if ( size
== 2 ) maxval
= (double) 0x7fff;
658 else if ( size
== 4 ) maxval
= (double) 0x7fffffff;
660 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
664 rv
= newsizedstringobject(NULL
, len
/2);
667 ncp
= (signed char *)getstringvalue(rv
);
670 for ( i
=0; i
< len
; i
+= size
*2 ) {
671 if ( size
== 1 ) val1
= (int)*CHARP(cp
, i
);
672 else if ( size
== 2 ) val1
= (int)*SHORTP(cp
, i
);
673 else if ( size
== 4 ) val1
= (int)*LONGP(cp
, i
);
674 if ( size
== 1 ) val2
= (int)*CHARP(cp
, i
+1);
675 else if ( size
== 2 ) val2
= (int)*SHORTP(cp
, i
+2);
676 else if ( size
== 4 ) val2
= (int)*LONGP(cp
, i
+4);
677 fval
= (double)val1
*fac1
+ (double)val2
*fac2
;
678 if ( fval
> maxval
) fval
= maxval
;
679 else if ( fval
< -maxval
) fval
= -maxval
;
681 if ( size
== 1 ) *CHARP(ncp
, i
/2) = (signed char)val1
;
682 else if ( size
== 2 ) *SHORTP(ncp
, i
/2) = (short)val1
;
683 else if ( size
== 4 ) *LONGP(ncp
, i
/2)= (long)val1
;
689 audioop_tostereo(self
, args
)
693 signed char *cp
, *ncp
;
694 int len
, size
, val1
, val2
, val
;
695 double fac1
, fac2
, fval
, maxval
;
699 if ( !getargs(args
, "(s#idd)", &cp
, &len
, &size
, &fac1
, &fac2
) )
702 if ( size
== 1 ) maxval
= (double) 0x7f;
703 else if ( size
== 2 ) maxval
= (double) 0x7fff;
704 else if ( size
== 4 ) maxval
= (double) 0x7fffffff;
706 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
710 rv
= newsizedstringobject(NULL
, len
*2);
713 ncp
= (signed char *)getstringvalue(rv
);
716 for ( i
=0; i
< len
; i
+= size
) {
717 if ( size
== 1 ) val
= (int)*CHARP(cp
, i
);
718 else if ( size
== 2 ) val
= (int)*SHORTP(cp
, i
);
719 else if ( size
== 4 ) val
= (int)*LONGP(cp
, i
);
721 fval
= (double)val
*fac1
;
722 if ( fval
> maxval
) fval
= maxval
;
723 else if ( fval
< -maxval
) fval
= -maxval
;
726 fval
= (double)val
*fac2
;
727 if ( fval
> maxval
) fval
= maxval
;
728 else if ( fval
< -maxval
) fval
= -maxval
;
731 if ( size
== 1 ) *CHARP(ncp
, i
*2) = (signed char)val1
;
732 else if ( size
== 2 ) *SHORTP(ncp
, i
*2) = (short)val1
;
733 else if ( size
== 4 ) *LONGP(ncp
, i
*2) = (long)val1
;
735 if ( size
== 1 ) *CHARP(ncp
, i
*2+1) = (signed char)val2
;
736 else if ( size
== 2 ) *SHORTP(ncp
, i
*2+2) = (short)val2
;
737 else if ( size
== 4 ) *LONGP(ncp
, i
*2+4) = (long)val2
;
743 audioop_add(self
, args
)
747 signed char *cp1
, *cp2
, *ncp
;
748 int len1
, len2
, size
, val1
, val2
;
752 if ( !getargs(args
, "(s#s#i)",
753 &cp1
, &len1
, &cp2
, &len2
, &size
) )
756 if ( len1
!= len2
) {
757 err_setstr(AudioopError
, "Lengths should be the same");
761 if ( size
!= 1 && size
!= 2 && size
!= 4) {
762 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
766 rv
= newsizedstringobject(NULL
, len1
);
769 ncp
= (signed char *)getstringvalue(rv
);
772 for ( i
=0; i
< len1
; i
+= size
) {
773 if ( size
== 1 ) val1
= (int)*CHARP(cp1
, i
);
774 else if ( size
== 2 ) val1
= (int)*SHORTP(cp1
, i
);
775 else if ( size
== 4 ) val1
= (int)*LONGP(cp1
, i
);
777 if ( size
== 1 ) val2
= (int)*CHARP(cp2
, i
);
778 else if ( size
== 2 ) val2
= (int)*SHORTP(cp2
, i
);
779 else if ( size
== 4 ) val2
= (int)*LONGP(cp2
, i
);
781 if ( size
== 1 ) *CHARP(ncp
, i
) = (signed char)(val1
+val2
);
782 else if ( size
== 2 ) *SHORTP(ncp
, i
) = (short)(val1
+val2
);
783 else if ( size
== 4 ) *LONGP(ncp
, i
) = (long)(val1
+val2
);
789 audioop_bias(self
, args
)
793 signed char *cp
, *ncp
;
799 if ( !getargs(args
, "(s#ii)",
800 &cp
, &len
, &size
, &bias
) )
803 if ( size
!= 1 && size
!= 2 && size
!= 4) {
804 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
808 rv
= newsizedstringobject(NULL
, len
);
811 ncp
= (signed char *)getstringvalue(rv
);
814 for ( i
=0; i
< len
; i
+= size
) {
815 if ( size
== 1 ) val
= (int)*CHARP(cp
, i
);
816 else if ( size
== 2 ) val
= (int)*SHORTP(cp
, i
);
817 else if ( size
== 4 ) val
= (int)*LONGP(cp
, i
);
819 if ( size
== 1 ) *CHARP(ncp
, i
) = (signed char)(val
+bias
);
820 else if ( size
== 2 ) *SHORTP(ncp
, i
) = (short)(val
+bias
);
821 else if ( size
== 4 ) *LONGP(ncp
, i
) = (long)(val
+bias
);
827 audioop_reverse(self
, args
)
837 if ( !getargs(args
, "(s#i)",
841 if ( size
!= 1 && size
!= 2 && size
!= 4 ) {
842 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
846 rv
= newsizedstringobject(NULL
, len
);
849 ncp
= (unsigned char *)getstringvalue(rv
);
851 for ( i
=0; i
< len
; i
+= size
) {
852 if ( size
== 1 ) val
= ((int)*CHARP(cp
, i
)) << 8;
853 else if ( size
== 2 ) val
= (int)*SHORTP(cp
, i
);
854 else if ( size
== 4 ) val
= ((int)*LONGP(cp
, i
)) >> 16;
858 if ( size
== 1 ) *CHARP(ncp
, j
) = (signed char)(val
>> 8);
859 else if ( size
== 2 ) *SHORTP(ncp
, j
) = (short)(val
);
860 else if ( size
== 4 ) *LONGP(ncp
, j
) = (long)(val
<<16);
866 audioop_lin2lin(self
, args
)
872 int len
, size
, size2
, val
;
876 if ( !getargs(args
, "(s#ii)",
877 &cp
, &len
, &size
, &size2
) )
880 if ( (size
!= 1 && size
!= 2 && size
!= 4) ||
881 (size2
!= 1 && size2
!= 2 && size2
!= 4)) {
882 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
886 rv
= newsizedstringobject(NULL
, (len
/size
)*size2
);
889 ncp
= (unsigned char *)getstringvalue(rv
);
891 for ( i
=0, j
=0; i
< len
; i
+= size
, j
+= size2
) {
892 if ( size
== 1 ) val
= ((int)*CHARP(cp
, i
)) << 8;
893 else if ( size
== 2 ) val
= (int)*SHORTP(cp
, i
);
894 else if ( size
== 4 ) val
= ((int)*LONGP(cp
, i
)) >> 16;
896 if ( size2
== 1 ) *CHARP(ncp
, j
) = (signed char)(val
>> 8);
897 else if ( size2
== 2 ) *SHORTP(ncp
, j
) = (short)(val
);
898 else if ( size2
== 4 ) *LONGP(ncp
, j
) = (long)(val
<<16);
904 audioop_lin2ulaw(self
, args
)
914 if ( !getargs(args
, "(s#i)",
918 if ( size
!= 1 && size
!= 2 && size
!= 4) {
919 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
923 rv
= newsizedstringobject(NULL
, len
/size
);
926 ncp
= (unsigned char *)getstringvalue(rv
);
928 for ( i
=0; i
< len
; i
+= size
) {
929 if ( size
== 1 ) val
= ((int)*CHARP(cp
, i
)) << 8;
930 else if ( size
== 2 ) val
= (int)*SHORTP(cp
, i
);
931 else if ( size
== 4 ) val
= ((int)*LONGP(cp
, i
)) >> 16;
933 *ncp
++ = st_linear_to_ulaw(val
);
939 audioop_ulaw2lin(self
, args
)
950 if ( !getargs(args
, "(s#i)",
954 if ( size
!= 1 && size
!= 2 && size
!= 4) {
955 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
959 rv
= newsizedstringobject(NULL
, len
*size
);
962 ncp
= (signed char *)getstringvalue(rv
);
964 for ( i
=0; i
< len
*size
; i
+= size
) {
966 val
= st_ulaw_to_linear(cval
);
968 if ( size
== 1 ) *CHARP(ncp
, i
) = (signed char)(val
>> 8);
969 else if ( size
== 2 ) *SHORTP(ncp
, i
) = (short)(val
);
970 else if ( size
== 4 ) *LONGP(ncp
, i
) = (long)(val
<<16);
976 audioop_lin2adpcm(self
, args
)
982 int len
, size
, val
, step
, valpred
, delta
, index
, sign
, vpdiff
, diff
;
983 object
*rv
, *state
, *str
;
984 int i
, outputbuffer
, bufferstep
;
986 if ( !getargs(args
, "(s#iO)",
987 &cp
, &len
, &size
, &state
) )
991 if ( size
!= 1 && size
!= 2 && size
!= 4) {
992 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
996 str
= newsizedstringobject(NULL
, len
/(size
*2));
999 ncp
= (signed char *)getstringvalue(str
);
1001 /* Decode state, should have (value, step) */
1002 if ( state
== None
) {
1003 /* First time, it seems. Set defaults */
1007 } else if ( !getargs(state
, "(ii)", &valpred
, &index
) )
1010 step
= stepsizeTable
[index
];
1013 for ( i
=0; i
< len
; i
+= size
) {
1014 if ( size
== 1 ) val
= ((int)*CHARP(cp
, i
)) << 8;
1015 else if ( size
== 2 ) val
= (int)*SHORTP(cp
, i
);
1016 else if ( size
== 4 ) val
= ((int)*LONGP(cp
, i
)) >> 16;
1018 /* Step 1 - compute difference with previous value */
1019 diff
= val
- valpred
;
1020 sign
= (diff
< 0) ? 8 : 0;
1021 if ( sign
) diff
= (-diff
);
1023 /* Step 2 - Divide and clamp */
1025 ** This code *approximately* computes:
1026 ** delta = diff*4/step;
1027 ** vpdiff = (delta+0.5)*step/4;
1028 ** but in shift step bits are dropped. The net result of this is
1029 ** that even if you have fast mul/div hardware you cannot put it to
1030 ** good use since the fixup would be too expensive.
1033 vpdiff
= (step
>> 3);
1035 if ( diff
>= step
) {
1041 if ( diff
>= step
) {
1047 if ( diff
>= step
) {
1052 /* Step 3 - Update previous value */
1058 /* Step 4 - Clamp previous value to 16 bits */
1059 if ( valpred
> 32767 )
1061 else if ( valpred
< -32768 )
1064 /* Step 5 - Assemble value, update index and step values */
1067 index
+= indexTable
[delta
];
1068 if ( index
< 0 ) index
= 0;
1069 if ( index
> 88 ) index
= 88;
1070 step
= stepsizeTable
[index
];
1072 /* Step 6 - Output value */
1074 outputbuffer
= (delta
<< 4) & 0xf0;
1076 *ncp
++ = (delta
& 0x0f) | outputbuffer
;
1078 bufferstep
= !bufferstep
;
1080 rv
= mkvalue("(O(ii))", str
, valpred
, index
);
1086 audioop_adpcm2lin(self
, args
)
1092 int len
, size
, val
, valpred
, step
, delta
, index
, sign
, vpdiff
;
1093 object
*rv
, *str
, *state
;
1094 int i
, inputbuffer
, bufferstep
;
1096 if ( !getargs(args
, "(s#iO)",
1097 &cp
, &len
, &size
, &state
) )
1100 if ( size
!= 1 && size
!= 2 && size
!= 4) {
1101 err_setstr(AudioopError
, "Size should be 1, 2 or 4");
1105 /* Decode state, should have (value, step) */
1106 if ( state
== None
) {
1107 /* First time, it seems. Set defaults */
1111 } else if ( !getargs(state
, "(ii)", &valpred
, &index
) )
1114 str
= newsizedstringobject(NULL
, len
*size
*2);
1117 ncp
= (signed char *)getstringvalue(str
);
1119 step
= stepsizeTable
[index
];
1122 for ( i
=0; i
< len
*size
*2; i
+= size
) {
1123 /* Step 1 - get the delta value and compute next index */
1125 delta
= inputbuffer
& 0xf;
1127 inputbuffer
= *cp
++;
1128 delta
= (inputbuffer
>> 4) & 0xf;
1131 bufferstep
= !bufferstep
;
1133 /* Step 2 - Find new index value (for later) */
1134 index
+= indexTable
[delta
];
1135 if ( index
< 0 ) index
= 0;
1136 if ( index
> 88 ) index
= 88;
1138 /* Step 3 - Separate sign and magnitude */
1142 /* Step 4 - Compute difference and new predicted value */
1144 ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
1148 if ( delta
& 4 ) vpdiff
+= step
;
1149 if ( delta
& 2 ) vpdiff
+= step
>>1;
1150 if ( delta
& 1 ) vpdiff
+= step
>>2;
1157 /* Step 5 - clamp output value */
1158 if ( valpred
> 32767 )
1160 else if ( valpred
< -32768 )
1163 /* Step 6 - Update step value */
1164 step
= stepsizeTable
[index
];
1166 /* Step 6 - Output value */
1167 if ( size
== 1 ) *CHARP(ncp
, i
) = (signed char)(valpred
>> 8);
1168 else if ( size
== 2 ) *SHORTP(ncp
, i
) = (short)(valpred
);
1169 else if ( size
== 4 ) *LONGP(ncp
, i
) = (long)(valpred
<<16);
1172 rv
= mkvalue("(O(ii))", str
, valpred
, index
);
1177 static struct methodlist audioop_methods
[] = {
1178 { "max", audioop_max
},
1179 { "avg", audioop_avg
},
1180 { "maxpp", audioop_maxpp
},
1181 { "avgpp", audioop_avgpp
},
1182 { "rms", audioop_rms
},
1183 { "findfit", audioop_findfit
},
1184 { "findmax", audioop_findmax
},
1185 { "findfactor", audioop_findfactor
},
1186 { "cross", audioop_cross
},
1187 { "mul", audioop_mul
},
1188 { "add", audioop_add
},
1189 { "bias", audioop_bias
},
1190 { "ulaw2lin", audioop_ulaw2lin
},
1191 { "lin2ulaw", audioop_lin2ulaw
},
1192 { "lin2lin", audioop_lin2lin
},
1193 { "adpcm2lin", audioop_adpcm2lin
},
1194 { "lin2adpcm", audioop_lin2adpcm
},
1195 { "tomono", audioop_tomono
},
1196 { "tostereo", audioop_tostereo
},
1197 { "getsample", audioop_getsample
},
1198 { "reverse", audioop_reverse
},
1207 m
= initmodule("audioop", audioop_methods
);
1208 d
= getmoduledict(m
);
1209 AudioopError
= newstringobject("audioop.error");
1210 if ( AudioopError
== NULL
|| dictinsert(d
,"error",AudioopError
) )
1211 fatal("can't define audioop.error");