supernova: fix for small audio vector sizes
[supercollider.git] / lang / LangSource / PyrSignal.cpp
blob85b2685b11e84d1d95a0fd70a6a9e06fc234a71b
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 compound formulas :
23 amclip out = B<=0 ? 0 : A*B; // two quadrant amplitude modulation
24 ring1 out = A*(B+1) = A*B + A; // amplitude modulation of a by b.
25 ring2 out = A*B + A + B; // ring modulation plus both original signals
26 ring3 out = A*A*B; // ring modulation variant
27 ring4 out = A*A*B - A*B*B; // ring modulation variant
28 difsqr out = A*A - B*B; // difference of squares
29 sumsqr out = A*A + B*B; // sum of squares
30 sqrdif out = (A - B)^2 // square of the difference = a^2 + b^2 - 2ab
31 sqrsum out = (A + B)^2 // square of the sum = a^2 + b^2 + 2ab
34 #include <math.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include "PyrSignal.h"
38 #include "PyrKernel.h"
39 #include "SC_InlineUnaryOp.h"
40 #include "SC_InlineBinaryOp.h"
41 #include "SCBase.h"
42 #include "InitAlloc.h"
44 //double log2 ( double x );
45 //double hypot ( double x, double y );
47 float gSlopeFactor[32];
48 long gWrapMask[32];
50 float *sineCycle;
51 float *invSineCycle;
52 float *pmSineCycle;
53 float *gFracTable;
55 double phaseToSineIndex;
56 double sineIndexToPhase;
58 void signal_init_globs()
60 int i;
61 double phaseoffset, d, pmf;
62 long sz, sz2;
64 /* setup slopes and wrap masks */
65 for (i=0; i<32; ++i) {
66 long length = 1L<<i;
67 gSlopeFactor[i] = 1./length;
68 gWrapMask[i] = length - 1;
71 /* fill sine wave */
72 // pyrmalloc:
73 // lifetime: forever. initialized at startup.
74 sineCycle = (float*)pyr_pool_runtime->Alloc((SINESIZE+1) * sizeof(float));
75 MEMFAIL(sineCycle);
76 invSineCycle = (float*)pyr_pool_runtime->Alloc((SINESIZE+1) * sizeof(float));
77 MEMFAIL(invSineCycle);
78 pmSineCycle = (float*)pyr_pool_runtime->Alloc((SINESIZE+1) * sizeof(float));
79 MEMFAIL(pmSineCycle);
80 //gFracTable = (float*)pyr_pool_runtime->Alloc(FRACTABLESIZE * sizeof(float));
81 //MEMFAIL(gFracTable);
83 sineIndexToPhase = 2. * 3.1415926535897932384626433832795 / SINESIZE;
84 phaseToSineIndex = 1. / sineIndexToPhase;
85 phaseoffset = sineIndexToPhase * 0.5;
86 pmf = (1L << 29) / twopi;
87 for (i=0; i<=SINESIZE; ++i) {
88 double phase;
89 phase = i * sineIndexToPhase;
90 sineCycle[i] = d = sin(phase);
91 invSineCycle[i] = 1. / d;
92 pmSineCycle[i] = d * pmf;
94 // fix 1/0 values to a special large number
95 invSineCycle[0] = invSineCycle[SINESIZE/2] = invSineCycle[SINESIZE] = VERY_BIG_FLOAT;
96 sz = SINESIZE;
97 sz2 = sz>>1;
98 for (i=1; i<=8; ++i) {
99 //for (i=1; i<=0; ++i) { //ie. none
100 //postfl("%d %f %f\n", i, invSineCycle[i], sineCycle[i]);
101 invSineCycle[i] = invSineCycle[sz-i] = VERY_BIG_FLOAT;
102 invSineCycle[sz2-i] = invSineCycle[sz2+i] = VERY_BIG_FLOAT;
104 /*fracscale = 1./FRACTABLESIZE;
105 for (i=0; i<FRACTABLESIZE; ++i) {
106 gFracTable[i] = (double)i * fracscale;
110 PyrObject* newPyrSignal(VMGlobals *g, long size)
112 PyrObject *signal;
113 long numbytes = size * sizeof(float);
114 signal = (PyrObject*)g->gc->New(numbytes, 0, obj_float, true);
115 if (signal) {
116 signal->classptr = class_signal;
117 signal->size = size;
119 // note: signal is filled with garbage
120 return signal;
123 /*PyrObject* newPyrSignalFrom(VMGlobals *g, PyrObject* inSignal, long size)
125 PyrObject *signal;
126 double *pslot, *qslot, *endptr;
127 long set, m, mmax;
128 long numbytes = size * sizeof(float);
129 signal = (PyrObject*)g->gc->New(numbytes, 0, obj_float, true);
130 signal->classptr = inSignal->classptr;
131 signal->size = size;
132 return signal;
136 PyrObject* signal_fill(PyrObject *outSignal, float inValue)
138 float *out = (float*)(outSignal->slots) - 1;
139 UNROLL_CODE(outSignal->size, out, *++out = inValue;);
140 return outSignal;
143 PyrObject* signal_scale(PyrObject *outSignal, float inValue)
145 if (inValue != 1.f) {
146 float *out = (float*)(outSignal->slots) - 1;
147 UNROLL_CODE(outSignal->size, out, *++out *= inValue;)
149 return outSignal;
152 PyrObject* signal_offset(PyrObject *outSignal, float inValue)
154 if (inValue != 0.f) {
155 float *out = (float*)(outSignal->slots) - 1;
156 UNROLL_CODE(outSignal->size, out, *++out += inValue;)
158 return outSignal;
161 PyrObject* signal_add_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
163 BINOP_LOOP1(+);
166 PyrObject* signal_mul_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
168 BINOP_LOOP1(*);
171 PyrObject* signal_sub_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
173 BINOP_LOOP2(
174 *++c = *++a - *++b;
178 PyrObject* signal_ring1_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
180 BINOP_LOOP2(
181 ++a; *++c = *a * *++b + *a;
185 PyrObject* signal_ring2_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
187 BINOP_LOOP2(
188 ++a; ++b; *++c = *a * *b + *a + *b;
192 PyrObject* signal_ring3_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
194 BINOP_LOOP2(
195 ++a; *++c = *a * *a * *++b;
199 PyrObject* signal_ring4_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
201 BINOP_LOOP2(
202 ++a; ++b; *++c = *a * *a * *b - *a * *b * *b;
206 PyrObject* signal_thresh_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
208 BINOP_LOOP2(
209 ++a; ++b; *++c = *a < *b ? 0.f : *a;
213 PyrObject* signal_amclip_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
215 BINOP_LOOP2(
216 ++a; ++b; *++c = *b <= 0.f ? 0.f : *a * *b;
220 PyrObject* signal_div_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
222 BINOP_LOOP2(
223 *++c = *++a / *++b;
227 PyrObject* signal_difsqr_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
229 BINOP_LOOP2(
230 ++a; ++b; *c = *a * *a - *b * *b;
234 PyrObject* signal_sumsqr_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
236 BINOP_LOOP2(
237 ++a; ++b; *c = *a * *a + *b * *b;
241 PyrObject* signal_sqrsum_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
243 float z;
244 BINOP_LOOP2(
245 z = *++a + *++b; *++c = z * z;
249 PyrObject* signal_sqrdif_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
251 float z;
252 BINOP_LOOP2(
253 z = *++a - *++b; *++c = z * z;
257 PyrObject* signal_absdif_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
259 BINOP_LOOP2(
260 *++c = fabs(*++a - *++b);
264 PyrObject* signal_add_xf(VMGlobals *g, PyrObject* ina, float inb)
266 PyrObject *outc = newPyrSignal(g, ina->size);
267 if (inb == 0.f) {
268 float *a = (float*)(ina->slots);
269 memcpy((float*)(outc->slots), a, ina->size * sizeof(float));
270 } else {
271 float *a = (float*)(ina->slots) - 1;
272 float *c = (float*)(outc->slots) - 1;
273 UNROLL_CODE(outc->size, c, *++c = *++a + inb;)
275 return outc;
278 PyrObject* signal_sub_xf(VMGlobals *g, PyrObject* ina, float inb)
280 PyrObject *outc = newPyrSignal(g, ina->size);
281 if (inb == 0.f) {
282 float *a = (float*)(ina->slots);
283 memcpy((float*)(outc->slots), a, ina->size * sizeof(float));
284 } else {
285 float *a = (float*)(ina->slots) - 1;
286 float *c = (float*)(outc->slots) - 1;
287 UNROLL_CODE(outc->size, c, *++c = *++a - inb;)
289 return outc;
292 PyrObject* signal_mul_xf(VMGlobals *g, PyrObject* ina, float inb)
294 PyrObject *outc = newPyrSignal(g, ina->size);
295 if (inb == 1.f) {
296 float *a = (float*)(ina->slots);
297 memcpy((float*)(outc->slots), a, ina->size * sizeof(float));
298 } else {
299 float *a = (float*)(ina->slots) - 1;
300 float *c = (float*)(outc->slots) - 1;
301 UNROLL_CODE(outc->size, c, *++c = *++a * inb;)
303 return outc;
306 PyrObject* signal_ring1_xf(VMGlobals *g, PyrObject* ina, float inb)
308 PyrObject *outc = newPyrSignal(g, ina->size);
309 float *a = (float*)(ina->slots) - 1;
310 float *c = (float*)(outc->slots) - 1;
311 UNROLL_CODE(outc->size, c, ++a; *++c = *a * inb + *a;)
312 return outc;
315 PyrObject* signal_ring2_xf(VMGlobals *g, PyrObject* ina, float inb)
317 PyrObject *outc = newPyrSignal(g, ina->size);
318 float *a = (float*)(ina->slots) - 1;
319 float *c = (float*)(outc->slots) - 1;
320 UNROLL_CODE(outc->size, c, ++a; *++c = *a * inb + *a + inb;)
321 return outc;
324 PyrObject* signal_ring3_xf(VMGlobals *g, PyrObject* ina, float inb)
326 PyrObject *outc = newPyrSignal(g, ina->size);
327 float *a = (float*)(ina->slots) - 1;
328 float *c = (float*)(outc->slots) - 1;
329 UNROLL_CODE(outc->size, c, ++a; *++c = *a * *a * inb;)
330 return outc;
333 PyrObject* signal_ring4_xf(VMGlobals *g, PyrObject* ina, float inb)
335 PyrObject *outc = newPyrSignal(g, ina->size);
336 float *a = (float*)(ina->slots) - 1;
337 float *c = (float*)(outc->slots) - 1;
338 float inb2 = inb * inb;
339 UNROLL_CODE(outc->size, c, ++a; *++c = *a * *a * inb + *a * inb2;)
340 return outc;
344 PyrObject* signal_thresh_xf(VMGlobals *g, PyrObject* ina, float inb)
346 PyrObject *outc = newPyrSignal(g, ina->size);
347 float *a = (float*)(ina->slots) - 1;
348 float *c = (float*)(outc->slots) - 1;
349 float inb2 = inb * inb;
350 UNROLL_CODE(outc->size, c, ++a; *++c = *a < inb2 ? 0.f : *a;)
351 return outc;
354 PyrObject* signal_amclip_xf(VMGlobals *g, PyrObject* ina, float inb)
356 PyrObject *res;
357 PyrObject *outc = newPyrSignal(g, ina->size);
358 if (inb <= 0.f) res = signal_fill(outc, 0.f);
359 else res = signal_scale(outc, inb);
360 return res;
363 PyrObject* signal_div_xf(VMGlobals *g, PyrObject* ina, float inb)
365 PyrObject *outc = newPyrSignal(g, ina->size);
366 if (inb == 1.f) {
367 float *a = (float*)(ina->slots);
368 memcpy((float*)(outc->slots), a, ina->size * sizeof(float));
369 } else {
370 float *a = (float*)(ina->slots) - 1;
371 float *c = (float*)(outc->slots) - 1;
372 inb = 1.f/inb;
373 UNROLL_CODE(outc->size, c, *++c = *++a * inb;)
375 return outc;
378 PyrObject* signal_difsqr_xf(VMGlobals *g, PyrObject* ina, float inb)
380 PyrObject *outc = newPyrSignal(g, ina->size);
381 float *a = (float*)(ina->slots) - 1;
382 float *c = (float*)(outc->slots) - 1;
383 inb = inb * inb;
384 UNROLL_CODE(outc->size, c, ++a; *++c = *a * *a - inb;)
385 return outc;
388 PyrObject* signal_sumsqr_xf(VMGlobals *g, PyrObject* ina, float inb)
390 PyrObject *outc = newPyrSignal(g, ina->size);
391 float *a = (float*)(ina->slots) - 1;
392 float *c = (float*)(outc->slots) - 1;
393 inb = inb * inb;
394 UNROLL_CODE(outc->size, c, ++a; *++c = *a * *a + inb;)
395 return outc;
398 PyrObject* signal_sqrsum_xf(VMGlobals *g, PyrObject* ina, float inb)
400 PyrObject *outc = newPyrSignal(g, ina->size);
401 float *a = (float*)(ina->slots) - 1;
402 float *c = (float*)(outc->slots) - 1;
403 float temp;
404 UNROLL_CODE(outc->size, c, ++a; temp = *a + inb; *++c = temp * temp;)
405 return outc;
408 PyrObject* signal_sqrdif_xf(VMGlobals *g, PyrObject* ina, float inb)
410 PyrObject *outc = newPyrSignal(g, ina->size);
411 float *a = (float*)(ina->slots) - 1;
412 float *c = (float*)(outc->slots) - 1;
413 float temp;
414 UNROLL_CODE(outc->size, c, ++a; temp = *a - inb; *++c = temp * temp;)
415 return outc;
418 PyrObject* signal_absdif_xf(VMGlobals *g, PyrObject* ina, float inb)
420 PyrObject *outc = newPyrSignal(g, ina->size);
421 float *a = (float*)(ina->slots) - 1;
422 float *c = (float*)(outc->slots) - 1;
423 UNROLL_CODE(outc->size, c, ++a; *++c = fabs(*a - inb); )
424 return outc;
427 PyrObject* signal_ring1_fx(VMGlobals *g, float ina, PyrObject* inb)
429 PyrObject *outc = newPyrSignal(g, inb->size);
430 float *b = (float*)(inb->slots) - 1;
431 float *c = (float*)(outc->slots) - 1;
432 UNROLL_CODE(outc->size, c, *++c = ina * *++b + ina;)
433 return outc;
436 PyrObject* signal_ring2_fx(VMGlobals *g, float ina, PyrObject* inb)
438 PyrObject *outc = newPyrSignal(g, inb->size);
439 float *b = (float*)(inb->slots) - 1;
440 float *c = (float*)(outc->slots) - 1;
441 UNROLL_CODE(outc->size, c, ++b; *++c = ina * *b + ina + *b;)
442 return outc;
445 PyrObject* signal_ring3_fx(VMGlobals *g, float ina, PyrObject* inb)
447 PyrObject *outc = newPyrSignal(g, inb->size);
448 float *b = (float*)(inb->slots) - 1;
449 float *c = (float*)(outc->slots) - 1;
450 float ina2 = ina * ina;
451 UNROLL_CODE(outc->size, c, *++c = ina2 * *++b;)
452 return outc;
455 PyrObject* signal_ring4_fx(VMGlobals *g, float ina, PyrObject* inb)
457 PyrObject *outc = newPyrSignal(g, inb->size);
458 float *b = (float*)(inb->slots) - 1;
459 float *c = (float*)(outc->slots) - 1;
460 float ina2 = ina * ina;
461 UNROLL_CODE(outc->size, c, ++b; *++c = ina2 * *b - ina * *b * *b;)
462 return outc;
465 PyrObject* signal_thresh_fx(VMGlobals *g, float ina, PyrObject* inb)
467 PyrObject *outc = newPyrSignal(g, inb->size);
468 float *b = (float*)(inb->slots) - 1;
469 float *c = (float*)(outc->slots) - 1;
470 UNROLL1_CODE(outc->size, c, ++b; *++c = ina < *b ? 0.f : ina;)
471 return outc;
474 PyrObject* signal_amclip_fx(VMGlobals *g, float ina, PyrObject* inb)
476 PyrObject *outc = newPyrSignal(g, inb->size);
477 float *b = (float*)(inb->slots) - 1;
478 float *c = (float*)(outc->slots) - 1;
479 UNROLL1_CODE(outc->size, c, ++b; *++c = *b <= 0.f ? 0.f : ina * *b;)
480 return outc;
483 PyrObject* signal_sub_fx(VMGlobals *g, float ina, PyrObject* inb)
485 PyrObject *outc = newPyrSignal(g, inb->size);
486 float *b = (float*)(inb->slots) - 1;
487 float *c = (float*)(outc->slots) - 1;
488 UNROLL_CODE(outc->size, c, *++c = ina - *++b;)
489 return outc;
492 PyrObject* signal_div_fx(VMGlobals *g, float ina, PyrObject* inb)
494 PyrObject *outc = newPyrSignal(g, inb->size);
495 float *b = (float*)(inb->slots) - 1;
496 float *c = (float*)(outc->slots) - 1;
497 UNROLL_CODE(outc->size, c, *++c = ina / *++b;)
498 return outc;
501 PyrObject* signal_difsqr_fx(VMGlobals *g, float ina, PyrObject* inb)
503 PyrObject *outc = newPyrSignal(g, inb->size);
504 float *b = (float*)(inb->slots) - 1;
505 float *c = (float*)(outc->slots) - 1;
506 ina = ina * ina;
507 UNROLL_CODE(outc->size, c, ++b; *++c = ina - *b * *b;)
508 return outc;
511 PyrObject* signal_sumsqr_fx(VMGlobals *g, float ina, PyrObject* inb)
513 PyrObject *outc = newPyrSignal(g, inb->size);
514 float *b = (float*)(inb->slots) - 1;
515 float *c = (float*)(outc->slots) - 1;
516 ina = ina * ina;
517 UNROLL_CODE(outc->size, c, ++b; *++c = ina + *b * *b;)
518 return outc;
521 PyrObject* signal_sqrsum_fx(VMGlobals *g, float ina, PyrObject* inb)
523 PyrObject *outc = newPyrSignal(g, inb->size);
524 float temp;
525 float *b = (float*)(inb->slots) - 1;
526 float *c = (float*)(outc->slots) - 1;
527 UNROLL_CODE(outc->size, c, ++b; temp = ina + *b; *++c = temp * temp;)
528 return outc;
531 PyrObject* signal_sqrdif_fx(VMGlobals *g, float ina, PyrObject* inb)
533 PyrObject *outc = newPyrSignal(g, inb->size);
534 float temp;
535 float *b = (float*)(inb->slots) - 1;
536 float *c = (float*)(outc->slots) - 1;
537 UNROLL_CODE(outc->size, c, ++b; temp = ina - *b; *++c = temp * temp;)
538 return outc;
541 PyrObject* signal_absdif_fx(VMGlobals *g, float ina, PyrObject* inb)
543 PyrObject *outc = newPyrSignal(g, inb->size);
544 float *b = (float*)(inb->slots) - 1;
545 float *c = (float*)(outc->slots) - 1;
546 UNROLL_CODE(outc->size, c, ++b; *++c = fabs(ina - *b);)
547 return outc;
550 PyrObject* signal_min_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
552 BINOP_LOOP2(
553 ++a; ++b; *++c = *a < *b ? *a : *b;
557 PyrObject* signal_max_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
559 BINOP_LOOP2(
560 ++a; ++b; *++c = *a > *b ? *a : *b;
564 PyrObject* signal_scaleneg_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
566 BINOP_LOOP2(
567 ++a; ++b; *++c = *a < 0.f ? *a * *b : *a;
571 PyrObject* signal_clip2_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
573 BINOP_LOOP2(
574 ++a; ++b; *++c = *a > *b ? *b : (*a < -*b ? -*b : *a);
578 PyrObject* signal_fold2_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
580 BINOP_LOOP2(
581 ++a; ++b; *++c = sc_fold(*a, -*b, *b);
585 PyrObject* signal_wrap2_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
587 BINOP_LOOP2(
588 ++a; ++b; *++c = sc_wrap(*a, -*b, *b);
592 PyrObject* signal_excess_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
594 BINOP_LOOP2(
595 ++a; ++b; *++c = *a > *b ? *a - *b : (*a < -*b ? *a + *b : 0.f);
599 bool signal_equal_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
601 float *a = (float*)(ina->slots) - 1;
602 float *b = (float*)(inb->slots) - 1;
603 float *endptr = a + ina->size;
604 if (ina->size != inb->size) return false;
605 if (slotRawSymbol(&ina->slots[ kSignalRate ]) != slotRawSymbol(&inb->slots[ kSignalRate ])) return false;
606 while (a < endptr) { if (*a++ != *b++) return false; }
607 return true;
610 PyrObject* signal_min_xf(VMGlobals *g, PyrObject* ina, float inb)
612 PyrObject *outc = newPyrSignal(g, ina->size);
613 float *a = (float*)(ina->slots) - 1;
614 float *c = (float*)(outc->slots) - 1;
615 UNROLL1_CODE(outc->size, c, ++a; *++c = *a < inb ? *a : inb;)
616 return outc;
619 PyrObject* signal_max_xf(VMGlobals *g, PyrObject* ina, float inb)
621 PyrObject *outc = newPyrSignal(g, ina->size);
622 float *a = (float*)(ina->slots) - 1;
623 float *c = (float*)(outc->slots) - 1;
624 UNROLL1_CODE(outc->size, c, ++a; *++c = *a > inb ? *a : inb;)
625 return outc;
628 PyrObject* signal_scaleneg_xf(VMGlobals *g, PyrObject* ina, float inb)
630 PyrObject *outc = newPyrSignal(g, ina->size);
631 float *a = (float*)(ina->slots) - 1;
632 float *c = (float*)(outc->slots) - 1;
633 UNROLL1_CODE(outc->size, c, ++a; *++c = *a < 0.f ? *a * inb : *a;)
634 return outc;
637 PyrObject* signal_clip2_xf(VMGlobals *g, PyrObject* ina, float inb)
639 PyrObject *outc = newPyrSignal(g, ina->size);
640 float *a = (float*)(ina->slots) - 1;
641 float *c = (float*)(outc->slots) - 1;
642 UNROLL1_CODE(outc->size, c, ++a; *++c = *a > inb ? inb : (*a < -inb ? -inb : *a);)
643 return outc;
646 PyrObject* signal_fold2_xf(VMGlobals *g, PyrObject* ina, float inb)
648 PyrObject *outc = newPyrSignal(g, ina->size);
649 float *a = (float*)(ina->slots) - 1;
650 float *c = (float*)(outc->slots) - 1;
651 UNROLL1_CODE(outc->size, c, ++a; *++c = sc_fold(*a, -inb, inb);)
652 return outc;
655 PyrObject* signal_wrap2_xf(VMGlobals *g, PyrObject* ina, float inb)
657 PyrObject *outc = newPyrSignal(g, ina->size);
658 float *a = (float*)(ina->slots) - 1;
659 float *c = (float*)(outc->slots) - 1;
660 UNROLL1_CODE(outc->size, c, ++a; *++c = sc_wrap(*a, -inb, inb);)
661 return outc;
664 PyrObject* signal_excess_xf(VMGlobals *g, PyrObject* ina, float inb)
666 PyrObject *outc = newPyrSignal(g, ina->size);
667 float *a = (float*)(ina->slots) - 1;
668 float *c = (float*)(outc->slots) - 1;
669 UNROLL1_CODE(outc->size, c, ++a; *++c = *a > inb ? *a - inb : (*a < -inb ? *a + inb : 0.f);)
670 return outc;
673 PyrObject* signal_scaleneg_fx(VMGlobals *g, float ina, PyrObject* inb)
675 PyrObject *outc = newPyrSignal(g, inb->size);
676 float *b = (float*)(inb->slots) - 1;
677 float *c = (float*)(outc->slots) - 1;
678 if (ina < 0.f) {
679 UNROLL1_CODE(outc->size, c, *++c = ina * *++b;);
680 } else {
681 UNROLL1_CODE(outc->size, c, *++c = ina;);
683 return outc;
686 PyrObject* signal_clip2_fx(VMGlobals *g, float ina, PyrObject* inb)
688 PyrObject *outc = newPyrSignal(g, inb->size);
689 float *b = (float*)(inb->slots) - 1;
690 float *c = (float*)(outc->slots) - 1;
691 UNROLL1_CODE(outc->size, c, ++b; *++c = ina > *b ? *b : (ina < -*b ? -*b : ina);)
692 return outc;
695 PyrObject* signal_fold2_fx(VMGlobals *g, float ina, PyrObject* inb)
697 PyrObject *outc = newPyrSignal(g, inb->size);
698 float *b = (float*)(inb->slots) - 1;
699 float *c = (float*)(outc->slots) - 1;
700 UNROLL1_CODE(outc->size, c, ++b; *++c = sc_fold(ina, -*b, *b);)
701 return outc;
704 PyrObject* signal_wrap2_fx(VMGlobals *g, float ina, PyrObject* inb)
706 PyrObject *outc = newPyrSignal(g, inb->size);
707 float *b = (float*)(inb->slots) - 1;
708 float *c = (float*)(outc->slots) - 1;
709 UNROLL1_CODE(outc->size, c, ++b; *++c = sc_wrap(ina, -*b, *b);)
710 return outc;
713 PyrObject* signal_excess_fx(VMGlobals *g, float ina, PyrObject* inb)
715 PyrObject *outc = newPyrSignal(g, inb->size);
716 float *b = (float*)(inb->slots) - 1;
717 float *c = (float*)(outc->slots) - 1;
718 UNROLL1_CODE(outc->size, c, ++b; *++c = ina > *b ? ina - *b : (ina < -*b ? ina + *b : 0.f);)
719 return outc;
722 PyrObject* signal_invert(VMGlobals *g, PyrObject *inPyrSignal)
724 float *in = (float*)(inPyrSignal->slots) - 1;
725 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
726 float *out = (float*)(outc->slots) - 1;
727 UNROLL_CODE(inPyrSignal->size, out, *++out = -*++in;)
728 return outc;
731 PyrObject* signal_recip(VMGlobals *g, PyrObject *inPyrSignal)
733 float *in = (float*)(inPyrSignal->slots) - 1;
734 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
735 float *out = (float*)(outc->slots) - 1;
736 UNROLL_CODE(inPyrSignal->size, out, *++out = 1.f / *++in;)
737 return outc;
740 PyrObject* signal_squared(VMGlobals *g, PyrObject *inPyrSignal)
742 float *in = (float*)(inPyrSignal->slots) - 1;
743 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
744 float *out = (float*)(outc->slots) - 1;
745 UNROLL_CODE(inPyrSignal->size, out, ++in; *++out = *in * *in;)
746 return outc;
749 PyrObject* signal_cubed(VMGlobals *g, PyrObject *inPyrSignal)
751 float *in = (float*)(inPyrSignal->slots) - 1;
752 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
753 float *out = (float*)(outc->slots) - 1;
754 UNROLL_CODE(inPyrSignal->size, out, ++in; *++out = *in * *in * *in;)
755 return outc;
758 // PowerPC has a fast fabs instruction
759 PyrObject* signal_abs(VMGlobals *g, PyrObject *inPyrSignal)
761 float *in = (float*)(inPyrSignal->slots) - 1;
762 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
763 float *out = (float*)(outc->slots) - 1;
764 UNROLL_CODE(inPyrSignal->size, out, *++out = fabs(*++in);)
765 return outc;
768 float signal_findpeak(PyrObject *inPyrSignal)
770 float *out = (float*)(inPyrSignal->slots) - 1;
771 float peak = 0.f;
772 float z;
773 UNROLL1_CODE(inPyrSignal->size, out, ++out; z = fabs(*out); peak = z>peak ? z : peak;)
774 return peak;
777 PyrObject* signal_normalize_transfer_fn(PyrObject *inPyrSignal)
779 float *out, scale, offset, x, maxval;
780 long length, halflength;
782 maxval = 0.0;
783 out = (float*)(inPyrSignal->slots) - 1;
784 length = inPyrSignal->size;
785 halflength = length >> 1;
786 offset = (out[halflength-1] + out[halflength]) * 0.5;
788 UNROLL1_CODE(inPyrSignal->size, out, ++out;
789 x = *out - offset;
790 x = (x < 0.) ? -x : x;
791 if (x > maxval) maxval = x;
793 if (maxval) {
794 out = (float*)(inPyrSignal->slots) - 1;
795 scale = 1.0 / maxval;
796 UNROLL1_CODE(inPyrSignal->size, out, ++out;
797 *out = (*out - offset) * scale;
800 return inPyrSignal;
804 float signal_integral(PyrObject *inPyrSignal)
806 float *out = (float*)(inPyrSignal->slots) - 1;
807 float sum = 0.f;
808 UNROLL1_CODE(inPyrSignal->size, out, sum += *++out;)
809 return sum;
812 PyrObject* signal_sign(VMGlobals *g, PyrObject *inPyrSignal)
814 float *in = (float*)(inPyrSignal->slots) - 1;
815 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
816 float *out = (float*)(outc->slots) - 1;
817 UNROLL1_CODE(inPyrSignal->size, out, ++in; *++out = *in < 0.f ? -1.f : (*in > 0.f ? 1.f : 0.f);)
818 return outc;
821 PyrObject* signal_negative(VMGlobals *g, PyrObject *inPyrSignal)
823 float *in = (float*)(inPyrSignal->slots) - 1;
824 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
825 float *out = (float*)(outc->slots) - 1;
826 UNROLL1_CODE(inPyrSignal->size, out, *++out = *++in < 0.f ? 1.f : 0.f;)
827 return outc;
830 PyrObject* signal_positive(VMGlobals *g, PyrObject *inPyrSignal)
832 float *in = (float*)(inPyrSignal->slots) - 1;
833 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
834 float *out = (float*)(outc->slots) - 1;
835 UNROLL1_CODE(inPyrSignal->size, out, *++out = *++in >= 0.f ? 1.f : 0.f;)
836 return outc;
839 PyrObject* signal_strictly_positive(VMGlobals *g, PyrObject *inPyrSignal)
841 float *in = (float*)(inPyrSignal->slots) - 1;
842 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
843 float *out = (float*)(outc->slots) - 1;
844 UNROLL1_CODE(inPyrSignal->size, out, *++out = *++in > 0.f ? 1.f : 0.f;)
845 return outc;
848 PyrObject* signal_nyqring(VMGlobals *g, PyrObject *inPyrSignal)
850 float *in = (float*)(inPyrSignal->slots) - 1;
851 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
852 float *out = (float*)(outc->slots) - 1;
853 float *endptr = out + inPyrSignal->size;
854 switch (inPyrSignal->size & 3) {
855 while (out < endptr) {
856 *++out = -*++in;
857 case 3 : *++out = *++in;
858 case 2 : *++out = -*++in;
859 case 1 : *++out = *++in;
860 case 0 : ;
863 return outc;
866 PyrObject* signal_clip_f(VMGlobals *g, PyrObject *inPyrSignal, float lo, float hi)
868 float *in = (float*)(inPyrSignal->slots) - 1;
869 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
870 float *out = (float*)(outc->slots) - 1;
871 float *endptr = out + inPyrSignal->size;
872 while (out < endptr) {
873 ++in; *++out = *in < lo ? lo : (*in > hi ? hi : *in);
875 return outc;
878 PyrObject* signal_clip_x(VMGlobals *g, PyrObject *ina, PyrObject *inb, PyrObject *inc)
880 PyrObject *outd;
881 float *a, *b, *c, *d, *endptr;
882 long minsize = sc_min(ina->size, inb->size);
883 minsize = sc_min(minsize, inc->size);
884 outd = newPyrSignal(g, minsize);
885 a = (float*)(ina->slots) - 1;
886 b = (float*)(inb->slots) - 1;
887 c = (float*)(inc->slots) - 1;
888 d = (float*)(outd->slots) - 1;
889 endptr = a + minsize;
890 UNROLL1_CODE(outd->size, d, ++a; ++b; ++c; *++d = *a < *b ? *b : (*a > *c ? *c : *a););
891 return outd;
895 /// WRAP AND FOLD ARE STILL INCORRECT !
897 PyrObject* signal_wrap_f(VMGlobals *g, PyrObject *inPyrSignal, float lo, float hi)
899 float *out = (float*)(inPyrSignal->slots) - 1;
900 float *endptr = out + inPyrSignal->size;
901 while (out < endptr) {
902 ++out; *out = sc_wrap(*out, lo, hi);
904 return inPyrSignal;
907 PyrObject* signal_wrap_x(VMGlobals *g, PyrObject *ina, PyrObject *inb, PyrObject *inc)
909 PyrObject *outd;
910 float *a, *b, *c, *d, *endptr;
911 long minsize = sc_min(ina->size, inb->size);
912 minsize = sc_min(minsize, inc->size);
913 outd = newPyrSignal(g, minsize);
914 a = (float*)(ina->slots) - 1;
915 b = (float*)(inb->slots) - 1;
916 c = (float*)(inc->slots) - 1;
917 d = (float*)(outd->slots) - 1;
918 endptr = d + outd->size;
919 while (d < endptr) {
920 a++; b++; c++; d++;
921 ++d; *d = sc_wrap(*a, *b, *c);
923 return outd;
926 PyrObject* signal_fold_f(VMGlobals *g, PyrObject *inPyrSignal, float lo, float hi)
928 float *out = (float*)(inPyrSignal->slots) - 1;
929 float *endptr = out + inPyrSignal->size;
930 while (out < endptr) {
931 ++out; *out = sc_fold(*out, lo, hi);
933 return inPyrSignal;
936 PyrObject* signal_fold_x(VMGlobals *g, PyrObject *ina, PyrObject *inb, PyrObject *inc)
938 PyrObject *outd;
939 float *a, *b, *c, *d, *endptr;
940 long minsize = sc_min(ina->size, inb->size);
941 minsize = sc_min(minsize, inc->size);
942 outd = newPyrSignal(g, minsize);
943 a = (float*)(ina->slots) - 1;
944 b = (float*)(inb->slots) - 1;
945 c = (float*)(inc->slots) - 1;
946 d = (float*)(outd->slots) - 1;
947 endptr = d + outd->size;
948 while (d < endptr) {
949 a++; b++; c++; d++;
950 *d = sc_fold(*a, *b, *c);
952 return outd;
955 PyrObject* signal_log(VMGlobals *g, PyrObject *inPyrSignal)
957 float *in = (float*)(inPyrSignal->slots) - 1;
958 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
959 float *out = (float*)(outc->slots) - 1;
960 UNROLL1_CODE(inPyrSignal->size, out, *++out = log(*++in);)
961 return outc;
964 #ifdef SC_WIN32
965 // in PyrMathSupport.cpp
966 double log2(double x);
967 #elif defined(__FreeBSD__)
968 double log2(double x);
969 #endif
971 PyrObject* signal_log2(VMGlobals *g, PyrObject *inPyrSignal)
973 float *in = (float*)(inPyrSignal->slots) - 1;
974 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
975 float *out = (float*)(outc->slots) - 1;
976 UNROLL1_CODE(inPyrSignal->size, out, *++out = log2(*++in);)
977 return outc;
980 PyrObject* signal_log10(VMGlobals *g, PyrObject *inPyrSignal)
982 float *in = (float*)(inPyrSignal->slots) - 1;
983 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
984 float *out = (float*)(outc->slots) - 1;
985 UNROLL1_CODE(inPyrSignal->size, out, *++out = log10(*++in);)
986 return outc;
990 PyrObject* signal_sin(VMGlobals *g, PyrObject *inPyrSignal)
992 float *in = (float*)(inPyrSignal->slots) - 1;
993 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
994 float *out = (float*)(outc->slots) - 1;
995 UNROLL1_CODE(inPyrSignal->size, out, *++out = sin(*++in);)
996 return outc;
999 PyrObject* signal_cos(VMGlobals *g, PyrObject *inPyrSignal)
1001 float *in = (float*)(inPyrSignal->slots) - 1;
1002 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
1003 float *out = (float*)(outc->slots) - 1;
1004 UNROLL1_CODE(inPyrSignal->size, out, *++out = cos(*++in);)
1005 return outc;
1008 PyrObject* signal_tan(VMGlobals *g, PyrObject *inPyrSignal)
1010 float *in = (float*)(inPyrSignal->slots) - 1;
1011 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
1012 float *out = (float*)(outc->slots) - 1;
1013 UNROLL1_CODE(inPyrSignal->size, out, *++out = tan(*++in);)
1014 return outc;
1017 PyrObject* signal_sinh(VMGlobals *g, PyrObject *inPyrSignal)
1019 float *in = (float*)(inPyrSignal->slots) - 1;
1020 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
1021 float *out = (float*)(outc->slots) - 1;
1022 UNROLL1_CODE(inPyrSignal->size, out, *++out = sinh(*++in);)
1023 return outc;
1026 PyrObject* signal_cosh(VMGlobals *g, PyrObject *inPyrSignal)
1028 float *in = (float*)(inPyrSignal->slots) - 1;
1029 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
1030 float *out = (float*)(outc->slots) - 1;
1031 UNROLL1_CODE(inPyrSignal->size, out, *++out = cosh(*++in);)
1032 return outc;
1035 PyrObject* signal_tanh(VMGlobals *g, PyrObject *inPyrSignal)
1037 float *in = (float*)(inPyrSignal->slots) - 1;
1038 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
1039 float *out = (float*)(outc->slots) - 1;
1040 UNROLL1_CODE(inPyrSignal->size, out, *++out = tanh(*++in);)
1041 return outc;
1044 PyrObject* signal_tanh_ds(PyrObject *inPyrSignal)
1046 float *out = (float*)(inPyrSignal->slots) - 1;
1047 UNROLL1_CODE(inPyrSignal->size, out, ++out; *out = tanh(*out);)
1048 return inPyrSignal;
1051 PyrObject* signal_asin(VMGlobals *g, PyrObject *inPyrSignal)
1053 float *in = (float*)(inPyrSignal->slots) - 1;
1054 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
1055 float *out = (float*)(outc->slots) - 1;
1056 UNROLL1_CODE(inPyrSignal->size, out, *++out = asin(*++in);)
1057 return outc;
1060 PyrObject* signal_acos(VMGlobals *g, PyrObject *inPyrSignal)
1062 float *in = (float*)(inPyrSignal->slots) - 1;
1063 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
1064 float *out = (float*)(outc->slots) - 1;
1065 UNROLL1_CODE(inPyrSignal->size, out, *++out = acos(*++in);)
1066 return outc;
1069 PyrObject* signal_atan(VMGlobals *g, PyrObject *inPyrSignal)
1071 float *in = (float*)(inPyrSignal->slots) - 1;
1072 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
1073 float *out = (float*)(outc->slots) - 1;
1074 UNROLL1_CODE(inPyrSignal->size, out, *++out = atan(*++in);)
1075 return outc;
1078 PyrObject* signal_exp(VMGlobals *g, PyrObject *inPyrSignal)
1080 float *in = (float*)(inPyrSignal->slots) - 1;
1081 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
1082 float *out = (float*)(outc->slots) - 1;
1083 UNROLL1_CODE(inPyrSignal->size, out, *++out = exp(*++in);)
1084 return outc;
1087 PyrObject* signal_sqrt(VMGlobals *g, PyrObject *inPyrSignal)
1089 float *in = (float*)(inPyrSignal->slots) - 1;
1090 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
1091 float *out = (float*)(outc->slots) - 1;
1092 UNROLL1_CODE(inPyrSignal->size, out, *++out = sqrt(*++in);)
1093 return outc;
1096 PyrObject* signal_distort(VMGlobals *g, PyrObject *inPyrSignal)
1098 float *in = (float*)(inPyrSignal->slots) - 1;
1099 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
1100 float *out = (float*)(outc->slots) - 1;
1101 float *endptr = out + inPyrSignal->size;
1102 while (out < endptr) {
1103 float z = *++in;
1104 if (z < 0.f) *++out = z/(1.f - z);
1105 else *++out = z/(1.f + z);
1107 return outc;
1110 PyrObject* signal_softclip(VMGlobals *g, PyrObject *inPyrSignal)
1112 float *in = (float*)(inPyrSignal->slots) - 1;
1113 PyrObject *outc = newPyrSignal(g, inPyrSignal->size);
1114 float *out = (float*)(outc->slots) - 1;
1115 float *endptr = out + inPyrSignal->size;
1116 while (out < endptr) {
1117 float z = *++in;
1118 if (z < -0.5f) *++out = (-z - .25f)/z;
1119 else if (z > 0.5f) *++out = (z - .25f)/z;
1120 else *++out = z;
1122 return outc;
1126 PyrObject* signal_rotate(VMGlobals *g, PyrObject* ina, int rot)
1128 long i, j;
1129 PyrObject *outc = newPyrSignal(g, ina->size);
1130 float *a0 = (float*)(ina->slots) - 1;
1131 // float *a = a0 + sc_mod(rot, ina->size);
1132 float *a = a0 + sc_mod(0 - rot, ina->size);
1133 float *aend = a0 + ina->size;
1134 float *c = (float*)(outc->slots) - 1;
1135 long nsmps = outc->size;
1136 for (i=0,j=rot; i<nsmps; i++, j++) {
1137 *++c = *++a;
1138 if (a >= aend) a = a0;
1140 return outc;
1143 PyrObject* signal_reverse_range(PyrObject* ina, long start, long end)
1145 long size = ina->size;
1146 long size2;
1147 long i;
1148 start = sc_max(0, start);
1149 end = sc_min(end + 1, size);
1150 size = end - start;
1151 size2 = size>>1;
1152 float *a = (float*)(ina->slots) - 1 + start;
1153 // float *b = (float*)(ina->slots) - 1 + end;
1154 float *b = (float*)(ina->slots) + end;
1155 float temp;
1156 for (i=0; i<size2; ++i) {
1157 temp = *++a;
1158 *a = *--b;
1159 *b = temp;
1161 return ina;
1164 PyrObject* signal_normalize_range(PyrObject* ina, long start, long end)
1166 long size = ina->size;
1167 long i;
1168 float z, scale, maxlevel;
1169 float *a0, *a;
1170 start = sc_max(0, start);
1171 end = sc_min(end + 1, size);
1172 size = end - start;
1173 a0 = (float*)(ina->slots) - 1 + start;
1174 a = a0;
1175 maxlevel = 0.f;
1176 for (i=0; i<size; ++i) {
1177 z = fabs(*++a);
1178 if (z > maxlevel) maxlevel = z;
1180 a = a0;
1181 if (maxlevel != 0.f) {
1182 scale = 1./maxlevel;
1183 for (i=0; i<size; ++i) {
1184 z = *++a;
1185 *a = scale * z;
1188 return ina;
1191 PyrObject* signal_invert_range(PyrObject* ina, long start, long end)
1193 long size = ina->size;
1194 long i;
1195 float z;
1196 start = sc_max(0, start);
1197 end = sc_min(end, size);
1198 size = end - start + 1;
1199 float *a = (float*)(ina->slots) - 1 + start;
1201 for (i=0; i<size; ++i) {
1202 z = *++a; *a = -z;
1204 return ina;
1208 PyrObject* signal_fade_range(PyrObject* ina, long start, long end, float lvl0, float lvl1)
1210 long size = ina->size;
1211 long i;
1212 float z, level, slope;
1213 start = sc_max(0, start);
1214 end = sc_min(end + 1, size);
1215 size = end - start;
1216 float *a = (float*)(ina->slots) - 1 + start;
1217 slope = (lvl1 - lvl0) / size;
1218 level = lvl0;
1219 for (i=0; i<size; ++i) {
1220 z = *++a;
1221 *a = z * level;
1222 level += slope;
1224 return ina;
1228 PyrObject* signal_overdub(VMGlobals *g, PyrObject* ina, PyrObject* inb, long index)
1230 float *a, *b;
1231 long len;
1233 if (index > 0) {
1234 a = (float*)(ina->slots) + index - 1;
1235 b = (float*)(inb->slots) - 1;
1236 len = sc_min(inb->size, ina->size - index);
1237 } else {
1238 a = (float*)(ina->slots) - 1;
1239 b = (float*)(inb->slots) - index - 1;
1240 len = sc_min(ina->size, inb->size + index);
1243 UNROLL_CODE(len, a, *++a += *++b;);
1245 return ina;
1248 PyrObject* signal_overwrite(VMGlobals *g, PyrObject* ina, PyrObject* inb, long index)
1250 float *a, *b;
1251 long len;
1252 if (index > 0) {
1253 a = (float*)(ina->slots) + index - 1;
1254 b = (float*)(inb->slots) - 1;
1255 len = sc_min(inb->size, ina->size - index);
1256 } else {
1257 a = (float*)(ina->slots) - 1;
1258 b = (float*)(inb->slots) - index - 1;
1259 len = sc_min(ina->size, inb->size + index);
1262 UNROLL_CODE(len, a, *++a = *++b;);
1264 return ina;