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 #include "SC_PlugIn.h"
23
24 #include <boost/utility/enable_if.hpp>
25 #include <boost/align/is_aligned.hpp>
26
27 #ifdef NOVA_SIMD
28 # include "simd_unary_arithmetic.hpp"
29 # include "simd_binary_arithmetic.hpp"
30 # include "simd_ternary_arithmetic.hpp"
31 # include "simd_math.hpp"
32 # include "simd_memory.hpp"
33 # include "softclip.hpp"
34 # include "simd_unit_conversion.hpp"
35
36 # include "function_attributes.h"
37
38 using nova::wrap_argument;
39
40 # define NOVA_WRAPPER(NAME, NOVANAME) \
41 FLATTEN void NAME##_nova(UnaryOpUGen* unit, int inNumSamples) { \
42 nova::NOVANAME##_vec_simd(OUT(0), IN(0), inNumSamples); \
43 }
44
45 # define NOVA_WRAPPER_CT_UNROLL(NAME, NOVANAME) \
46 FLATTEN void NAME##_nova(UnaryOpUGen* unit, int inNumSamples) { \
47 nova::NOVANAME##_vec_simd(OUT(0), IN(0), inNumSamples); \
48 } \
49 \
50 FLATTEN void NAME##_nova_64(UnaryOpUGen* unit, int inNumSamples) { \
51 nova::NOVANAME##_vec_simd<64>(OUT(0), IN(0)); \
52 }
53
54 struct sc_distort_functor {
operator ()sc_distort_functor55 template <typename FloatType> inline FloatType operator()(FloatType arg) const { return sc_distort(arg); }
56
operator ()sc_distort_functor57 template <typename FloatType> inline nova::vec<FloatType> operator()(nova::vec<FloatType> arg) const {
58 nova::vec<FloatType> one(1.f);
59 return arg * reciprocal(one + abs(arg));
60 }
61 };
62
63 struct sc_scurve_functor {
operator ()sc_scurve_functor64 template <typename FloatType> inline FloatType operator()(FloatType arg) const { return sc_scurve(arg); }
65
operator ()sc_scurve_functor66 template <typename FloatType> inline nova::vec<FloatType> operator()(nova::vec<FloatType> arg) const {
67 return perform(arg);
68 }
69
70 template <typename VecType>
performsc_scurve_functor71 inline typename boost::disable_if_c<VecType::has_compare_bitmask, VecType>::type perform(VecType arg) const {
72 typedef VecType vec;
73
74 vec result;
75 for (int i = 0; i != result.size; ++i)
76 result.set(i, sc_scurve(arg.get(i)));
77 return result;
78 }
79
80 template <typename VecType>
performsc_scurve_functor81 inline typename boost::enable_if_c<VecType::has_compare_bitmask, VecType>::type perform(VecType arg) const {
82 typedef VecType vec;
83 vec one(1.f);
84 vec zero(0.f);
85 vec two(2.f);
86 vec three(3.f);
87
88 vec result = (arg * arg) * (three - (two * arg));
89
90 vec boundLow = mask_lt(arg, zero);
91 vec boundHigh = mask_gt(arg, one);
92
93 result = select(result, zero, boundLow);
94 result = select(result, one, boundHigh);
95
96 return result;
97 }
98 };
99
100
101 namespace nova {
102 NOVA_SIMD_DEFINE_UNARY_WRAPPER(distort, sc_distort_functor)
103 NOVA_SIMD_DEFINE_UNARY_WRAPPER(scurve, sc_scurve_functor)
104 }
105 #endif
106
107 using namespace std; // for math functions
108
109 static InterfaceTable* ft;
110
111 //////////////////////////////////////////////////////////////////////////////////////////////////
112
113
114 /* special unary math operators */
115 enum {
116 opNeg,
117 opNot,
118 opIsNil,
119 opNotNil,
120 opBitNot,
121 opAbs,
122 opAsFloat,
123 opAsInteger,
124 opCeil,
125 opFloor,
126 opFrac,
127 opSign,
128 opSquared,
129 opCubed,
130 opSqrt,
131 opExp,
132 opRecip,
133 opMIDICPS,
134 opCPSMIDI,
135
136 opMIDIRatio,
137 opRatioMIDI,
138 opDbAmp,
139 opAmpDb,
140 opOctCPS,
141 opCPSOct,
142 opLog,
143 opLog2,
144 opLog10,
145 opSin,
146 opCos,
147 opTan,
148 opArcSin,
149 opArcCos,
150 opArcTan,
151 opSinH,
152 opCosH,
153 opTanH,
154
155 opRand,
156 opRand2,
157 opLinRand,
158 opBiLinRand,
159 opSum3Rand,
160
161 opDistort,
162 opSoftClip,
163 opCoin,
164
165 opDigitValue,
166 opSilence,
167 opThru,
168 opRectWindow,
169 opHanWindow,
170 opWelchWindow,
171 opTriWindow,
172
173 opRamp,
174 opSCurve,
175
176 opNumUnarySelectors
177 };
178
179
180 struct UnaryOpUGen : public Unit {};
181
182 typedef void (*UnaryOpFunc)(UnaryOpUGen* unit, int inNumSamples);
183
184 extern "C" {
185
186 void UnaryOpUGen_Ctor(UnaryOpUGen* unit);
187 }
188
189 bool ChooseOperatorFunc(UnaryOpUGen* unit);
190
UnaryOpUGen_Ctor(UnaryOpUGen * unit)191 void UnaryOpUGen_Ctor(UnaryOpUGen* unit) {
192 bool initialized = ChooseOperatorFunc(unit);
193 if (!initialized)
194 (unit->mCalcFunc)(unit, 1);
195 }
196
197 ////////////////////////////////////////////////////////////////////////////////////////////////////////
198
199 #define DEFINE_UNARY_OP_FUNCS(name, function) \
200 extern "C" void name##_a(UnaryOpUGen* unit, int inNumSamples) { \
201 float* out = ZOUT(0); \
202 float* a = ZIN(0); \
203 \
204 LOOP1(inNumSamples, ZXP(out) = function(ZXP(a));); \
205 } \
206 \
207 extern "C" void name##_1(UnaryOpUGen* unit, int inNumSamples) { ZOUT0(0) = function(ZIN0(0)); } \
208 \
209 extern "C" void name##_d(UnaryOpUGen* unit, int inNumSamples) { \
210 if (inNumSamples) { \
211 float x = DEMANDINPUT_A(0, inNumSamples); \
212 OUT0(0) = sc_isnan(x) ? NAN : function(x); \
213 } else { \
214 RESETINPUT(0); \
215 } \
216 }
217
sc_invert(F x)218 template <typename F> inline F sc_invert(F x) { return -x; }
219
DEFINE_UNARY_OP_FUNCS(invert,sc_invert)220 DEFINE_UNARY_OP_FUNCS(invert, sc_invert)
221
222 #ifdef NOVA_SIMD
223 FLATTEN void invert_nova(UnaryOpUGen* unit, int inNumSamples) {
224 nova::minus_vec_simd(OUT(0), 0.f, IN(0), inNumSamples);
225 }
226
invert_nova_64(UnaryOpUGen * unit,int inNumSamples)227 FLATTEN void invert_nova_64(UnaryOpUGen* unit, int inNumSamples) { nova::minus_vec_simd<64>(OUT(0), 0.f, IN(0)); }
228
229 #endif
230
231
sc_not(F x)232 template <typename F> inline F sc_not(F x) { return x > 0.f ? 0.f : 1.f; }
233
DEFINE_UNARY_OP_FUNCS(not,sc_not)234 DEFINE_UNARY_OP_FUNCS(not, sc_not)
235 DEFINE_UNARY_OP_FUNCS(bitNot, sc_bitNot)
236
237
238 void zero_a(UnaryOpUGen* unit, int inNumSamples) {
239 float* out = ZOUT(0);
240
241 ZClear(inNumSamples, out);
242 }
243
thru_a(UnaryOpUGen * unit,int inNumSamples)244 void thru_a(UnaryOpUGen* unit, int inNumSamples) {
245 float* out = ZOUT(0);
246 float* a = ZIN(0);
247
248 ZCopy(inNumSamples, out, a);
249 }
250
DEFINE_UNARY_OP_FUNCS(abs,std::abs)251 DEFINE_UNARY_OP_FUNCS(abs, std::abs)
252
253 #ifdef NOVA_SIMD
254 FLATTEN void zero_nova(UnaryOpUGen* unit, int inNumSamples) { nova::zerovec_simd(OUT(0), inNumSamples); }
255
zero_nova_64(UnaryOpUGen * unit,int inNumSamples)256 FLATTEN void zero_nova_64(UnaryOpUGen* unit, int inNumSamples) { nova::zerovec_simd<64>(OUT(0)); }
257
thru_nova(UnaryOpUGen * unit,int inNumSamples)258 FLATTEN void thru_nova(UnaryOpUGen* unit, int inNumSamples) { nova::copyvec_simd(OUT(0), IN(0), inNumSamples); }
259
thru_nova_64(UnaryOpUGen * unit,int inNumSamples)260 FLATTEN void thru_nova_64(UnaryOpUGen* unit, int inNumSamples) { nova::copyvec_simd<64>(OUT(0), IN(0)); }
261
abs_nova(UnaryOpUGen * unit,int inNumSamples)262 FLATTEN void abs_nova(UnaryOpUGen* unit, int inNumSamples) { nova::abs_vec_simd(OUT(0), IN(0), inNumSamples); }
263
abs_nova_64(UnaryOpUGen * unit,int inNumSamples)264 FLATTEN void abs_nova_64(UnaryOpUGen* unit, int inNumSamples) { nova::abs_vec_simd<64>(OUT(0), IN(0)); }
265 #endif
266
DEFINE_UNARY_OP_FUNCS(recip,sc_reciprocal)267 DEFINE_UNARY_OP_FUNCS(recip, sc_reciprocal)
268
269 #ifdef NOVA_SIMD
270 FLATTEN void recip_nova(UnaryOpUGen* unit, int inNumSamples) { nova::reciprocal_vec_simd(OUT(0), IN(0), inNumSamples); }
271
recip_nova_64(UnaryOpUGen * unit,int inNumSamples)272 FLATTEN void recip_nova_64(UnaryOpUGen* unit, int inNumSamples) { nova::reciprocal_vec_simd<64>(OUT(0), IN(0)); }
273 #endif
274
275
DEFINE_UNARY_OP_FUNCS(floor,floor)276 DEFINE_UNARY_OP_FUNCS(floor, floor)
277 DEFINE_UNARY_OP_FUNCS(ceil, ceil)
278
279 #ifdef NOVA_SIMD
280 NOVA_WRAPPER_CT_UNROLL(floor, floor)
281 NOVA_WRAPPER_CT_UNROLL(ceil, ceil)
282 #endif
283
284 DEFINE_UNARY_OP_FUNCS(sin, sin)
285 DEFINE_UNARY_OP_FUNCS(cos, cos)
286 DEFINE_UNARY_OP_FUNCS(tan, tan)
287
288 DEFINE_UNARY_OP_FUNCS(asin, asin)
289 DEFINE_UNARY_OP_FUNCS(acos, acos)
290 DEFINE_UNARY_OP_FUNCS(atan, atan)
291
292 DEFINE_UNARY_OP_FUNCS(sinh, sinh)
293 DEFINE_UNARY_OP_FUNCS(cosh, cosh)
294 DEFINE_UNARY_OP_FUNCS(tanh, tanh)
295
296
297 #ifdef NOVA_SIMD
298 NOVA_WRAPPER(sin, sin)
299 NOVA_WRAPPER(cos, cos)
300 NOVA_WRAPPER(tan, tan)
301 NOVA_WRAPPER(asin, asin)
302 NOVA_WRAPPER(acos, acos)
303 NOVA_WRAPPER(atan, atan)
304 NOVA_WRAPPER(tanh, tanh)
305 #endif
306
307
308 DEFINE_UNARY_OP_FUNCS(log, std::log)
309 DEFINE_UNARY_OP_FUNCS(log2, sc_log2)
310 DEFINE_UNARY_OP_FUNCS(log10, sc_log10)
311 DEFINE_UNARY_OP_FUNCS(exp, exp)
312
313 #ifdef NOVA_SIMD
314 NOVA_WRAPPER(log, log)
315 NOVA_WRAPPER(log2, log2)
316 NOVA_WRAPPER(log10, log10)
317 NOVA_WRAPPER(exp, exp)
318 #endif
319
320 DEFINE_UNARY_OP_FUNCS(sqrt, sc_sqrt)
321
322 #ifdef NOVA_SIMD
323 NOVA_WRAPPER_CT_UNROLL(sqrt, signed_sqrt)
324 #endif
325
326 DEFINE_UNARY_OP_FUNCS(ampdb, sc_ampdb)
327 DEFINE_UNARY_OP_FUNCS(dbamp, sc_dbamp)
328 DEFINE_UNARY_OP_FUNCS(midicps, sc_midicps)
329 DEFINE_UNARY_OP_FUNCS(cpsmidi, sc_cpsmidi)
330 DEFINE_UNARY_OP_FUNCS(midiratio, sc_midiratio)
331 DEFINE_UNARY_OP_FUNCS(ratiomidi, sc_ratiomidi)
332 DEFINE_UNARY_OP_FUNCS(cpsoct, sc_cpsoct)
333 DEFINE_UNARY_OP_FUNCS(octcps, sc_octcps)
334
335 #ifdef NOVA_SIMD
336 NOVA_WRAPPER(ampdb, amp2db)
337 NOVA_WRAPPER(dbamp, db2amp)
338 NOVA_WRAPPER(midicps, midi2freq)
339 NOVA_WRAPPER(cpsmidi, freq2midi)
340 NOVA_WRAPPER(midiratio, midi2ratio)
341 NOVA_WRAPPER(ratiomidi, ratio2midi)
342 NOVA_WRAPPER(cpsoct, freq2oct)
343 NOVA_WRAPPER(octcps, oct2freq)
344 #endif
345
346
347 DEFINE_UNARY_OP_FUNCS(frac, sc_frac)
348 #ifdef NOVA_SIMD
349 NOVA_WRAPPER_CT_UNROLL(frac, frac)
350 #endif
351
352
353 DEFINE_UNARY_OP_FUNCS(squared, sc_squared)
354 #ifdef NOVA_SIMD
355 NOVA_WRAPPER_CT_UNROLL(squared, square)
356 #endif
357
358
359 DEFINE_UNARY_OP_FUNCS(cubed, sc_cubed)
360 #ifdef NOVA_SIMD
361 NOVA_WRAPPER_CT_UNROLL(cubed, cube)
362 #endif
363
364 DEFINE_UNARY_OP_FUNCS(sign, sc_sign)
365
366 #ifdef NOVA_SIMD
367 NOVA_WRAPPER_CT_UNROLL(sign, sgn)
368 #endif
369
370 DEFINE_UNARY_OP_FUNCS(distort, sc_distort)
371
372 #ifdef NOVA_SIMD
373 NOVA_WRAPPER_CT_UNROLL(distort, distort)
374 #endif
375
376 DEFINE_UNARY_OP_FUNCS(distortneg, sc_distortneg)
377 DEFINE_UNARY_OP_FUNCS(softclip, sc_softclip)
378
379 #ifdef NOVA_SIMD
380 NOVA_WRAPPER_CT_UNROLL(softclip, softclip)
381 #endif
382
383 DEFINE_UNARY_OP_FUNCS(rectwindow, sc_rectwindow)
384 DEFINE_UNARY_OP_FUNCS(hanwindow, sc_hanwindow)
385 DEFINE_UNARY_OP_FUNCS(welwindow, sc_welwindow)
386 DEFINE_UNARY_OP_FUNCS(triwindow, sc_triwindow)
387
388 DEFINE_UNARY_OP_FUNCS(scurve, sc_scurve)
389 #ifdef NOVA_SIMD
390 NOVA_WRAPPER_CT_UNROLL(scurve, scurve)
391 #endif
392
393 DEFINE_UNARY_OP_FUNCS(ramp, sc_ramp)
394
395
396 #ifdef NOVA_SIMD
397 FLATTEN void ramp_nova(UnaryOpUGen* unit, int inNumSamples) {
398 nova::clip_vec_simd(OUT(0), wrap_argument(IN(0)), wrap_argument(0.f), wrap_argument(1.f), inNumSamples);
399 }
400
ramp_nova_64(UnaryOpUGen * unit,int inNumSamples)401 FLATTEN void ramp_nova_64(UnaryOpUGen* unit, int inNumSamples) {
402 nova::clip_vec_simd<64>(OUT(0), wrap_argument(IN(0)), wrap_argument(0.f), wrap_argument(1.f));
403 }
404 #endif
405
406 ////////////////////////////////////////////////////////////////////////////////////////////////////////
407
zero_d(UnaryOpUGen * unit,int inNumSamples)408 void zero_d(UnaryOpUGen* unit, int inNumSamples) {
409 if (inNumSamples) {
410 float x = DEMANDINPUT_A(0, inNumSamples);
411 OUT0(0) = sc_isnan(x) ? NAN : 0.f;
412 } else {
413 RESETINPUT(0);
414 }
415 }
416
thru_d(UnaryOpUGen * unit,int inNumSamples)417 void thru_d(UnaryOpUGen* unit, int inNumSamples) {
418 if (inNumSamples) {
419 float x = DEMANDINPUT_A(0, inNumSamples);
420 OUT0(0) = sc_isnan(x) ? NAN : (x);
421 } else {
422 RESETINPUT(0);
423 }
424 }
425
426
427 ////////////////////////////////////////////////////////////////////////////////////////////////////////
428
429 #define DEFINE_UNARY_OP_RANDOM_FUNCS(name, function) \
430 extern "C" void name##_a(UnaryOpUGen* unit, int inNumSamples) { \
431 float* out = ZOUT(0); \
432 float* a = ZIN(0); \
433 RGen& rgen = *unit->mParent->mRGen; \
434 LOOP1(inNumSamples, ZXP(out) = rgen.function() * ZXP(a);); \
435 } \
436 \
437 extern "C" void name##_1(UnaryOpUGen* unit, int inNumSamples) { \
438 RGen& rgen = *unit->mParent->mRGen; \
439 ZOUT0(0) = rgen.function() * ZIN0(0); \
440 } \
441 \
442 extern "C" void name##_d(UnaryOpUGen* unit, int inNumSamples) { \
443 if (inNumSamples) { \
444 float x = DEMANDINPUT_A(0, inNumSamples); \
445 RGen& rgen = *unit->mParent->mRGen; \
446 OUT0(0) = sc_isnan(x) ? NAN : (rgen.function() * x); \
447 } else { \
448 RESETINPUT(0); \
449 } \
450 }
451
452 DEFINE_UNARY_OP_RANDOM_FUNCS(rand, frand);
453 DEFINE_UNARY_OP_RANDOM_FUNCS(rand2, frand2);
454 DEFINE_UNARY_OP_RANDOM_FUNCS(linrand, flinrand);
455 DEFINE_UNARY_OP_RANDOM_FUNCS(bilinrand, fbilinrand);
456 DEFINE_UNARY_OP_RANDOM_FUNCS(sum3rand, fsum3rand);
457
458
coin_a(UnaryOpUGen * unit,int inNumSamples)459 void coin_a(UnaryOpUGen* unit, int inNumSamples) {
460 float* out = ZOUT(0);
461 float* a = ZIN(0);
462 RGen& rgen = *unit->mParent->mRGen;
463 LOOP1(inNumSamples, ZXP(out) = (rgen.frand() < ZXP(a)) ? 1.f : 0.f;);
464 }
465
coin_1(UnaryOpUGen * unit,int inNumSamples)466 void coin_1(UnaryOpUGen* unit, int inNumSamples) {
467 RGen& rgen = *unit->mParent->mRGen;
468 float x = ZIN0(0);
469 ZOUT0(0) = (rgen.frand() < x) ? 1.f : 0.f;
470 }
471
coin_d(UnaryOpUGen * unit,int inNumSamples)472 void coin_d(UnaryOpUGen* unit, int inNumSamples) {
473 if (inNumSamples) {
474 float x = DEMANDINPUT_A(0, inNumSamples);
475 RGen& rgen = *unit->mParent->mRGen;
476 float val = (rgen.frand() < x) ? 1.f : 0.f;
477 OUT0(0) = sc_isnan(x) ? NAN : val;
478 } else {
479 RESETINPUT(0);
480 }
481 }
482
483
484 ////////////////////////////////////////////////////////////////////////////////////////////////////////
485
ChooseNormalFunc(UnaryOpUGen * unit)486 static UnaryOpFunc ChooseNormalFunc(UnaryOpUGen* unit) {
487 void (*func)(UnaryOpUGen * unit, int inNumSamples);
488
489 switch (unit->mSpecialIndex) {
490 case opSilence:
491 func = &zero_a;
492 break;
493 case opThru:
494 func = &thru_a;
495 break;
496 case opNeg:
497 func = &invert_a;
498 break;
499 case opNot:
500 func = ¬_a;
501 break;
502 case opBitNot:
503 func = &bitNot_a;
504 break;
505 case opAbs:
506 func = &abs_a;
507 break;
508 case opCeil:
509 func = &ceil_a;
510 break;
511 case opFloor:
512 func = &floor_a;
513 break;
514 case opFrac:
515 func = &frac_a;
516 break;
517 case opSign:
518 func = &sign_a;
519 break;
520 case opSquared:
521 func = &squared_a;
522 break;
523 case opCubed:
524 func = &cubed_a;
525 break;
526 case opSqrt:
527 func = &sqrt_a;
528 break;
529 case opExp:
530 func = &exp_a;
531 break;
532 case opRecip:
533 func = &recip_a;
534 break;
535 case opMIDICPS:
536 func = &midicps_a;
537 break;
538 case opCPSMIDI:
539 func = &cpsmidi_a;
540 break;
541
542 case opMIDIRatio:
543 func = &midiratio_a;
544 break;
545 case opRatioMIDI:
546 func = &ratiomidi_a;
547 break;
548 case opDbAmp:
549 func = &dbamp_a;
550 break;
551 case opAmpDb:
552 func = &db_a;
553 break;
554 case opOctCPS:
555 func = &octcps_a;
556 break;
557 case opCPSOct:
558 func = &cpsoct_a;
559 break;
560 case opLog:
561 func = &log_a;
562 break;
563 case opLog2:
564 func = &log2_a;
565 break;
566 case opLog10:
567 func = &log10_a;
568 break;
569 case opSin:
570 func = &sin_a;
571 break;
572 case opCos:
573 func = &cos_a;
574 break;
575 case opTan:
576 func = &tan_a;
577 break;
578 case opArcSin:
579 func = &asin_a;
580 break;
581 case opArcCos:
582 func = &acos_a;
583 break;
584 case opArcTan:
585 func = &atan_a;
586 break;
587 case opSinH:
588 func = &sinh_a;
589 break;
590 case opCosH:
591 func = &cosh_a;
592 break;
593 case opTanH:
594 func = &tanh_a;
595 break;
596
597 case opRand:
598 func = &rand_a;
599 break;
600 case opRand2:
601 func = &rand2_a;
602 break;
603 case opLinRand:
604 func = &linrand_a;
605 break;
606 case opBiLinRand:
607 func = &bilinrand_a;
608 break;
609 case opSum3Rand:
610 func = &sum3rand_a;
611 break;
612 case opCoin:
613 func = &coin_a;
614 break;
615
616 case opDistort:
617 func = &distort_a;
618 break;
619 case opSoftClip:
620 func = &softclip_a;
621 break;
622
623 case opRectWindow:
624 func = &rectwindow_a;
625 break;
626 case opHanWindow:
627 func = &hanwindow_a;
628 break;
629 case opWelchWindow:
630 func = &welwindow_a;
631 break;
632 case opTriWindow:
633 func = &triwindow_a;
634 break;
635
636 case opSCurve:
637 func = &scurve_a;
638 break;
639 case opRamp:
640 func = &ramp_a;
641 break;
642
643 default:
644 func = &thru_a;
645 break;
646 }
647 return func;
648 }
649
ChooseOneFunc(UnaryOpUGen * unit)650 static UnaryOpFunc ChooseOneFunc(UnaryOpUGen* unit) {
651 void (*func)(UnaryOpUGen * unit, int inNumSamples);
652
653 switch (unit->mSpecialIndex) {
654 case opSilence:
655 func = &zero_a;
656 break;
657 case opThru:
658 func = &thru_a;
659 break;
660 case opNeg:
661 func = &invert_1;
662 break;
663 case opNot:
664 func = ¬_1;
665 break;
666 case opBitNot:
667 func = &bitNot_1;
668 break;
669 case opAbs:
670 func = &abs_1;
671 break;
672 case opCeil:
673 func = &ceil_1;
674 break;
675 case opFloor:
676 func = &floor_1;
677 break;
678 case opFrac:
679 func = &frac_1;
680 break;
681 case opSign:
682 func = &sign_1;
683 break;
684 case opSquared:
685 func = &squared_1;
686 break;
687 case opCubed:
688 func = &cubed_1;
689 break;
690 case opSqrt:
691 func = &sqrt_1;
692 break;
693 case opExp:
694 func = &exp_1;
695 break;
696 case opRecip:
697 func = &recip_1;
698 break;
699 case opMIDICPS:
700 func = &midicps_1;
701 break;
702 case opCPSMIDI:
703 func = &cpsmidi_1;
704 break;
705
706 case opMIDIRatio:
707 func = &midiratio_1;
708 break;
709 case opRatioMIDI:
710 func = &ratiomidi_1;
711 break;
712 case opDbAmp:
713 func = &dbamp_1;
714 break;
715 case opAmpDb:
716 func = &db_1;
717 break;
718 case opOctCPS:
719 func = &octcps_1;
720 break;
721 case opCPSOct:
722 func = &cpsoct_1;
723 break;
724 case opLog:
725 func = &log_1;
726 break;
727 case opLog2:
728 func = &log2_1;
729 break;
730 case opLog10:
731 func = &log10_1;
732 break;
733 case opSin:
734 func = &sin_1;
735 break;
736 case opCos:
737 func = &cos_1;
738 break;
739 case opTan:
740 func = &tan_1;
741 break;
742 case opArcSin:
743 func = &asin_1;
744 break;
745 case opArcCos:
746 func = &acos_1;
747 break;
748 case opArcTan:
749 func = &atan_1;
750 break;
751 case opSinH:
752 func = &sinh_1;
753 break;
754 case opCosH:
755 func = &cosh_1;
756 break;
757 case opTanH:
758 func = &tanh_1;
759 break;
760
761 case opRand:
762 func = &rand_1;
763 break;
764 case opRand2:
765 func = &rand2_1;
766 break;
767 case opLinRand:
768 func = &linrand_1;
769 break;
770 case opBiLinRand:
771 func = &bilinrand_1;
772 break;
773 case opSum3Rand:
774 func = &sum3rand_1;
775 break;
776 case opCoin:
777 func = &coin_1;
778 break;
779
780 case opDistort:
781 func = &distort_1;
782 break;
783 case opSoftClip:
784 func = &softclip_1;
785 break;
786
787 case opRectWindow:
788 func = &rectwindow_1;
789 break;
790 case opHanWindow:
791 func = &hanwindow_1;
792 break;
793 case opWelchWindow:
794 func = &welwindow_1;
795 break;
796 case opTriWindow:
797 func = &triwindow_1;
798 break;
799
800 case opSCurve:
801 func = &scurve_1;
802 break;
803 case opRamp:
804 func = &ramp_1;
805 break;
806
807 default:
808 func = &thru_a;
809 break;
810 }
811 return func;
812 }
813
814
ChooseDemandFunc(UnaryOpUGen * unit)815 static UnaryOpFunc ChooseDemandFunc(UnaryOpUGen* unit) {
816 void (*func)(UnaryOpUGen * unit, int inNumSamples);
817
818 switch (unit->mSpecialIndex) {
819 case opSilence:
820 func = &zero_d;
821 break;
822 case opThru:
823 func = &thru_d;
824 break;
825 case opNeg:
826 func = &invert_d;
827 break;
828 case opNot:
829 func = ¬_d;
830 break;
831 case opBitNot:
832 func = &bitNot_d;
833 break;
834 case opAbs:
835 func = &abs_d;
836 break;
837 case opCeil:
838 func = &ceil_d;
839 break;
840 case opFloor:
841 func = &floor_d;
842 break;
843 case opFrac:
844 func = &frac_d;
845 break;
846 case opSign:
847 func = &sign_d;
848 break;
849 case opSquared:
850 func = &squared_d;
851 break;
852 case opCubed:
853 func = &cubed_d;
854 break;
855 case opSqrt:
856 func = &sqrt_d;
857 break;
858 case opExp:
859 func = &exp_d;
860 break;
861 case opRecip:
862 func = &recip_d;
863 break;
864 case opMIDICPS:
865 func = &midicps_d;
866 break;
867 case opCPSMIDI:
868 func = &cpsmidi_d;
869 break;
870
871 case opMIDIRatio:
872 func = &midiratio_d;
873 break;
874 case opRatioMIDI:
875 func = &ratiomidi_d;
876 break;
877 case opDbAmp:
878 func = &dbamp_d;
879 break;
880 case opAmpDb:
881 func = &db_d;
882 break;
883 case opOctCPS:
884 func = &octcps_d;
885 break;
886 case opCPSOct:
887 func = &cpsoct_d;
888 break;
889 case opLog:
890 func = &log_d;
891 break;
892 case opLog2:
893 func = &log2_d;
894 break;
895 case opLog10:
896 func = &log10_d;
897 break;
898 case opSin:
899 func = &sin_d;
900 break;
901 case opCos:
902 func = &cos_d;
903 break;
904 case opTan:
905 func = &tan_d;
906 break;
907 case opArcSin:
908 func = &asin_d;
909 break;
910 case opArcCos:
911 func = &acos_d;
912 break;
913 case opArcTan:
914 func = &atan_d;
915 break;
916 case opSinH:
917 func = &sinh_d;
918 break;
919 case opCosH:
920 func = &cosh_d;
921 break;
922 case opTanH:
923 func = &tanh_d;
924 break;
925
926 case opRand:
927 func = &rand_d;
928 break;
929 case opRand2:
930 func = &rand2_d;
931 break;
932 case opLinRand:
933 func = &linrand_d;
934 break;
935 case opBiLinRand:
936 func = &bilinrand_d;
937 break;
938 case opSum3Rand:
939 func = &sum3rand_d;
940 break;
941 case opCoin:
942 func = &coin_d;
943 break;
944
945 case opDistort:
946 func = &distort_d;
947 break;
948 case opSoftClip:
949 func = &softclip_d;
950 break;
951
952 case opRectWindow:
953 func = &rectwindow_d;
954 break;
955 case opHanWindow:
956 func = &hanwindow_d;
957 break;
958 case opWelchWindow:
959 func = &welwindow_d;
960 break;
961 case opTriWindow:
962 func = &triwindow_d;
963 break;
964
965 case opSCurve:
966 func = &scurve_d;
967 break;
968 case opRamp:
969 func = &ramp_d;
970 break;
971
972
973 default:
974 func = &thru_d;
975 break;
976 }
977 return func;
978 }
979
980 #ifdef NOVA_SIMD
981
ChooseNovaSimdFunc(UnaryOpUGen * unit)982 static UnaryOpFunc ChooseNovaSimdFunc(UnaryOpUGen* unit) {
983 void (*func)(UnaryOpUGen * unit, int inNumSamples);
984
985 if (BUFLENGTH == 64) {
986 switch (unit->mSpecialIndex) {
987 case opSilence:
988 return &zero_nova_64;
989 case opThru:
990 func = &thru_nova;
991 break;
992 case opNeg:
993 return &invert_nova_64;
994 case opNot:
995 func = ¬_a;
996 break;
997 case opBitNot:
998 func = &bitNot_a;
999 break;
1000 case opAbs:
1001 return &abs_nova_64;
1002 case opCeil:
1003 func = &ceil_nova_64;
1004 break;
1005 case opFloor:
1006 func = &floor_nova_64;
1007 break;
1008 case opFrac:
1009 func = &frac_nova_64;
1010 break;
1011 case opSign:
1012 return &sign_nova_64;
1013 case opSquared:
1014 return &squared_nova_64;
1015 case opCubed:
1016 return &cubed_nova_64;
1017 case opSqrt:
1018 func = &sqrt_nova_64;
1019 break;
1020 case opExp:
1021 func = &exp_nova;
1022 break;
1023 case opRecip:
1024 return &recip_nova_64;
1025 case opMIDICPS:
1026 func = &midicps_nova;
1027 break;
1028 case opCPSMIDI:
1029 func = &cpsmidi_nova;
1030 break;
1031 case opMIDIRatio:
1032 func = &midiratio_nova;
1033 break;
1034 case opRatioMIDI:
1035 func = &ratiomidi_nova;
1036 break;
1037 case opDbAmp:
1038 func = &dbamp_nova;
1039 break;
1040 case opAmpDb:
1041 func = &db_nova;
1042 break;
1043 case opOctCPS:
1044 func = &octcps_nova;
1045 break;
1046 case opCPSOct:
1047 func = &cpsoct_nova;
1048 break;
1049 case opLog:
1050 func = &log_nova;
1051 break;
1052 case opLog2:
1053 func = &log2_nova;
1054 break;
1055 case opLog10:
1056 func = &log10_nova;
1057 break;
1058 case opSin:
1059 func = &sin_nova;
1060 break;
1061 case opCos:
1062 func = &cos_nova;
1063 break;
1064 case opTan:
1065 func = &tan_nova;
1066 break;
1067 case opArcSin:
1068 func = &asin_nova;
1069 break;
1070 case opArcCos:
1071 func = &acos_nova;
1072 break;
1073 case opArcTan:
1074 func = &atan_nova;
1075 break;
1076 case opSinH:
1077 func = &sinh_a;
1078 break;
1079 case opCosH:
1080 func = &cosh_a;
1081 break;
1082 case opTanH:
1083 func = &tanh_nova;
1084 break;
1085
1086 case opRand:
1087 func = &rand_a;
1088 break;
1089 case opRand2:
1090 func = &rand2_a;
1091 break;
1092 case opLinRand:
1093 func = &linrand_a;
1094 break;
1095 case opBiLinRand:
1096 func = &bilinrand_a;
1097 break;
1098 case opSum3Rand:
1099 func = &sum3rand_a;
1100 break;
1101 case opCoin:
1102 func = &coin_a;
1103 break;
1104
1105 case opDistort:
1106 func = &distort_nova_64;
1107 break;
1108 case opSoftClip:
1109 func = &softclip_nova_64;
1110 break;
1111
1112 case opRectWindow:
1113 func = &rectwindow_a;
1114 break;
1115 case opHanWindow:
1116 func = &hanwindow_a;
1117 break;
1118 case opWelchWindow:
1119 func = &welwindow_a;
1120 break;
1121 case opTriWindow:
1122 func = &triwindow_a;
1123 break;
1124
1125 case opSCurve:
1126 func = &scurve_nova_64;
1127 break;
1128 case opRamp:
1129 return &ramp_nova_64;
1130
1131 default:
1132 return &thru_nova_64;
1133 }
1134 return func;
1135 }
1136 switch (unit->mSpecialIndex) {
1137 case opSilence:
1138 func = &zero_nova;
1139 break;
1140 case opThru:
1141 func = &thru_nova;
1142 break;
1143 case opNeg:
1144 func = &invert_nova;
1145 break;
1146 case opNot:
1147 func = ¬_a;
1148 break;
1149 case opBitNot:
1150 func = &bitNot_a;
1151 break;
1152 case opAbs:
1153 func = &abs_nova;
1154 break;
1155 case opCeil:
1156 func = &ceil_nova;
1157 break;
1158 case opFloor:
1159 func = &floor_nova;
1160 break;
1161 case opFrac:
1162 func = &frac_nova;
1163 break;
1164 case opSign:
1165 func = &sign_nova;
1166 break;
1167 case opSquared:
1168 func = &squared_nova;
1169 break;
1170 case opCubed:
1171 func = &cubed_nova;
1172 break;
1173 case opSqrt:
1174 func = &sqrt_nova;
1175 break;
1176 case opExp:
1177 func = &exp_nova;
1178 break;
1179 case opRecip:
1180 func = &recip_nova;
1181 break;
1182 case opMIDICPS:
1183 func = &midicps_nova;
1184 break;
1185 case opCPSMIDI:
1186 func = &cpsmidi_nova;
1187 break;
1188 case opMIDIRatio:
1189 func = &midiratio_nova;
1190 break;
1191 case opRatioMIDI:
1192 func = &ratiomidi_nova;
1193 break;
1194 case opDbAmp:
1195 func = &dbamp_nova;
1196 break;
1197 case opAmpDb:
1198 func = &db_nova;
1199 break;
1200 case opOctCPS:
1201 func = &octcps_nova;
1202 break;
1203 case opCPSOct:
1204 func = &cpsoct_nova;
1205 break;
1206 case opLog:
1207 func = &log_nova;
1208 break;
1209 case opLog2:
1210 func = &log2_nova;
1211 break;
1212 case opLog10:
1213 func = &log10_nova;
1214 break;
1215 case opSin:
1216 func = &sin_nova;
1217 break;
1218 case opCos:
1219 func = &cos_nova;
1220 break;
1221 case opTan:
1222 func = &tan_nova;
1223 break;
1224 case opArcSin:
1225 func = &asin_nova;
1226 break;
1227 case opArcCos:
1228 func = &acos_nova;
1229 break;
1230 case opArcTan:
1231 func = &atan_nova;
1232 break;
1233 case opSinH:
1234 func = &sinh_a;
1235 break;
1236 case opCosH:
1237 func = &cosh_a;
1238 break;
1239 case opTanH:
1240 func = &tanh_nova;
1241 break;
1242
1243 case opRand:
1244 func = &rand_a;
1245 break;
1246 case opRand2:
1247 func = &rand2_a;
1248 break;
1249 case opLinRand:
1250 func = &linrand_a;
1251 break;
1252 case opBiLinRand:
1253 func = &bilinrand_a;
1254 break;
1255 case opSum3Rand:
1256 func = &sum3rand_a;
1257 break;
1258 case opCoin:
1259 func = &coin_a;
1260 break;
1261
1262 case opDistort:
1263 func = &distort_nova;
1264 break;
1265 case opSoftClip:
1266 func = &softclip_nova;
1267 break;
1268
1269 case opRectWindow:
1270 func = &rectwindow_a;
1271 break;
1272 case opHanWindow:
1273 func = &hanwindow_a;
1274 break;
1275 case opWelchWindow:
1276 func = &welwindow_a;
1277 break;
1278 case opTriWindow:
1279 func = &triwindow_a;
1280 break;
1281
1282 case opSCurve:
1283 func = &scurve_nova;
1284 break;
1285 case opRamp:
1286 func = &ramp_nova;
1287 break;
1288
1289 default:
1290 func = &thru_nova;
1291 break;
1292 }
1293 return func;
1294 }
1295 #endif
1296
ChooseOperatorFunc(UnaryOpUGen * unit)1297 bool ChooseOperatorFunc(UnaryOpUGen* unit) {
1298 // Print("->ChooseOperatorFunc %d\n", unit->mSpecialIndex);
1299 UnaryOpFunc func;
1300 bool ret = false;
1301 if (unit->mCalcRate == calc_DemandRate) {
1302 func = ChooseDemandFunc(unit);
1303 } else if (BUFLENGTH == 1) {
1304 func = ChooseOneFunc(unit);
1305 #if defined(NOVA_SIMD)
1306 } else if (boost::alignment::is_aligned(BUFLENGTH, 16)) {
1307 /* select normal function for initialization */
1308 func = ChooseNormalFunc(unit);
1309 func(unit, 1);
1310
1311 /* select simd function */
1312 func = ChooseNovaSimdFunc(unit);
1313 ret = true;
1314 #endif
1315 } else {
1316 func = ChooseNormalFunc(unit);
1317 }
1318 unit->mCalcFunc = (UnitCalcFunc)func;
1319 // Print("<-ChooseOperatorFunc %p\n", func);
1320 // Print("calc %d\n", unit->mCalcRate);
1321 return ret;
1322 }
1323
1324
1325 ////////////////////////////////////////////////////////////////////////////////////////////////////////
1326
PluginLoad(UnaryOp)1327 PluginLoad(UnaryOp) {
1328 ft = inTable;
1329
1330 DefineSimpleUnit(UnaryOpUGen);
1331 }
1332