FFT: Prevent user from attempting hops smaller than SC's block size
[supercollider.git] / server / plugins / UnaryOpUGens.cpp
blob49829c8656686fec6adcbe1f4eedefe31b6b1063
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 #include "SC_PlugIn.h"
24 #ifdef NOVA_SIMD
25 #include "simd_unary_arithmetic.hpp"
26 #include "simd_binary_arithmetic.hpp"
27 #include "simd_ternary_arithmetic.hpp"
28 #include "simd_math.hpp"
29 #include "simd_memory.hpp"
30 #include "softclip.hpp"
31 #include "simd_unit_conversion.hpp"
33 #include "function_attributes.h"
35 using nova::wrap_argument;
37 #define NOVA_WRAPPER(NAME, NOVANAME) \
38 FLATTEN void NAME##_nova(UnaryOpUGen *unit, int inNumSamples) \
39 { \
40 nova::NOVANAME##_vec_simd(OUT(0), IN(0), inNumSamples); \
43 #define NOVA_WRAPPER_CT_UNROLL(NAME, NOVANAME) \
44 FLATTEN void NAME##_nova(UnaryOpUGen *unit, int inNumSamples) \
45 { \
46 nova::NOVANAME##_vec_simd(OUT(0), IN(0), inNumSamples); \
47 } \
49 FLATTEN void NAME##_nova_64(UnaryOpUGen *unit, int inNumSamples) \
50 { \
51 nova::NOVANAME##_vec_simd<64>(OUT(0), IN(0)); \
54 #endif
56 using namespace std; // for math functions
58 static InterfaceTable *ft;
60 //////////////////////////////////////////////////////////////////////////////////////////////////
63 /* special unary math operators */
64 enum {
65 opNeg,
66 opNot,
67 opIsNil,
68 opNotNil,
69 opBitNot,
70 opAbs,
71 opAsFloat,
72 opAsInt,
73 opCeil,
74 opFloor,
75 opFrac,
76 opSign,
77 opSquared,
78 opCubed,
79 opSqrt,
80 opExp,
81 opRecip,
82 opMIDICPS,
83 opCPSMIDI,
85 opMIDIRatio,
86 opRatioMIDI,
87 opDbAmp,
88 opAmpDb,
89 opOctCPS,
90 opCPSOct,
91 opLog,
92 opLog2,
93 opLog10,
94 opSin,
95 opCos,
96 opTan,
97 opArcSin,
98 opArcCos,
99 opArcTan,
100 opSinH,
101 opCosH,
102 opTanH,
103 opRand,
104 opRand2,
105 opLinRand,
106 opBiLinRand,
108 opSum3Rand,
110 opDistort,
111 opSoftClip,
112 opCoin,
114 opDigitValue,
115 opSilence,
116 opThru,
117 opRectWindow,
118 opHanWindow,
119 opWelchWindow,
120 opTriWindow,
122 opRamp,
123 opSCurve,
125 opNumUnarySelectors
129 struct UnaryOpUGen : public Unit
133 typedef void (*UnaryOpFunc)(UnaryOpUGen *unit, int inNumSamples);
135 extern "C"
138 void UnaryOpUGen_Ctor(UnaryOpUGen *unit);
141 bool ChooseOperatorFunc(UnaryOpUGen *unit);
143 void UnaryOpUGen_Ctor(UnaryOpUGen *unit)
145 bool initialized = ChooseOperatorFunc(unit);
146 if (!initialized)
147 (unit->mCalcFunc)(unit, 1);
150 ////////////////////////////////////////////////////////////////////////////////////////////////////////
152 #define DEFINE_UNARY_OP_FUNCS(name, function) \
153 extern "C" void name##_a(UnaryOpUGen *unit, int inNumSamples) \
155 float *out = ZOUT(0); \
156 float *a = ZIN(0); \
158 LOOP1(inNumSamples, \
159 ZXP(out) = function(ZXP(a)); \
160 ); \
163 extern "C" void name##_1(UnaryOpUGen *unit, int inNumSamples) \
165 ZOUT0(0) = function(ZIN0(0)); \
168 extern "C" void name##_d(UnaryOpUGen *unit, int inNumSamples) \
170 if (inNumSamples) { \
171 float x = DEMANDINPUT_A(0, inNumSamples); \
172 OUT0(0) = sc_isnan(x) ? NAN : function(x); \
173 } else { \
174 RESETINPUT(0); \
178 template <typename F>
179 inline F sc_invert(F x)
181 return -x;
184 DEFINE_UNARY_OP_FUNCS(invert, sc_invert)
186 #ifdef NOVA_SIMD
187 FLATTEN void invert_nova(UnaryOpUGen *unit, int inNumSamples)
189 nova::minus_vec_simd(OUT(0), 0.f, IN(0), inNumSamples);
192 FLATTEN void invert_nova_64(UnaryOpUGen *unit, int inNumSamples)
194 nova::minus_vec_simd<64>(OUT(0), 0.f, IN(0));
197 #endif
200 template <typename F>
201 inline F sc_not(F x)
203 return x > 0.f ? 0.f : 1.f;
206 DEFINE_UNARY_OP_FUNCS(not, sc_not)
208 void zero_a(UnaryOpUGen *unit, int inNumSamples)
210 float *out = ZOUT(0);
212 ZClear(inNumSamples, out);
215 void thru_a(UnaryOpUGen *unit, int inNumSamples)
217 float *out = ZOUT(0);
218 float *a = ZIN(0);
220 ZCopy(inNumSamples, out, a);
223 DEFINE_UNARY_OP_FUNCS(abs, std::abs)
225 #ifdef NOVA_SIMD
226 FLATTEN void zero_nova(UnaryOpUGen *unit, int inNumSamples)
228 nova::zerovec_simd(OUT(0), inNumSamples);
231 FLATTEN void zero_nova_64(UnaryOpUGen *unit, int inNumSamples)
233 nova::zerovec_simd<64>(OUT(0));
236 FLATTEN void thru_nova(UnaryOpUGen *unit, int inNumSamples)
238 nova::copyvec_simd(OUT(0), IN(0), inNumSamples);
241 FLATTEN void thru_nova_64(UnaryOpUGen *unit, int inNumSamples)
243 nova::copyvec_simd<64>(OUT(0), IN(0));
246 FLATTEN void abs_nova(UnaryOpUGen *unit, int inNumSamples)
248 nova::abs_vec_simd(OUT(0), IN(0), inNumSamples);
251 FLATTEN void abs_nova_64(UnaryOpUGen *unit, int inNumSamples)
253 nova::abs_vec_simd<64>(OUT(0), IN(0));
255 #endif
257 template <typename F>
258 inline F sc_recip(F x)
260 return (F)1. / x;
263 DEFINE_UNARY_OP_FUNCS(recip, sc_recip)
265 #ifdef NOVA_SIMD
266 FLATTEN void recip_nova(UnaryOpUGen *unit, int inNumSamples)
268 nova::over_vec_simd(OUT(0), 1.f, IN(0), inNumSamples);
271 FLATTEN void recip_nova_64(UnaryOpUGen *unit, int inNumSamples)
273 nova::over_vec_simd<64>(OUT(0), 1.f, IN(0));
275 #endif
278 DEFINE_UNARY_OP_FUNCS(floor, floor)
279 DEFINE_UNARY_OP_FUNCS(ceil, ceil)
281 #ifdef NOVA_SIMD
282 NOVA_WRAPPER_CT_UNROLL(floor, floor)
283 NOVA_WRAPPER_CT_UNROLL(ceil, ceil)
284 #endif
286 DEFINE_UNARY_OP_FUNCS(sin, sin)
287 DEFINE_UNARY_OP_FUNCS(cos, cos)
288 DEFINE_UNARY_OP_FUNCS(tan, tan)
290 DEFINE_UNARY_OP_FUNCS(asin, asin)
291 DEFINE_UNARY_OP_FUNCS(acos, acos)
292 DEFINE_UNARY_OP_FUNCS(atan, atan)
294 DEFINE_UNARY_OP_FUNCS(sinh, sinh)
295 DEFINE_UNARY_OP_FUNCS(cosh, cosh)
296 DEFINE_UNARY_OP_FUNCS(tanh, tanh)
299 #ifdef NOVA_SIMD
300 NOVA_WRAPPER(sin, sin)
301 NOVA_WRAPPER(cos, cos)
302 NOVA_WRAPPER(tan, tan)
303 NOVA_WRAPPER(asin, asin)
304 NOVA_WRAPPER(acos, acos)
305 NOVA_WRAPPER(atan, atan)
306 NOVA_WRAPPER(tanh, tanh)
307 #endif
310 DEFINE_UNARY_OP_FUNCS(log, std::log)
311 DEFINE_UNARY_OP_FUNCS(log2, sc_log2)
312 DEFINE_UNARY_OP_FUNCS(log10, sc_log10)
313 DEFINE_UNARY_OP_FUNCS(exp, exp)
315 #ifdef NOVA_SIMD
316 NOVA_WRAPPER(log, log)
317 NOVA_WRAPPER(log2, log2)
318 NOVA_WRAPPER(log10, log10)
319 NOVA_WRAPPER(exp, exp)
320 #endif
322 DEFINE_UNARY_OP_FUNCS(sqrt, sc_sqrt)
324 #ifdef NOVA_SIMD
325 NOVA_WRAPPER_CT_UNROLL(sqrt, signed_sqrt)
326 #endif
328 DEFINE_UNARY_OP_FUNCS(ampdb, sc_ampdb)
329 DEFINE_UNARY_OP_FUNCS(dbamp, sc_dbamp)
330 DEFINE_UNARY_OP_FUNCS(midicps, sc_midicps)
331 DEFINE_UNARY_OP_FUNCS(cpsmidi, sc_cpsmidi)
332 DEFINE_UNARY_OP_FUNCS(midiratio, sc_midiratio)
333 DEFINE_UNARY_OP_FUNCS(ratiomidi, sc_ratiomidi)
334 DEFINE_UNARY_OP_FUNCS(cpsoct, sc_cpsoct)
335 DEFINE_UNARY_OP_FUNCS(octcps, sc_octcps)
337 #ifdef NOVA_SIMD
338 NOVA_WRAPPER(ampdb, amp2db)
339 NOVA_WRAPPER(dbamp, db2amp)
340 NOVA_WRAPPER(midicps, midi2freq)
341 NOVA_WRAPPER(cpsmidi, freq2midi)
342 NOVA_WRAPPER(midiratio, midi2ratio)
343 NOVA_WRAPPER(ratiomidi, ratio2midi)
344 NOVA_WRAPPER(cpsoct, freq2oct)
345 NOVA_WRAPPER(octcps, oct2freq)
346 #endif
349 DEFINE_UNARY_OP_FUNCS(frac, sc_frac)
350 #ifdef NOVA_SIMD
351 NOVA_WRAPPER_CT_UNROLL(frac, frac)
352 #endif
355 DEFINE_UNARY_OP_FUNCS(squared, sc_squared)
356 #ifdef NOVA_SIMD
357 NOVA_WRAPPER_CT_UNROLL(squared, square)
358 #endif
361 DEFINE_UNARY_OP_FUNCS(cubed, sc_cubed)
362 #ifdef NOVA_SIMD
363 NOVA_WRAPPER_CT_UNROLL(cubed, cube)
364 #endif
366 DEFINE_UNARY_OP_FUNCS(sign, sc_sign)
368 #ifdef NOVA_SIMD
369 NOVA_WRAPPER_CT_UNROLL(sign, sgn)
370 #endif
372 DEFINE_UNARY_OP_FUNCS(distort, sc_distort)
374 #ifdef NOVA_SIMD
375 void distort_a_nova(UnaryOpUGen *unit, int inNumSamples)
377 float *out = OUT(0);
378 float *a = IN(0);
379 using namespace nova;
381 int vs = vec<float>::size;
382 int len = inNumSamples / vs;
383 vec<float> one(1.f);
385 for (int i=0; i<len; ++i) {
386 vec<float> arg; arg.load_aligned(a);
387 vec<float> result = arg / (one + abs(arg));
388 result.store_aligned(out);
389 out += vs; a += vs;
392 #endif
394 DEFINE_UNARY_OP_FUNCS(distortneg, sc_distortneg)
395 DEFINE_UNARY_OP_FUNCS(softclip, sc_softclip)
397 #ifdef NOVA_SIMD
398 NOVA_WRAPPER_CT_UNROLL(softclip, softclip)
399 #endif
401 DEFINE_UNARY_OP_FUNCS(rectwindow, sc_rectwindow)
402 DEFINE_UNARY_OP_FUNCS(hanwindow, sc_hanwindow)
403 DEFINE_UNARY_OP_FUNCS(welwindow, sc_welwindow)
404 DEFINE_UNARY_OP_FUNCS(triwindow, sc_triwindow)
406 DEFINE_UNARY_OP_FUNCS(scurve, sc_scurve)
407 DEFINE_UNARY_OP_FUNCS(ramp, sc_ramp)
410 #ifdef NOVA_SIMD
411 FLATTEN void ramp_nova(UnaryOpUGen *unit, int inNumSamples)
413 nova::clip_vec_simd(OUT(0), wrap_argument(IN(0)), wrap_argument(0.f), wrap_argument(1.f), inNumSamples);
416 FLATTEN void ramp_nova_64(UnaryOpUGen *unit, int inNumSamples)
418 nova::clip_vec_simd<64>(OUT(0), wrap_argument(IN(0)), wrap_argument(0.f), wrap_argument(1.f));
420 #endif
422 ////////////////////////////////////////////////////////////////////////////////////////////////////////
424 void zero_d(UnaryOpUGen *unit, int inNumSamples)
426 if (inNumSamples) {
427 float x = DEMANDINPUT_A(0, inNumSamples);
428 OUT0(0) = sc_isnan(x) ? NAN : 0.f;
429 } else {
430 RESETINPUT(0);
434 void thru_d(UnaryOpUGen *unit, int inNumSamples)
436 if (inNumSamples) {
437 float x = DEMANDINPUT_A(0, inNumSamples);
438 OUT0(0) = sc_isnan(x) ? NAN : (x);
439 } else {
440 RESETINPUT(0);
444 ////////////////////////////////////////////////////////////////////////////////////////////////////////
446 static UnaryOpFunc ChooseNormalFunc(UnaryOpUGen *unit)
448 void (*func)(UnaryOpUGen *unit, int inNumSamples);
450 switch (unit->mSpecialIndex) {
451 case opSilence : func = &zero_a; break;
452 case opThru : func = &thru_a; break;
453 case opNeg : func = &invert_a; break;
454 case opNot : func = &not_a; break;
455 case opAbs : func = &abs_a; break;
456 case opCeil : func = &ceil_a; break;
457 case opFloor : func = &floor_a; break;
458 case opFrac : func = &frac_a; break;
459 case opSign : func = &sign_a; break;
460 case opSquared : func = &squared_a; break;
461 case opCubed : func = &cubed_a; break;
462 case opSqrt : func = &sqrt_a; break;
463 case opExp : func = &exp_a; break;
464 case opRecip : func = &recip_a; break;
465 case opMIDICPS : func = &midicps_a; break;
466 case opCPSMIDI : func = &cpsmidi_a; break;
468 case opMIDIRatio : func = &midiratio_a; break;
469 case opRatioMIDI : func = &ratiomidi_a; break;
470 case opDbAmp : func = &dbamp_a; break;
471 case opAmpDb : func = &ampdb_a; break;
472 case opOctCPS : func = &octcps_a; break;
473 case opCPSOct : func = &cpsoct_a; break;
474 case opLog : func = &log_a; break;
475 case opLog2 : func = &log2_a; break;
476 case opLog10 : func = &log10_a; break;
477 case opSin : func = &sin_a; break;
478 case opCos : func = &cos_a; break;
479 case opTan : func = &tan_a; break;
480 case opArcSin : func = &asin_a; break;
481 case opArcCos : func = &acos_a; break;
482 case opArcTan : func = &atan_a; break;
483 case opSinH : func = &sinh_a; break;
484 case opCosH : func = &cosh_a; break;
485 case opTanH : func = &tanh_a; break;
487 case opDistort : func = &distort_a; break;
488 case opSoftClip : func = &softclip_a; break;
490 case opRectWindow : func = &rectwindow_a; break;
491 case opHanWindow : func = &hanwindow_a; break;
492 case opWelchWindow : func = &welwindow_a; break;
493 case opTriWindow : func = &triwindow_a; break;
495 case opSCurve : func = &scurve_a; break;
496 case opRamp : func = &ramp_a; break;
498 default : func = &thru_a; break;
500 return func;
503 static UnaryOpFunc ChooseOneFunc(UnaryOpUGen *unit)
505 void (*func)(UnaryOpUGen *unit, int inNumSamples);
507 switch (unit->mSpecialIndex) {
508 case opSilence : func = &zero_a; break;
509 case opThru : func = &thru_a; break;
510 case opNeg : func = &invert_1; break;
511 case opNot : func = &not_1; break;
512 case opAbs : func = &abs_1; break;
513 case opCeil : func = &ceil_1; break;
514 case opFloor : func = &floor_1; break;
515 case opFrac : func = &frac_1; break;
516 case opSign : func = &sign_1; break;
517 case opSquared : func = &squared_1; break;
518 case opCubed : func = &cubed_1; break;
519 case opSqrt : func = &sqrt_1; break;
520 case opExp : func = &exp_1; break;
521 case opRecip : func = &recip_1; break;
522 case opMIDICPS : func = &midicps_1; break;
523 case opCPSMIDI : func = &cpsmidi_1; break;
525 case opMIDIRatio : func = &midiratio_1; break;
526 case opRatioMIDI : func = &ratiomidi_1; break;
527 case opDbAmp : func = &dbamp_1; break;
528 case opAmpDb : func = &ampdb_1; break;
529 case opOctCPS : func = &octcps_1; break;
530 case opCPSOct : func = &cpsoct_1; break;
531 case opLog : func = &log_1; break;
532 case opLog2 : func = &log2_1; break;
533 case opLog10 : func = &log10_1; break;
534 case opSin : func = &sin_1; break;
535 case opCos : func = &cos_1; break;
536 case opTan : func = &tan_1; break;
537 case opArcSin : func = &asin_1; break;
538 case opArcCos : func = &acos_1; break;
539 case opArcTan : func = &atan_1; break;
540 case opSinH : func = &sinh_1; break;
541 case opCosH : func = &cosh_1; break;
542 case opTanH : func = &tanh_1; break;
544 case opDistort : func = &distort_1; break;
545 case opSoftClip : func = &softclip_1; break;
547 case opRectWindow : func = &rectwindow_1; break;
548 case opHanWindow : func = &hanwindow_1; break;
549 case opWelchWindow : func = &welwindow_1; break;
550 case opTriWindow : func = &triwindow_1; break;
552 case opSCurve : func = &scurve_1; break;
553 case opRamp : func = &ramp_1; break;
555 default : func = &thru_a; break;
557 return func;
561 static UnaryOpFunc ChooseDemandFunc(UnaryOpUGen *unit)
563 void (*func)(UnaryOpUGen *unit, int inNumSamples);
565 switch (unit->mSpecialIndex) {
566 case opSilence : func = &zero_d; break;
567 case opThru : func = &thru_d; break;
568 case opNeg : func = &invert_d; break;
569 case opNot : func = &not_d; break;
570 case opAbs : func = &abs_d; break;
571 case opCeil : func = &ceil_d; break;
572 case opFloor : func = &floor_d; break;
573 case opFrac : func = &frac_d; break;
574 case opSign : func = &sign_d; break;
575 case opSquared : func = &squared_d; break;
576 case opCubed : func = &cubed_d; break;
577 case opSqrt : func = &sqrt_d; break;
578 case opExp : func = &exp_d; break;
579 case opRecip : func = &recip_d; break;
580 case opMIDICPS : func = &midicps_d; break;
581 case opCPSMIDI : func = &cpsmidi_d; break;
583 case opMIDIRatio : func = &midiratio_d; break;
584 case opRatioMIDI : func = &ratiomidi_d; break;
585 case opDbAmp : func = &dbamp_d; break;
586 case opAmpDb : func = &ampdb_d; break;
587 case opOctCPS : func = &octcps_d; break;
588 case opCPSOct : func = &cpsoct_d; break;
589 case opLog : func = &log_d; break;
590 case opLog2 : func = &log2_d; break;
591 case opLog10 : func = &log10_d; break;
592 case opSin : func = &sin_d; break;
593 case opCos : func = &cos_d; break;
594 case opTan : func = &tan_d; break;
595 case opArcSin : func = &asin_d; break;
596 case opArcCos : func = &acos_d; break;
597 case opArcTan : func = &atan_d; break;
598 case opSinH : func = &sinh_d; break;
599 case opCosH : func = &cosh_d; break;
600 case opTanH : func = &tanh_d; break;
602 case opDistort : func = &distort_d; break;
603 case opSoftClip : func = &softclip_d; break;
605 case opRectWindow : func = &rectwindow_d; break;
606 case opHanWindow : func = &hanwindow_d; break;
607 case opWelchWindow : func = &welwindow_d; break;
608 case opTriWindow : func = &triwindow_d; break;
610 case opSCurve : func = &scurve_d; break;
611 case opRamp : func = &ramp_d; break;
613 default : func = &thru_d; break;
615 return func;
618 #ifdef NOVA_SIMD
620 static UnaryOpFunc ChooseNovaSimdFunc(UnaryOpUGen *unit)
622 void (*func)(UnaryOpUGen *unit, int inNumSamples);
624 if (BUFLENGTH == 64) {
625 switch (unit->mSpecialIndex) {
626 case opSilence : return &zero_nova_64;
627 case opThru : func = &thru_nova; break;
628 case opNeg : return &invert_nova_64;
629 case opNot : func = &not_a; break;
630 case opAbs : return &abs_nova_64;
631 case opCeil : func = &ceil_nova_64; break;
632 case opFloor : func = &floor_nova_64; break;
633 case opFrac : func = &frac_nova_64; break;
634 case opSign : return &sign_nova_64;
635 case opSquared : return &squared_nova_64;
636 case opCubed : return &cubed_nova_64;
637 case opSqrt : func = &sqrt_nova_64; break;
638 case opExp : func = &exp_nova; break;
639 case opRecip : return &recip_nova_64;
640 case opMIDICPS : func = &midicps_nova; break;
641 case opCPSMIDI : func = &cpsmidi_nova; break;
642 case opMIDIRatio : func = &midiratio_nova; break;
643 case opRatioMIDI : func = &ratiomidi_nova; break;
644 case opDbAmp : func = &dbamp_nova; break;
645 case opAmpDb : func = &ampdb_nova; break;
646 case opOctCPS : func = &octcps_nova; break;
647 case opCPSOct : func = &cpsoct_nova; break;
648 case opLog : func = &log_nova; break;
649 case opLog2 : func = &log2_nova; break;
650 case opLog10 : func = &log10_nova; break;
651 case opSin : func = &sin_nova; break;
652 case opCos : func = &cos_nova; break;
653 case opTan : func = &tan_nova; break;
654 case opArcSin : func = &asin_nova; break;
655 case opArcCos : func = &acos_nova; break;
656 case opArcTan : func = &atan_nova; break;
657 case opSinH : func = &sinh_a; break;
658 case opCosH : func = &cosh_a; break;
659 case opTanH : func = &tanh_nova; break;
661 case opDistort : func = &distort_a_nova; break;
662 case opSoftClip : func = &softclip_nova_64; break;
664 case opRectWindow : func = &rectwindow_a; break;
665 case opHanWindow : func = &hanwindow_a; break;
666 case opWelchWindow : func = &welwindow_a; break;
667 case opTriWindow : func = &triwindow_a; break;
669 case opSCurve : func = &scurve_a; break;
670 case opRamp : return &ramp_nova_64;
672 default : return &thru_nova_64;
675 switch (unit->mSpecialIndex) {
676 case opSilence : func = &zero_nova; break;
677 case opThru : func = &thru_nova; break;
678 case opNeg : func = &invert_nova; break;
679 case opNot : func = &not_a; break;
680 case opAbs : func = &abs_nova; break;
681 case opCeil : func = &ceil_nova; break;
682 case opFloor : func = &floor_nova; break;
683 case opFrac : func = &frac_nova; break;
684 case opSign : func = &sign_nova; break;
685 case opSquared : func = &squared_nova; break;
686 case opCubed : func = &cubed_nova; break;
687 case opSqrt : func = &sqrt_nova; break;
688 case opExp : func = &exp_nova; break;
689 case opRecip : func = &recip_nova; break;
690 case opMIDICPS : func = &midicps_nova; break;
691 case opCPSMIDI : func = &cpsmidi_nova; break;
692 case opMIDIRatio : func = &midiratio_nova; break;
693 case opRatioMIDI : func = &ratiomidi_nova; break;
694 case opDbAmp : func = &dbamp_nova; break;
695 case opAmpDb : func = &ampdb_nova; break;
696 case opOctCPS : func = &octcps_nova; break;
697 case opCPSOct : func = &cpsoct_nova; break;
698 case opLog : func = &log_nova; break;
699 case opLog2 : func = &log2_nova; break;
700 case opLog10 : func = &log10_nova; break;
701 case opSin : func = &sin_nova; break;
702 case opCos : func = &cos_nova; break;
703 case opTan : func = &tan_nova; break;
704 case opArcSin : func = &asin_nova; break;
705 case opArcCos : func = &acos_nova; break;
706 case opArcTan : func = &atan_nova; break;
707 case opSinH : func = &sinh_a; break;
708 case opCosH : func = &cosh_a; break;
709 case opTanH : func = &tanh_nova; break;
711 case opDistort : func = &distort_a_nova; break;
712 case opSoftClip : func = &softclip_nova; break;
714 case opRectWindow : func = &rectwindow_a; break;
715 case opHanWindow : func = &hanwindow_a; break;
716 case opWelchWindow : func = &welwindow_a; break;
717 case opTriWindow : func = &triwindow_a; break;
719 case opSCurve : func = &scurve_a; break;
720 case opRamp : func = &ramp_nova; break;
722 default : func = &thru_nova; break;
724 return func;
726 #endif
728 bool ChooseOperatorFunc(UnaryOpUGen *unit)
730 //Print("->ChooseOperatorFunc %d\n", unit->mSpecialIndex);
731 UnaryOpFunc func;
732 bool ret = false;
733 if (unit->mCalcRate == calc_DemandRate) {
734 func = ChooseDemandFunc(unit);
735 } else if (BUFLENGTH == 1) {
736 func = ChooseOneFunc(unit);
737 #if defined(NOVA_SIMD)
738 } else if (!(BUFLENGTH & 15)) {
739 /* select normal function for initialization */
740 func = ChooseNormalFunc(unit);
741 func(unit, 1);
743 /* select simd function */
744 func = ChooseNovaSimdFunc(unit);
745 ret = true;
746 #endif
747 } else {
748 func = ChooseNormalFunc(unit);
750 unit->mCalcFunc = (UnitCalcFunc)func;
751 //Print("<-ChooseOperatorFunc %p\n", func);
752 //Print("calc %d\n", unit->mCalcRate);
753 return ret;
757 ////////////////////////////////////////////////////////////////////////////////////////////////////////
759 PluginLoad(UnaryOp)
761 ft = inTable;
763 DefineSimpleUnit(UnaryOpUGen);