1 /*
2     SuperCollider real time audio synthesis system
3     Copyright (c) 2002 James McCartney. All rights reserved.
4     http://www.audiosynth.com
5 
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.
10 
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.
15 
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
19 */
20 
21 /*
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
32 */
33 
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"
43 
newPyrSignal(VMGlobals * g,long size)44 PyrObject* newPyrSignal(VMGlobals* g, long size) {
45     PyrObject* signal;
46     long numbytes = size * sizeof(float);
47     signal = (PyrObject*)g->gc->New(numbytes, 0, obj_float, true);
48     if (signal) {
49         signal->classptr = class_signal;
50         signal->size = size;
51     }
52     // note: signal is filled with garbage
53     return signal;
54 }
55 
56 /*PyrObject* newPyrSignalFrom(VMGlobals *g, PyrObject* inSignal, long size)
57 {
58     PyrObject *signal;
59     double *pslot, *qslot, *endptr;
60     long set, m, mmax;
61     long numbytes = size * sizeof(float);
62     signal = (PyrObject*)g->gc->New(numbytes, 0, obj_float, true);
63     signal->classptr = inSignal->classptr;
64     signal->size = size;
65     return signal;
66 }
67 */
68 
signal_fill(PyrObject * outSignal,float inValue)69 PyrObject* signal_fill(PyrObject* outSignal, float inValue) {
70     float* out = (float*)(outSignal->slots) - 1;
71     UNROLL_CODE(outSignal->size, out, *++out = inValue;);
72     return outSignal;
73 }
74 
signal_scale(PyrObject * outSignal,float inValue)75 PyrObject* signal_scale(PyrObject* outSignal, float inValue) {
76     if (inValue != 1.f) {
77         float* out = (float*)(outSignal->slots) - 1;
78         UNROLL_CODE(outSignal->size, out, *++out *= inValue;)
79     }
80     return outSignal;
81 }
82 
signal_offset(PyrObject * outSignal,float inValue)83 PyrObject* signal_offset(PyrObject* outSignal, float inValue) {
84     if (inValue != 0.f) {
85         float* out = (float*)(outSignal->slots) - 1;
86         UNROLL_CODE(outSignal->size, out, *++out += inValue;)
87     }
88     return outSignal;
89 }
90 
signal_add_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)91 PyrObject* signal_add_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) { BINOP_LOOP1(+); }
92 
signal_mul_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)93 PyrObject* signal_mul_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) { BINOP_LOOP1(*); }
94 
signal_sub_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)95 PyrObject* signal_sub_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) { BINOP_LOOP2(*++c = *++a - *++b;); }
96 
signal_ring1_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)97 PyrObject* signal_ring1_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) { BINOP_LOOP2(++a; *++c = *a * *++b + *a;); }
98 
signal_ring2_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)99 PyrObject* signal_ring2_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) {
100     BINOP_LOOP2(++a; ++b; *++c = *a * *b + *a + *b;);
101 }
102 
signal_ring3_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)103 PyrObject* signal_ring3_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) { BINOP_LOOP2(++a; *++c = *a * *a * *++b;); }
104 
signal_ring4_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)105 PyrObject* signal_ring4_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) {
106     BINOP_LOOP2(++a; ++b; *++c = *a * *a * *b - *a * *b * *b;);
107 }
108 
signal_thresh_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)109 PyrObject* signal_thresh_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) {
110     BINOP_LOOP2(++a; ++b; *++c = *a < *b ? 0.f : *a;);
111 }
112 
signal_amclip_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)113 PyrObject* signal_amclip_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) {
114     BINOP_LOOP2(++a; ++b; *++c = *b <= 0.f ? 0.f : *a * *b;);
115 }
116 
signal_div_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)117 PyrObject* signal_div_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) { BINOP_LOOP2(*++c = *++a / *++b;); }
118 
signal_difsqr_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)119 PyrObject* signal_difsqr_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) {
120     BINOP_LOOP2(++a; ++b; *c = *a * *a - *b * *b;);
121 }
122 
signal_sumsqr_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)123 PyrObject* signal_sumsqr_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) {
124     BINOP_LOOP2(++a; ++b; *c = *a * *a + *b * *b;);
125 }
126 
signal_sqrsum_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)127 PyrObject* signal_sqrsum_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) {
128     float z;
129     BINOP_LOOP2(z = *++a + *++b; *++c = z * z;);
130 }
131 
signal_sqrdif_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)132 PyrObject* signal_sqrdif_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) {
133     float z;
134     BINOP_LOOP2(z = *++a - *++b; *++c = z * z;);
135 }
136 
signal_absdif_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)137 PyrObject* signal_absdif_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) { BINOP_LOOP2(*++c = fabs(*++a - *++b);); }
138 
signal_add_xf(VMGlobals * g,PyrObject * ina,float inb)139 PyrObject* signal_add_xf(VMGlobals* g, PyrObject* ina, float inb) {
140     PyrObject* outc = newPyrSignal(g, ina->size);
141     if (inb == 0.f) {
142         float* a = (float*)(ina->slots);
143         memcpy((float*)(outc->slots), a, ina->size * sizeof(float));
144     } else {
145         float* a = (float*)(ina->slots) - 1;
146         float* c = (float*)(outc->slots) - 1;
147         UNROLL_CODE(outc->size, c, *++c = *++a + inb;)
148     }
149     return outc;
150 }
151 
signal_sub_xf(VMGlobals * g,PyrObject * ina,float inb)152 PyrObject* signal_sub_xf(VMGlobals* g, PyrObject* ina, float inb) {
153     PyrObject* outc = newPyrSignal(g, ina->size);
154     if (inb == 0.f) {
155         float* a = (float*)(ina->slots);
156         memcpy((float*)(outc->slots), a, ina->size * sizeof(float));
157     } else {
158         float* a = (float*)(ina->slots) - 1;
159         float* c = (float*)(outc->slots) - 1;
160         UNROLL_CODE(outc->size, c, *++c = *++a - inb;)
161     }
162     return outc;
163 }
164 
signal_mul_xf(VMGlobals * g,PyrObject * ina,float inb)165 PyrObject* signal_mul_xf(VMGlobals* g, PyrObject* ina, float inb) {
166     PyrObject* outc = newPyrSignal(g, ina->size);
167     if (inb == 1.f) {
168         float* a = (float*)(ina->slots);
169         memcpy((float*)(outc->slots), a, ina->size * sizeof(float));
170     } else {
171         float* a = (float*)(ina->slots) - 1;
172         float* c = (float*)(outc->slots) - 1;
173         UNROLL_CODE(outc->size, c, *++c = *++a * inb;)
174     }
175     return outc;
176 }
177 
signal_ring1_xf(VMGlobals * g,PyrObject * ina,float inb)178 PyrObject* signal_ring1_xf(VMGlobals* g, PyrObject* ina, float inb) {
179     PyrObject* outc = newPyrSignal(g, ina->size);
180     float* a = (float*)(ina->slots) - 1;
181     float* c = (float*)(outc->slots) - 1;
182     UNROLL_CODE(outc->size, c, ++a; *++c = *a * inb + *a;)
183     return outc;
184 }
185 
signal_ring2_xf(VMGlobals * g,PyrObject * ina,float inb)186 PyrObject* signal_ring2_xf(VMGlobals* g, PyrObject* ina, float inb) {
187     PyrObject* outc = newPyrSignal(g, ina->size);
188     float* a = (float*)(ina->slots) - 1;
189     float* c = (float*)(outc->slots) - 1;
190     UNROLL_CODE(outc->size, c, ++a; *++c = *a * inb + *a + inb;)
191     return outc;
192 }
193 
signal_ring3_xf(VMGlobals * g,PyrObject * ina,float inb)194 PyrObject* signal_ring3_xf(VMGlobals* g, PyrObject* ina, float inb) {
195     PyrObject* outc = newPyrSignal(g, ina->size);
196     float* a = (float*)(ina->slots) - 1;
197     float* c = (float*)(outc->slots) - 1;
198     UNROLL_CODE(outc->size, c, ++a; *++c = *a * *a * inb;)
199     return outc;
200 }
201 
signal_ring4_xf(VMGlobals * g,PyrObject * ina,float inb)202 PyrObject* signal_ring4_xf(VMGlobals* g, PyrObject* ina, float inb) {
203     PyrObject* outc = newPyrSignal(g, ina->size);
204     float* a = (float*)(ina->slots) - 1;
205     float* c = (float*)(outc->slots) - 1;
206     float inb2 = inb * inb;
207     UNROLL_CODE(outc->size, c, ++a; *++c = *a * *a * inb + *a * inb2;)
208     return outc;
209 }
210 
211 
signal_thresh_xf(VMGlobals * g,PyrObject * ina,float inb)212 PyrObject* signal_thresh_xf(VMGlobals* g, PyrObject* ina, float inb) {
213     PyrObject* outc = newPyrSignal(g, ina->size);
214     float* a = (float*)(ina->slots) - 1;
215     float* c = (float*)(outc->slots) - 1;
216     float inb2 = inb * inb;
217     UNROLL_CODE(outc->size, c, ++a; *++c = *a < inb2 ? 0.f : *a;)
218     return outc;
219 }
220 
signal_amclip_xf(VMGlobals * g,PyrObject * ina,float inb)221 PyrObject* signal_amclip_xf(VMGlobals* g, PyrObject* ina, float inb) {
222     PyrObject* res;
223     PyrObject* outc = newPyrSignal(g, ina->size);
224     if (inb <= 0.f)
225         res = signal_fill(outc, 0.f);
226     else
227         res = signal_scale(outc, inb);
228     return res;
229 }
230 
signal_div_xf(VMGlobals * g,PyrObject * ina,float inb)231 PyrObject* signal_div_xf(VMGlobals* g, PyrObject* ina, float inb) {
232     PyrObject* outc = newPyrSignal(g, ina->size);
233     if (inb == 1.f) {
234         float* a = (float*)(ina->slots);
235         memcpy((float*)(outc->slots), a, ina->size * sizeof(float));
236     } else {
237         float* a = (float*)(ina->slots) - 1;
238         float* c = (float*)(outc->slots) - 1;
239         inb = 1.f / inb;
240         UNROLL_CODE(outc->size, c, *++c = *++a * inb;)
241     }
242     return outc;
243 }
244 
signal_difsqr_xf(VMGlobals * g,PyrObject * ina,float inb)245 PyrObject* signal_difsqr_xf(VMGlobals* g, PyrObject* ina, float inb) {
246     PyrObject* outc = newPyrSignal(g, ina->size);
247     float* a = (float*)(ina->slots) - 1;
248     float* c = (float*)(outc->slots) - 1;
249     inb = inb * inb;
250     UNROLL_CODE(outc->size, c, ++a; *++c = *a * *a - inb;)
251     return outc;
252 }
253 
signal_sumsqr_xf(VMGlobals * g,PyrObject * ina,float inb)254 PyrObject* signal_sumsqr_xf(VMGlobals* g, PyrObject* ina, float inb) {
255     PyrObject* outc = newPyrSignal(g, ina->size);
256     float* a = (float*)(ina->slots) - 1;
257     float* c = (float*)(outc->slots) - 1;
258     inb = inb * inb;
259     UNROLL_CODE(outc->size, c, ++a; *++c = *a * *a + inb;)
260     return outc;
261 }
262 
signal_sqrsum_xf(VMGlobals * g,PyrObject * ina,float inb)263 PyrObject* signal_sqrsum_xf(VMGlobals* g, PyrObject* ina, float inb) {
264     PyrObject* outc = newPyrSignal(g, ina->size);
265     float* a = (float*)(ina->slots) - 1;
266     float* c = (float*)(outc->slots) - 1;
267     float temp;
268     UNROLL_CODE(outc->size, c, ++a; temp = *a + inb; *++c = temp * temp;)
269     return outc;
270 }
271 
signal_sqrdif_xf(VMGlobals * g,PyrObject * ina,float inb)272 PyrObject* signal_sqrdif_xf(VMGlobals* g, PyrObject* ina, float inb) {
273     PyrObject* outc = newPyrSignal(g, ina->size);
274     float* a = (float*)(ina->slots) - 1;
275     float* c = (float*)(outc->slots) - 1;
276     float temp;
277     UNROLL_CODE(outc->size, c, ++a; temp = *a - inb; *++c = temp * temp;)
278     return outc;
279 }
280 
signal_absdif_xf(VMGlobals * g,PyrObject * ina,float inb)281 PyrObject* signal_absdif_xf(VMGlobals* g, PyrObject* ina, float inb) {
282     PyrObject* outc = newPyrSignal(g, ina->size);
283     float* a = (float*)(ina->slots) - 1;
284     float* c = (float*)(outc->slots) - 1;
285     UNROLL_CODE(outc->size, c, ++a; *++c = fabs(*a - inb);)
286     return outc;
287 }
288 
signal_ring1_fx(VMGlobals * g,float ina,PyrObject * inb)289 PyrObject* signal_ring1_fx(VMGlobals* g, float ina, PyrObject* inb) {
290     PyrObject* outc = newPyrSignal(g, inb->size);
291     float* b = (float*)(inb->slots) - 1;
292     float* c = (float*)(outc->slots) - 1;
293     UNROLL_CODE(outc->size, c, *++c = ina * *++b + ina;)
294     return outc;
295 }
296 
signal_ring2_fx(VMGlobals * g,float ina,PyrObject * inb)297 PyrObject* signal_ring2_fx(VMGlobals* g, float ina, PyrObject* inb) {
298     PyrObject* outc = newPyrSignal(g, inb->size);
299     float* b = (float*)(inb->slots) - 1;
300     float* c = (float*)(outc->slots) - 1;
301     UNROLL_CODE(outc->size, c, ++b; *++c = ina * *b + ina + *b;)
302     return outc;
303 }
304 
signal_ring3_fx(VMGlobals * g,float ina,PyrObject * inb)305 PyrObject* signal_ring3_fx(VMGlobals* g, float ina, PyrObject* inb) {
306     PyrObject* outc = newPyrSignal(g, inb->size);
307     float* b = (float*)(inb->slots) - 1;
308     float* c = (float*)(outc->slots) - 1;
309     float ina2 = ina * ina;
310     UNROLL_CODE(outc->size, c, *++c = ina2 * *++b;)
311     return outc;
312 }
313 
signal_ring4_fx(VMGlobals * g,float ina,PyrObject * inb)314 PyrObject* signal_ring4_fx(VMGlobals* g, float ina, PyrObject* inb) {
315     PyrObject* outc = newPyrSignal(g, inb->size);
316     float* b = (float*)(inb->slots) - 1;
317     float* c = (float*)(outc->slots) - 1;
318     float ina2 = ina * ina;
319     UNROLL_CODE(outc->size, c, ++b; *++c = ina2 * *b - ina * *b * *b;)
320     return outc;
321 }
322 
signal_thresh_fx(VMGlobals * g,float ina,PyrObject * inb)323 PyrObject* signal_thresh_fx(VMGlobals* g, float ina, PyrObject* inb) {
324     PyrObject* outc = newPyrSignal(g, inb->size);
325     float* b = (float*)(inb->slots) - 1;
326     float* c = (float*)(outc->slots) - 1;
327     UNROLL1_CODE(outc->size, c, ++b; *++c = ina < *b ? 0.f : ina;)
328     return outc;
329 }
330 
signal_amclip_fx(VMGlobals * g,float ina,PyrObject * inb)331 PyrObject* signal_amclip_fx(VMGlobals* g, float ina, PyrObject* inb) {
332     PyrObject* outc = newPyrSignal(g, inb->size);
333     float* b = (float*)(inb->slots) - 1;
334     float* c = (float*)(outc->slots) - 1;
335     UNROLL1_CODE(outc->size, c, ++b; *++c = *b <= 0.f ? 0.f : ina * *b;)
336     return outc;
337 }
338 
signal_sub_fx(VMGlobals * g,float ina,PyrObject * inb)339 PyrObject* signal_sub_fx(VMGlobals* g, float ina, PyrObject* inb) {
340     PyrObject* outc = newPyrSignal(g, inb->size);
341     float* b = (float*)(inb->slots) - 1;
342     float* c = (float*)(outc->slots) - 1;
343     UNROLL_CODE(outc->size, c, *++c = ina - *++b;)
344     return outc;
345 }
346 
signal_div_fx(VMGlobals * g,float ina,PyrObject * inb)347 PyrObject* signal_div_fx(VMGlobals* g, float ina, PyrObject* inb) {
348     PyrObject* outc = newPyrSignal(g, inb->size);
349     float* b = (float*)(inb->slots) - 1;
350     float* c = (float*)(outc->slots) - 1;
351     UNROLL_CODE(outc->size, c, *++c = ina / *++b;)
352     return outc;
353 }
354 
signal_difsqr_fx(VMGlobals * g,float ina,PyrObject * inb)355 PyrObject* signal_difsqr_fx(VMGlobals* g, float ina, PyrObject* inb) {
356     PyrObject* outc = newPyrSignal(g, inb->size);
357     float* b = (float*)(inb->slots) - 1;
358     float* c = (float*)(outc->slots) - 1;
359     ina = ina * ina;
360     UNROLL_CODE(outc->size, c, ++b; *++c = ina - *b * *b;)
361     return outc;
362 }
363 
signal_sumsqr_fx(VMGlobals * g,float ina,PyrObject * inb)364 PyrObject* signal_sumsqr_fx(VMGlobals* g, float ina, PyrObject* inb) {
365     PyrObject* outc = newPyrSignal(g, inb->size);
366     float* b = (float*)(inb->slots) - 1;
367     float* c = (float*)(outc->slots) - 1;
368     ina = ina * ina;
369     UNROLL_CODE(outc->size, c, ++b; *++c = ina + *b * *b;)
370     return outc;
371 }
372 
signal_sqrsum_fx(VMGlobals * g,float ina,PyrObject * inb)373 PyrObject* signal_sqrsum_fx(VMGlobals* g, float ina, PyrObject* inb) {
374     PyrObject* outc = newPyrSignal(g, inb->size);
375     float temp;
376     float* b = (float*)(inb->slots) - 1;
377     float* c = (float*)(outc->slots) - 1;
378     UNROLL_CODE(outc->size, c, ++b; temp = ina + *b; *++c = temp * temp;)
379     return outc;
380 }
381 
signal_sqrdif_fx(VMGlobals * g,float ina,PyrObject * inb)382 PyrObject* signal_sqrdif_fx(VMGlobals* g, float ina, PyrObject* inb) {
383     PyrObject* outc = newPyrSignal(g, inb->size);
384     float temp;
385     float* b = (float*)(inb->slots) - 1;
386     float* c = (float*)(outc->slots) - 1;
387     UNROLL_CODE(outc->size, c, ++b; temp = ina - *b; *++c = temp * temp;)
388     return outc;
389 }
390 
signal_absdif_fx(VMGlobals * g,float ina,PyrObject * inb)391 PyrObject* signal_absdif_fx(VMGlobals* g, float ina, PyrObject* inb) {
392     PyrObject* outc = newPyrSignal(g, inb->size);
393     float* b = (float*)(inb->slots) - 1;
394     float* c = (float*)(outc->slots) - 1;
395     UNROLL_CODE(outc->size, c, ++b; *++c = fabs(ina - *b);)
396     return outc;
397 }
398 
signal_min_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)399 PyrObject* signal_min_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) {
400     BINOP_LOOP2(++a; ++b; *++c = *a < *b ? *a : *b;);
401 }
402 
signal_max_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)403 PyrObject* signal_max_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) {
404     BINOP_LOOP2(++a; ++b; *++c = *a > *b ? *a : *b;);
405 }
406 
signal_scaleneg_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)407 PyrObject* signal_scaleneg_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) {
408     BINOP_LOOP2(++a; ++b; *++c = *a < 0.f ? *a * *b : *a;);
409 }
410 
signal_clip2_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)411 PyrObject* signal_clip2_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) {
412     BINOP_LOOP2(++a; ++b; *++c = *a > *b ? *b : (*a < -*b ? -*b : *a););
413 }
414 
signal_fold2_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)415 PyrObject* signal_fold2_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) {
416     BINOP_LOOP2(++a; ++b; *++c = sc_fold(*a, -*b, *b););
417 }
418 
signal_wrap2_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)419 PyrObject* signal_wrap2_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) {
420     BINOP_LOOP2(++a; ++b; *++c = sc_wrap(*a, -*b, *b););
421 }
422 
signal_excess_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)423 PyrObject* signal_excess_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) {
424     BINOP_LOOP2(++a; ++b; *++c = *a > *b ? *a - *b : (*a < -*b ? *a + *b : 0.f););
425 }
426 
signal_equal_xx(VMGlobals * g,PyrObject * ina,PyrObject * inb)427 bool signal_equal_xx(VMGlobals* g, PyrObject* ina, PyrObject* inb) {
428     if (ina->size != inb->size)
429         return false;
430     if (slotRawSymbol(&ina->slots[kSignalRate]) != slotRawSymbol(&inb->slots[kSignalRate]))
431         return false;
432     float* a = (float*)(ina->slots);
433     float* b = (float*)(inb->slots);
434     for (int i = 0; i < ina->size; i++) {
435         if (a[i] != b[i]) {
436             return false;
437         }
438     }
439     return true;
440 }
441 
signal_min_xf(VMGlobals * g,PyrObject * ina,float inb)442 PyrObject* signal_min_xf(VMGlobals* g, PyrObject* ina, float inb) {
443     PyrObject* outc = newPyrSignal(g, ina->size);
444     float* a = (float*)(ina->slots) - 1;
445     float* c = (float*)(outc->slots) - 1;
446     UNROLL1_CODE(outc->size, c, ++a; *++c = *a < inb ? *a : inb;)
447     return outc;
448 }
449 
signal_max_xf(VMGlobals * g,PyrObject * ina,float inb)450 PyrObject* signal_max_xf(VMGlobals* g, PyrObject* ina, float inb) {
451     PyrObject* outc = newPyrSignal(g, ina->size);
452     float* a = (float*)(ina->slots) - 1;
453     float* c = (float*)(outc->slots) - 1;
454     UNROLL1_CODE(outc->size, c, ++a; *++c = *a > inb ? *a : inb;)
455     return outc;
456 }
457 
signal_scaleneg_xf(VMGlobals * g,PyrObject * ina,float inb)458 PyrObject* signal_scaleneg_xf(VMGlobals* g, PyrObject* ina, float inb) {
459     PyrObject* outc = newPyrSignal(g, ina->size);
460     float* a = (float*)(ina->slots) - 1;
461     float* c = (float*)(outc->slots) - 1;
462     UNROLL1_CODE(outc->size, c, ++a; *++c = *a < 0.f ? *a * inb : *a;)
463     return outc;
464 }
465 
signal_clip2_xf(VMGlobals * g,PyrObject * ina,float inb)466 PyrObject* signal_clip2_xf(VMGlobals* g, PyrObject* ina, float inb) {
467     PyrObject* outc = newPyrSignal(g, ina->size);
468     float* a = (float*)(ina->slots) - 1;
469     float* c = (float*)(outc->slots) - 1;
470     UNROLL1_CODE(outc->size, c, ++a; *++c = *a > inb ? inb : (*a < -inb ? -inb : *a);)
471     return outc;
472 }
473 
signal_fold2_xf(VMGlobals * g,PyrObject * ina,float inb)474 PyrObject* signal_fold2_xf(VMGlobals* g, PyrObject* ina, float inb) {
475     PyrObject* outc = newPyrSignal(g, ina->size);
476     float* a = (float*)(ina->slots) - 1;
477     float* c = (float*)(outc->slots) - 1;
478     UNROLL1_CODE(outc->size, c, ++a; *++c = sc_fold(*a, -inb, inb);)
479     return outc;
480 }
481 
signal_wrap2_xf(VMGlobals * g,PyrObject * ina,float inb)482 PyrObject* signal_wrap2_xf(VMGlobals* g, PyrObject* ina, float inb) {
483     PyrObject* outc = newPyrSignal(g, ina->size);
484     float* a = (float*)(ina->slots) - 1;
485     float* c = (float*)(outc->slots) - 1;
486     UNROLL1_CODE(outc->size, c, ++a; *++c = sc_wrap(*a, -inb, inb);)
487     return outc;
488 }
489 
signal_excess_xf(VMGlobals * g,PyrObject * ina,float inb)490 PyrObject* signal_excess_xf(VMGlobals* g, PyrObject* ina, float inb) {
491     PyrObject* outc = newPyrSignal(g, ina->size);
492     float* a = (float*)(ina->slots) - 1;
493     float* c = (float*)(outc->slots) - 1;
494     UNROLL1_CODE(outc->size, c, ++a; *++c = *a > inb ? *a - inb : (*a < -inb ? *a + inb : 0.f);)
495     return outc;
496 }
497 
signal_scaleneg_fx(VMGlobals * g,float ina,PyrObject * inb)498 PyrObject* signal_scaleneg_fx(VMGlobals* g, float ina, PyrObject* inb) {
499     PyrObject* outc = newPyrSignal(g, inb->size);
500     float* b = (float*)(inb->slots) - 1;
501     float* c = (float*)(outc->slots) - 1;
502     if (ina < 0.f) {
503         UNROLL1_CODE(outc->size, c, *++c = ina * *++b;);
504     } else {
505         UNROLL1_CODE(outc->size, c, *++c = ina;);
506     }
507     return outc;
508 }
509 
signal_clip2_fx(VMGlobals * g,float ina,PyrObject * inb)510 PyrObject* signal_clip2_fx(VMGlobals* g, float ina, PyrObject* inb) {
511     PyrObject* outc = newPyrSignal(g, inb->size);
512     float* b = (float*)(inb->slots) - 1;
513     float* c = (float*)(outc->slots) - 1;
514     UNROLL1_CODE(outc->size, c, ++b; *++c = ina > *b ? *b : (ina < -*b ? -*b : ina);)
515     return outc;
516 }
517 
signal_fold2_fx(VMGlobals * g,float ina,PyrObject * inb)518 PyrObject* signal_fold2_fx(VMGlobals* g, float ina, PyrObject* inb) {
519     PyrObject* outc = newPyrSignal(g, inb->size);
520     float* b = (float*)(inb->slots) - 1;
521     float* c = (float*)(outc->slots) - 1;
522     UNROLL1_CODE(outc->size, c, ++b; *++c = sc_fold(ina, -*b, *b);)
523     return outc;
524 }
525 
signal_wrap2_fx(VMGlobals * g,float ina,PyrObject * inb)526 PyrObject* signal_wrap2_fx(VMGlobals* g, float ina, PyrObject* inb) {
527     PyrObject* outc = newPyrSignal(g, inb->size);
528     float* b = (float*)(inb->slots) - 1;
529     float* c = (float*)(outc->slots) - 1;
530     UNROLL1_CODE(outc->size, c, ++b; *++c = sc_wrap(ina, -*b, *b);)
531     return outc;
532 }
533 
signal_excess_fx(VMGlobals * g,float ina,PyrObject * inb)534 PyrObject* signal_excess_fx(VMGlobals* g, float ina, PyrObject* inb) {
535     PyrObject* outc = newPyrSignal(g, inb->size);
536     float* b = (float*)(inb->slots) - 1;
537     float* c = (float*)(outc->slots) - 1;
538     UNROLL1_CODE(outc->size, c, ++b; *++c = ina > *b ? ina - *b : (ina < -*b ? ina + *b : 0.f);)
539     return outc;
540 }
541 
signal_invert(VMGlobals * g,PyrObject * inPyrSignal)542 PyrObject* signal_invert(VMGlobals* g, PyrObject* inPyrSignal) {
543     float* in = (float*)(inPyrSignal->slots) - 1;
544     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
545     float* out = (float*)(outc->slots) - 1;
546     UNROLL_CODE(inPyrSignal->size, out, *++out = -*++in;)
547     return outc;
548 }
549 
signal_recip(VMGlobals * g,PyrObject * inPyrSignal)550 PyrObject* signal_recip(VMGlobals* g, PyrObject* inPyrSignal) {
551     float* in = (float*)(inPyrSignal->slots) - 1;
552     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
553     float* out = (float*)(outc->slots) - 1;
554     UNROLL_CODE(inPyrSignal->size, out, *++out = 1.f / *++in;)
555     return outc;
556 }
557 
signal_squared(VMGlobals * g,PyrObject * inPyrSignal)558 PyrObject* signal_squared(VMGlobals* g, PyrObject* inPyrSignal) {
559     float* in = (float*)(inPyrSignal->slots) - 1;
560     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
561     float* out = (float*)(outc->slots) - 1;
562     UNROLL_CODE(inPyrSignal->size, out, ++in; *++out = *in * *in;)
563     return outc;
564 }
565 
signal_cubed(VMGlobals * g,PyrObject * inPyrSignal)566 PyrObject* signal_cubed(VMGlobals* g, PyrObject* inPyrSignal) {
567     float* in = (float*)(inPyrSignal->slots) - 1;
568     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
569     float* out = (float*)(outc->slots) - 1;
570     UNROLL_CODE(inPyrSignal->size, out, ++in; *++out = *in * *in * *in;)
571     return outc;
572 }
573 
574 // PowerPC has a fast fabs instruction
signal_abs(VMGlobals * g,PyrObject * inPyrSignal)575 PyrObject* signal_abs(VMGlobals* g, PyrObject* inPyrSignal) {
576     float* in = (float*)(inPyrSignal->slots) - 1;
577     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
578     float* out = (float*)(outc->slots) - 1;
579     UNROLL_CODE(inPyrSignal->size, out, *++out = fabs(*++in);)
580     return outc;
581 }
582 
signal_findpeak(PyrObject * inPyrSignal)583 float signal_findpeak(PyrObject* inPyrSignal) {
584     float* out = (float*)(inPyrSignal->slots) - 1;
585     float peak = 0.f;
586     float z;
587     UNROLL1_CODE(inPyrSignal->size, out, ++out; z = fabs(*out); peak = z > peak ? z : peak;)
588     return peak;
589 }
590 
signal_normalize_transfer_fn(PyrObject * inPyrSignal)591 PyrObject* signal_normalize_transfer_fn(PyrObject* inPyrSignal) {
592     float *out, scale, offset, x, maxval;
593     long length, halflength;
594 
595     maxval = 0.0;
596     out = (float*)(inPyrSignal->slots) - 1;
597     length = inPyrSignal->size;
598     halflength = length >> 1;
599     offset = (out[halflength - 1] + out[halflength]) * 0.5;
600 
601     UNROLL1_CODE(inPyrSignal->size, out, ++out; x = *out - offset; x = (x < 0.) ? -x : x; if (x > maxval) maxval = x;);
602     if (maxval) {
603         out = (float*)(inPyrSignal->slots) - 1;
604         scale = 1.0 / maxval;
605         UNROLL1_CODE(inPyrSignal->size, out, ++out; *out = (*out - offset) * scale;);
606     }
607     return inPyrSignal;
608 }
609 
610 
signal_integral(PyrObject * inPyrSignal)611 float signal_integral(PyrObject* inPyrSignal) {
612     float* out = (float*)(inPyrSignal->slots) - 1;
613     float sum = 0.f;
614     UNROLL1_CODE(inPyrSignal->size, out, sum += *++out;)
615     return sum;
616 }
617 
signal_sign(VMGlobals * g,PyrObject * inPyrSignal)618 PyrObject* signal_sign(VMGlobals* g, PyrObject* inPyrSignal) {
619     float* in = (float*)(inPyrSignal->slots) - 1;
620     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
621     float* out = (float*)(outc->slots) - 1;
622     UNROLL1_CODE(inPyrSignal->size, out, ++in; *++out = *in < 0.f ? -1.f : (*in > 0.f ? 1.f : 0.f);)
623     return outc;
624 }
625 
signal_negative(VMGlobals * g,PyrObject * inPyrSignal)626 PyrObject* signal_negative(VMGlobals* g, PyrObject* inPyrSignal) {
627     float* in = (float*)(inPyrSignal->slots) - 1;
628     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
629     float* out = (float*)(outc->slots) - 1;
630     UNROLL1_CODE(inPyrSignal->size, out, *++out = *++in < 0.f ? 1.f : 0.f;)
631     return outc;
632 }
633 
signal_positive(VMGlobals * g,PyrObject * inPyrSignal)634 PyrObject* signal_positive(VMGlobals* g, PyrObject* inPyrSignal) {
635     float* in = (float*)(inPyrSignal->slots) - 1;
636     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
637     float* out = (float*)(outc->slots) - 1;
638     UNROLL1_CODE(inPyrSignal->size, out, *++out = *++in >= 0.f ? 1.f : 0.f;)
639     return outc;
640 }
641 
signal_strictly_positive(VMGlobals * g,PyrObject * inPyrSignal)642 PyrObject* signal_strictly_positive(VMGlobals* g, PyrObject* inPyrSignal) {
643     float* in = (float*)(inPyrSignal->slots) - 1;
644     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
645     float* out = (float*)(outc->slots) - 1;
646     UNROLL1_CODE(inPyrSignal->size, out, *++out = *++in > 0.f ? 1.f : 0.f;)
647     return outc;
648 }
649 
signal_nyqring(VMGlobals * g,PyrObject * inPyrSignal)650 PyrObject* signal_nyqring(VMGlobals* g, PyrObject* inPyrSignal) {
651     float* in = (float*)(inPyrSignal->slots) - 1;
652     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
653     float* out = (float*)(outc->slots) - 1;
654     float* endptr = out + inPyrSignal->size;
655     switch (inPyrSignal->size & 3) {
656         while (out < endptr) {
657             *++out = -*++in;
658         case 3:
659             *++out = *++in;
660         case 2:
661             *++out = -*++in;
662         case 1:
663             *++out = *++in;
664         case 0:;
665         }
666     }
667     return outc;
668 }
669 
signal_clip_f(VMGlobals * g,PyrObject * inPyrSignal,float lo,float hi)670 PyrObject* signal_clip_f(VMGlobals* g, PyrObject* inPyrSignal, float lo, float hi) {
671     float* in = (float*)(inPyrSignal->slots) - 1;
672     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
673     float* out = (float*)(outc->slots) - 1;
674     float* endptr = out + inPyrSignal->size;
675     while (out < endptr) {
676         ++in;
677         *++out = *in < lo ? lo : (*in > hi ? hi : *in);
678     }
679     return outc;
680 }
681 
signal_clip_x(VMGlobals * g,PyrObject * ina,PyrObject * inb,PyrObject * inc)682 PyrObject* signal_clip_x(VMGlobals* g, PyrObject* ina, PyrObject* inb, PyrObject* inc) {
683     PyrObject* outd;
684     float *a, *b, *c, *d, *endptr;
685     long minsize = sc_min(ina->size, inb->size);
686     minsize = sc_min(minsize, inc->size);
687     outd = newPyrSignal(g, minsize);
688     a = (float*)(ina->slots) - 1;
689     b = (float*)(inb->slots) - 1;
690     c = (float*)(inc->slots) - 1;
691     d = (float*)(outd->slots) - 1;
692     endptr = a + minsize;
693     UNROLL1_CODE(outd->size, d, ++a; ++b; ++c; *++d = *a < *b ? *b : (*a > *c ? *c : *a););
694     return outd;
695 }
696 
697 
698 /// WRAP AND FOLD ARE STILL INCORRECT !
699 
signal_wrap_f(VMGlobals * g,PyrObject * inPyrSignal,float lo,float hi)700 PyrObject* signal_wrap_f(VMGlobals* g, PyrObject* inPyrSignal, float lo, float hi) {
701     float* out = (float*)(inPyrSignal->slots) - 1;
702     float* endptr = out + inPyrSignal->size;
703     while (out < endptr) {
704         ++out;
705         *out = sc_wrap(*out, lo, hi);
706     }
707     return inPyrSignal;
708 }
709 
signal_wrap_x(VMGlobals * g,PyrObject * ina,PyrObject * inb,PyrObject * inc)710 PyrObject* signal_wrap_x(VMGlobals* g, PyrObject* ina, PyrObject* inb, PyrObject* inc) {
711     PyrObject* outd;
712     float *a, *b, *c, *d, *endptr;
713     long minsize = sc_min(ina->size, inb->size);
714     minsize = sc_min(minsize, inc->size);
715     outd = newPyrSignal(g, minsize);
716     a = (float*)(ina->slots) - 1;
717     b = (float*)(inb->slots) - 1;
718     c = (float*)(inc->slots) - 1;
719     d = (float*)(outd->slots) - 1;
720     endptr = d + outd->size;
721     while (d < endptr) {
722         a++;
723         b++;
724         c++;
725         d++;
726         ++d;
727         *d = sc_wrap(*a, *b, *c);
728     }
729     return outd;
730 }
731 
signal_fold_f(VMGlobals * g,PyrObject * inPyrSignal,float lo,float hi)732 PyrObject* signal_fold_f(VMGlobals* g, PyrObject* inPyrSignal, float lo, float hi) {
733     float* out = (float*)(inPyrSignal->slots) - 1;
734     float* endptr = out + inPyrSignal->size;
735     while (out < endptr) {
736         ++out;
737         *out = sc_fold(*out, lo, hi);
738     }
739     return inPyrSignal;
740 }
741 
signal_fold_x(VMGlobals * g,PyrObject * ina,PyrObject * inb,PyrObject * inc)742 PyrObject* signal_fold_x(VMGlobals* g, PyrObject* ina, PyrObject* inb, PyrObject* inc) {
743     PyrObject* outd;
744     float *a, *b, *c, *d, *endptr;
745     long minsize = sc_min(ina->size, inb->size);
746     minsize = sc_min(minsize, inc->size);
747     outd = newPyrSignal(g, minsize);
748     a = (float*)(ina->slots) - 1;
749     b = (float*)(inb->slots) - 1;
750     c = (float*)(inc->slots) - 1;
751     d = (float*)(outd->slots) - 1;
752     endptr = d + outd->size;
753     while (d < endptr) {
754         a++;
755         b++;
756         c++;
757         d++;
758         *d = sc_fold(*a, *b, *c);
759     }
760     return outd;
761 }
762 
signal_log(VMGlobals * g,PyrObject * inPyrSignal)763 PyrObject* signal_log(VMGlobals* g, PyrObject* inPyrSignal) {
764     float* in = (float*)(inPyrSignal->slots) - 1;
765     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
766     float* out = (float*)(outc->slots) - 1;
767     UNROLL1_CODE(inPyrSignal->size, out, *++out = log(*++in);)
768     return outc;
769 }
770 
signal_log2(VMGlobals * g,PyrObject * inPyrSignal)771 PyrObject* signal_log2(VMGlobals* g, PyrObject* inPyrSignal) {
772     float* in = (float*)(inPyrSignal->slots) - 1;
773     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
774     float* out = (float*)(outc->slots) - 1;
775     UNROLL1_CODE(inPyrSignal->size, out, *++out = sc_log2(*++in);)
776     return outc;
777 }
778 
signal_log10(VMGlobals * g,PyrObject * inPyrSignal)779 PyrObject* signal_log10(VMGlobals* g, PyrObject* inPyrSignal) {
780     float* in = (float*)(inPyrSignal->slots) - 1;
781     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
782     float* out = (float*)(outc->slots) - 1;
783     UNROLL1_CODE(inPyrSignal->size, out, *++out = log10(*++in);)
784     return outc;
785 }
786 
787 
signal_sin(VMGlobals * g,PyrObject * inPyrSignal)788 PyrObject* signal_sin(VMGlobals* g, PyrObject* inPyrSignal) {
789     float* in = (float*)(inPyrSignal->slots) - 1;
790     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
791     float* out = (float*)(outc->slots) - 1;
792     UNROLL1_CODE(inPyrSignal->size, out, *++out = sin(*++in);)
793     return outc;
794 }
795 
signal_cos(VMGlobals * g,PyrObject * inPyrSignal)796 PyrObject* signal_cos(VMGlobals* g, PyrObject* inPyrSignal) {
797     float* in = (float*)(inPyrSignal->slots) - 1;
798     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
799     float* out = (float*)(outc->slots) - 1;
800     UNROLL1_CODE(inPyrSignal->size, out, *++out = cos(*++in);)
801     return outc;
802 }
803 
signal_tan(VMGlobals * g,PyrObject * inPyrSignal)804 PyrObject* signal_tan(VMGlobals* g, PyrObject* inPyrSignal) {
805     float* in = (float*)(inPyrSignal->slots) - 1;
806     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
807     float* out = (float*)(outc->slots) - 1;
808     UNROLL1_CODE(inPyrSignal->size, out, *++out = tan(*++in);)
809     return outc;
810 }
811 
signal_sinh(VMGlobals * g,PyrObject * inPyrSignal)812 PyrObject* signal_sinh(VMGlobals* g, PyrObject* inPyrSignal) {
813     float* in = (float*)(inPyrSignal->slots) - 1;
814     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
815     float* out = (float*)(outc->slots) - 1;
816     UNROLL1_CODE(inPyrSignal->size, out, *++out = sinh(*++in);)
817     return outc;
818 }
819 
signal_cosh(VMGlobals * g,PyrObject * inPyrSignal)820 PyrObject* signal_cosh(VMGlobals* g, PyrObject* inPyrSignal) {
821     float* in = (float*)(inPyrSignal->slots) - 1;
822     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
823     float* out = (float*)(outc->slots) - 1;
824     UNROLL1_CODE(inPyrSignal->size, out, *++out = cosh(*++in);)
825     return outc;
826 }
827 
signal_tanh(VMGlobals * g,PyrObject * inPyrSignal)828 PyrObject* signal_tanh(VMGlobals* g, PyrObject* inPyrSignal) {
829     float* in = (float*)(inPyrSignal->slots) - 1;
830     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
831     float* out = (float*)(outc->slots) - 1;
832     UNROLL1_CODE(inPyrSignal->size, out, *++out = tanh(*++in);)
833     return outc;
834 }
835 
signal_tanh_ds(PyrObject * inPyrSignal)836 PyrObject* signal_tanh_ds(PyrObject* inPyrSignal) {
837     float* out = (float*)(inPyrSignal->slots) - 1;
838     UNROLL1_CODE(inPyrSignal->size, out, ++out; *out = tanh(*out);)
839     return inPyrSignal;
840 }
841 
signal_asin(VMGlobals * g,PyrObject * inPyrSignal)842 PyrObject* signal_asin(VMGlobals* g, PyrObject* inPyrSignal) {
843     float* in = (float*)(inPyrSignal->slots) - 1;
844     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
845     float* out = (float*)(outc->slots) - 1;
846     UNROLL1_CODE(inPyrSignal->size, out, *++out = asin(*++in);)
847     return outc;
848 }
849 
signal_acos(VMGlobals * g,PyrObject * inPyrSignal)850 PyrObject* signal_acos(VMGlobals* g, PyrObject* inPyrSignal) {
851     float* in = (float*)(inPyrSignal->slots) - 1;
852     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
853     float* out = (float*)(outc->slots) - 1;
854     UNROLL1_CODE(inPyrSignal->size, out, *++out = acos(*++in);)
855     return outc;
856 }
857 
signal_atan(VMGlobals * g,PyrObject * inPyrSignal)858 PyrObject* signal_atan(VMGlobals* g, PyrObject* inPyrSignal) {
859     float* in = (float*)(inPyrSignal->slots) - 1;
860     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
861     float* out = (float*)(outc->slots) - 1;
862     UNROLL1_CODE(inPyrSignal->size, out, *++out = atan(*++in);)
863     return outc;
864 }
865 
signal_exp(VMGlobals * g,PyrObject * inPyrSignal)866 PyrObject* signal_exp(VMGlobals* g, PyrObject* inPyrSignal) {
867     float* in = (float*)(inPyrSignal->slots) - 1;
868     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
869     float* out = (float*)(outc->slots) - 1;
870     UNROLL1_CODE(inPyrSignal->size, out, *++out = exp(*++in);)
871     return outc;
872 }
873 
signal_sqrt(VMGlobals * g,PyrObject * inPyrSignal)874 PyrObject* signal_sqrt(VMGlobals* g, PyrObject* inPyrSignal) {
875     float* in = (float*)(inPyrSignal->slots) - 1;
876     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
877     float* out = (float*)(outc->slots) - 1;
878     UNROLL1_CODE(inPyrSignal->size, out, *++out = sqrt(*++in);)
879     return outc;
880 }
881 
signal_distort(VMGlobals * g,PyrObject * inPyrSignal)882 PyrObject* signal_distort(VMGlobals* g, PyrObject* inPyrSignal) {
883     float* in = (float*)(inPyrSignal->slots) - 1;
884     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
885     float* out = (float*)(outc->slots) - 1;
886     float* endptr = out + inPyrSignal->size;
887     while (out < endptr) {
888         float z = *++in;
889         if (z < 0.f)
890             *++out = z / (1.f - z);
891         else
892             *++out = z / (1.f + z);
893     }
894     return outc;
895 }
896 
signal_softclip(VMGlobals * g,PyrObject * inPyrSignal)897 PyrObject* signal_softclip(VMGlobals* g, PyrObject* inPyrSignal) {
898     float* in = (float*)(inPyrSignal->slots) - 1;
899     PyrObject* outc = newPyrSignal(g, inPyrSignal->size);
900     float* out = (float*)(outc->slots) - 1;
901     float* endptr = out + inPyrSignal->size;
902     while (out < endptr) {
903         float z = *++in;
904         if (z < -0.5f)
905             *++out = (-z - .25f) / z;
906         else if (z > 0.5f)
907             *++out = (z - .25f) / z;
908         else
909             *++out = z;
910     }
911     return outc;
912 }
913 
914 
signal_rotate(VMGlobals * g,PyrObject * ina,int rot)915 PyrObject* signal_rotate(VMGlobals* g, PyrObject* ina, int rot) {
916     long i, j;
917     PyrObject* outc = newPyrSignal(g, ina->size);
918     float* a0 = (float*)(ina->slots) - 1;
919     //	float *a = a0 + sc_mod(rot, ina->size);
920     float* a = a0 + sc_mod(0 - rot, ina->size);
921     float* aend = a0 + ina->size;
922     float* c = (float*)(outc->slots) - 1;
923     long nsmps = outc->size;
924     for (i = 0, j = rot; i < nsmps; i++, j++) {
925         *++c = *++a;
926         if (a >= aend)
927             a = a0;
928     }
929     return outc;
930 }
931 
signal_reverse_range(PyrObject * ina,long start,long end)932 PyrObject* signal_reverse_range(PyrObject* ina, long start, long end) {
933     long size = ina->size;
934     long size2;
935     long i;
936     start = sc_max(0, start);
937     end = sc_min(end + 1, size);
938     size = end - start;
939     size2 = size >> 1;
940     float* a = (float*)(ina->slots) - 1 + start;
941     //	float *b = (float*)(ina->slots) - 1 + end;
942     float* b = (float*)(ina->slots) + end;
943     float temp;
944     for (i = 0; i < size2; ++i) {
945         temp = *++a;
946         *a = *--b;
947         *b = temp;
948     }
949     return ina;
950 }
951 
signal_normalize_range(PyrObject * ina,long start,long end)952 PyrObject* signal_normalize_range(PyrObject* ina, long start, long end) {
953     long size = ina->size;
954     long i;
955     float z, scale, maxlevel;
956     float *a0, *a;
957     start = sc_max(0, start);
958     end = sc_min(end + 1, size);
959     size = end - start;
960     a0 = (float*)(ina->slots) - 1 + start;
961     a = a0;
962     maxlevel = 0.f;
963     for (i = 0; i < size; ++i) {
964         z = fabs(*++a);
965         if (z > maxlevel)
966             maxlevel = z;
967     }
968     a = a0;
969     if (maxlevel != 0.f) {
970         scale = 1. / maxlevel;
971         for (i = 0; i < size; ++i) {
972             z = *++a;
973             *a = scale * z;
974         }
975     }
976     return ina;
977 }
978 
signal_invert_range(PyrObject * ina,long start,long end)979 PyrObject* signal_invert_range(PyrObject* ina, long start, long end) {
980     long size = ina->size;
981     long i;
982     float z;
983     start = sc_max(0, start);
984     end = sc_min(end, size);
985     size = end - start + 1;
986     float* a = (float*)(ina->slots) - 1 + start;
987 
988     for (i = 0; i < size; ++i) {
989         z = *++a;
990         *a = -z;
991     }
992     return ina;
993 }
994 
995 
signal_fade_range(PyrObject * ina,long start,long end,float lvl0,float lvl1)996 PyrObject* signal_fade_range(PyrObject* ina, long start, long end, float lvl0, float lvl1) {
997     long size = ina->size;
998     long i;
999     float z, level, slope;
1000     start = sc_max(0, start);
1001     end = sc_min(end + 1, size);
1002     size = end - start;
1003     float* a = (float*)(ina->slots) - 1 + start;
1004     slope = (lvl1 - lvl0) / size;
1005     level = lvl0;
1006     for (i = 0; i < size; ++i) {
1007         z = *++a;
1008         *a = z * level;
1009         level += slope;
1010     }
1011     return ina;
1012 }
1013 
1014 
signal_overdub(VMGlobals * g,PyrObject * ina,PyrObject * inb,long index)1015 PyrObject* signal_overdub(VMGlobals* g, PyrObject* ina, PyrObject* inb, long index) {
1016     float *a, *b;
1017     long len;
1018 
1019     if (index > 0) {
1020         a = (float*)(ina->slots) + index - 1;
1021         b = (float*)(inb->slots) - 1;
1022         len = sc_min(inb->size, ina->size - index);
1023     } else {
1024         a = (float*)(ina->slots) - 1;
1025         b = (float*)(inb->slots) - index - 1;
1026         len = sc_min(ina->size, inb->size + index);
1027     }
1028 
1029     UNROLL_CODE(len, a, *++a += *++b;);
1030 
1031     return ina;
1032 }
1033 
signal_overwrite(VMGlobals * g,PyrObject * ina,PyrObject * inb,long index)1034 PyrObject* signal_overwrite(VMGlobals* g, PyrObject* ina, PyrObject* inb, long index) {
1035     float *a, *b;
1036     long len;
1037     if (index > 0) {
1038         a = (float*)(ina->slots) + index - 1;
1039         b = (float*)(inb->slots) - 1;
1040         len = sc_min(inb->size, ina->size - index);
1041     } else {
1042         a = (float*)(ina->slots) - 1;
1043         b = (float*)(inb->slots) - index - 1;
1044         len = sc_min(ina->size, inb->size + index);
1045     }
1046 
1047     UNROLL_CODE(len, a, *++a = *++b;);
1048 
1049     return ina;
1050 }
1051