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 = &not_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 = &ampdb_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 = &not_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 = &ampdb_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 = &not_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 = &ampdb_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 = &not_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 = &ampdb_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 = &not_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 = &ampdb_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