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.hpp"
23 #include "SIMD_Unit.hpp"
25 static InterfaceTable
*ft
;
32 ControlRateInput
<1> mMul
;
33 ControlRateInput
<2> mAdd
;
35 #define MULADD_CALCFUNC(METHOD_NAME) \
37 set_unrolled_calc_function<MulAdd, \
38 &MulAdd::METHOD_NAME<unrolled_64>, \
39 &MulAdd::METHOD_NAME<unrolled>, \
40 &MulAdd::METHOD_NAME<scalar> >(); \
49 if (mCalcRate
!= calc_FullRate
) {
50 set_calc_function
<MulAdd
, &MulAdd::next_scalar
>();
54 assert(inRate(0) == calc_FullRate
);
60 MULADD_CALCFUNC(next_aa
);
63 MULADD_CALCFUNC(next_ak
);
67 MULADD_CALCFUNC(next_a0
);
69 MULADD_CALCFUNC(next_ai
);
78 MULADD_CALCFUNC(next_ka
);
81 MULADD_CALCFUNC(next_kk
);
85 MULADD_CALCFUNC(next_k0
);
87 MULADD_CALCFUNC(next_ki
);
97 MULADD_CALCFUNC(next_1a
);
99 MULADD_CALCFUNC(next_0a
);
101 MULADD_CALCFUNC(next_ia
);
105 MULADD_CALCFUNC(next_1k
);
106 else if (mMul
== 0.f
)
107 MULADD_CALCFUNC(next_0k
);
109 MULADD_CALCFUNC(next_ik
);
111 case calc_ScalarRate
:
114 MULADD_CALCFUNC(next_10
);
116 MULADD_CALCFUNC(next_1i
);
119 else if (mMul
== 0.f
) {
121 MULADD_CALCFUNC(next_00
);
123 MULADD_CALCFUNC(next_0i
);
127 MULADD_CALCFUNC(next_i0
);
129 MULADD_CALCFUNC(next_ii
);
141 inline bool mulChanged(void) const
143 return mMul
.changed(this);
146 inline bool addChanged(void) const
148 return mAdd
.changed(this);
151 #if __cplusplus <= 199711L
152 nova::detail::scalar_ramp_argument
<float> mulSlope(void)
154 decltype(nova::slope_argument(0.f
, 0.f
)) mulSlope(void)
157 return mMul
.slope(this);
160 #if __cplusplus <= 199711L
161 nova::detail::scalar_ramp_argument
<float> addSlope(void)
163 decltype(nova::slope_argument(0.f
, 0.f
)) addSlope(void)
166 return mAdd
.slope(this);
169 void next_scalar(int inNumSamples
)
171 out0(0) = (in0(0) * in0(1)) + in0(2);
175 void next_aa(int inNumSamples
)
177 muladd
<SIMD
>(out(0), in(0), in(1), in(2), inNumSamples
);
181 void next_ak(int inNumSamples
)
184 muladd
<SIMD
>(out(0), in(0), in(1), addSlope(), inNumSamples
);
187 times_vec
<SIMD
>(out(0), in(0), in(1), inNumSamples
);
189 next_ai
<SIMD
>(inNumSamples
);
194 void next_ai(int inNumSamples
)
196 muladd
<SIMD
>(out(0), in(0), in(1), mAdd
, inNumSamples
);
200 void next_ka(int inNumSamples
)
203 muladd
<SIMD
>(out(0), in(0), mulSlope(), in(2), inNumSamples
);
205 next_ia
<SIMD
>(inNumSamples
);
209 void next_kk(int inNumSamples
)
213 muladd
<SIMD
>(out(0), in(0), mulSlope(), addSlope(), inNumSamples
);
216 slope_vec
<SIMD
>(out(0), addSlope(), inNumSamples
);
217 else if (mMul
== 1.f
)
218 plus_vec
<SIMD
>(out(0), in(0), addSlope(), inNumSamples
);
220 muladd
<SIMD
>(out(0), in(0), mMul
, addSlope(), inNumSamples
);
223 next_ki
<SIMD
>(inNumSamples
);
227 void next_ki(int inNumSamples
)
230 muladd
<SIMD
>(out(0), in(0), mulSlope(), mAdd
, inNumSamples
);
232 next_ii
<SIMD
>(inNumSamples
);
236 void next_ia(int inNumSamples
)
239 next_0a
<SIMD
>(inNumSamples
);
240 else if (mMul
== 1.0)
241 next_1a
<SIMD
>(inNumSamples
);
243 muladd
<SIMD
>(out(0), in(0), mMul
, in(2), inNumSamples
);
247 void next_ik(int inNumSamples
)
251 slope_vec
<SIMD
>(out(0), addSlope(), inNumSamples
);
252 else if (mMul
== 1.f
)
253 plus_vec
<SIMD
>(out(0), in(0), addSlope(), inNumSamples
);
255 muladd
<SIMD
>(out(0), in(0), mMul
, addSlope(), inNumSamples
);
257 next_ii
<SIMD
>(inNumSamples
);
261 void next_ii(int inNumSamples
)
264 next_0i
<SIMD
>(inNumSamples
);
265 else if (mMul
== 1.f
) {
266 next_1i
<SIMD
>(inNumSamples
);
269 times_vec
<SIMD
>(out(0), in(0), mMul
, inNumSamples
);
271 muladd
<SIMD
>(out(0), in(0), mMul
, mAdd
, inNumSamples
);
276 void next_1a(int inNumSamples
)
278 plus_vec
<SIMD
>(out(0), in(0), in(2), inNumSamples
);
282 void next_1k(int inNumSamples
)
285 plus_vec
<SIMD
>(out(0), in(0), addSlope(), inNumSamples
);
287 next_1i
<SIMD
>(inNumSamples
);
291 void next_1i(int inNumSamples
)
294 copy_vec
<SIMD
>(out(0), in(0), inNumSamples
);
296 plus_vec
<SIMD
>(out(0), in(0), mAdd
, inNumSamples
);
300 void next_0a(int inNumSamples
)
302 copy_vec
<SIMD
>(out(0), in(2), inNumSamples
);
306 void next_0k(int inNumSamples
)
309 slope_vec
<SIMD
>(out(0), addSlope(), inNumSamples
);
311 next_0i
<SIMD
>(inNumSamples
);
315 void next_0i(int inNumSamples
)
317 set_vec
<SIMD
>(out(0), mAdd
, inNumSamples
);
321 void next_a0(int inNumSamples
)
323 times_vec
<SIMD
>(out(0), in(0), in(1), inNumSamples
);
327 void next_k0(int inNumSamples
)
330 times_vec
<SIMD
>(out(0), in(0), mulSlope(), inNumSamples
);
332 next_ik
<SIMD
>(inNumSamples
);
336 void next_i0(int inNumSamples
)
339 next_00
<SIMD
>(inNumSamples
);
340 else if (mMul
== 1.f
)
341 next_10
<SIMD
>(inNumSamples
);
343 times_vec
<SIMD
>(out(0), in(0), mMul
, inNumSamples
);
347 void next_10(int inNumSamples
)
349 copy_vec
<SIMD
>(out(0), in(0), inNumSamples
);
353 void next_00(int inNumSamples
)
355 set_vec
<SIMD
>(out(0), 0.f
, inNumSamples
);
364 ControlRateInput
<1> in1
;
365 ControlRateInput
<2> in2
;
372 if (mCalcRate
!= calc_FullRate
) {
373 set_calc_function
<Sum3
, &Sum3::next_scalar
>();
377 assert(inRate(0) == calc_FullRate
);
383 set_vector_calc_function
<Sum3
, &Sum3::next_aaa
<true>, &Sum3::next_aaa
<false> >();
387 set_vector_calc_function
<Sum3
, &Sum3::next_aak
<true>, &Sum3::next_aak
<false> >();
390 case calc_ScalarRate
:
391 set_vector_calc_function
<Sum3
, &Sum3::next_aai
<true>, &Sum3::next_aai
<false> >();
401 set_vector_calc_function
<Sum3
, &Sum3::next_akk
<true>, &Sum3::next_akk
<false> >();
404 case calc_ScalarRate
:
405 set_vector_calc_function
<Sum3
, &Sum3::next_aki
<true>, &Sum3::next_aki
<false> >();
412 case calc_ScalarRate
:
413 assert (inRate(2) == calc_ScalarRate
);
414 set_vector_calc_function
<Sum3
, &Sum3::next_aii
<true>, &Sum3::next_aii
<false> >();
422 template <bool SIMD
, typename Arg1
, typename Arg2
, typename Arg3
>
423 static void sum_vec(float * out
, Arg1
const & arg1
, Arg2
const & arg2
, Arg3
const & arg3
, int inNumSamples
)
426 nova::sum_vec_simd(out
, arg1
, arg2
, arg3
, inNumSamples
);
428 nova::sum_vec(out
, arg1
, arg2
, arg3
, inNumSamples
);
431 void next_scalar(int inNumSamples
)
433 out0(0) = in0(0) + in0(1) + in0(2);
437 void next_aaa(int inNumSamples
)
439 sum_vec
<SIMD
>(out(0), in(0), in(1), in(2), inNumSamples
);
443 void next_aak(int inNumSamples
)
445 if (in2
.changed(this))
446 sum_vec
<SIMD
>(out(0), in(0), in(1), in2
.slope(this), inNumSamples
);
448 next_aai
<SIMD
>(inNumSamples
);
452 void next_aai(int inNumSamples
)
454 sum_vec
<SIMD
>(out(0), in(0), in(1), in2
, inNumSamples
);
458 void next_aki(int inNumSamples
)
460 if (in1
.changed(this))
461 sum_vec
<SIMD
>(out(0), in(0), in1
.slope(this), in2
, inNumSamples
);
463 next_aii
<SIMD
>(inNumSamples
);
467 void next_akk(int inNumSamples
)
469 if (in2
.changed(this)) {
470 if (in1
.changed(this))
471 sum_vec
<SIMD
>(out(0), in(0), in1
.slope(this), in2
.slope(this), inNumSamples
);
473 sum_vec
<SIMD
>(out(0), in(0), in1
, in2
.slope(this), inNumSamples
);
475 next_aki
<SIMD
>(inNumSamples
);
479 void next_aii(int inNumSamples
)
481 sum_vec
<SIMD
>(out(0), in(0), in0(1), in0(2), inNumSamples
);
490 ControlRateInput
<1> in1
;
491 ControlRateInput
<2> in2
;
492 ControlRateInput
<3> in3
;
500 if (mCalcRate
!= calc_FullRate
) {
501 set_calc_function
<Sum4
, &Sum4::next_scalar
>();
505 assert(inRate(0) == calc_FullRate
);
513 set_vector_calc_function
<Sum4
, &Sum4::next_aaaa
<true>, &Sum4::next_aaaa
<false> >();
517 set_vector_calc_function
<Sum4
, &Sum4::next_aaak
<true>, &Sum4::next_aaak
<false> >();
520 case calc_ScalarRate
:
521 set_vector_calc_function
<Sum4
, &Sum4::next_aaai
<true>, &Sum4::next_aaai
<false> >();
531 set_vector_calc_function
<Sum4
, &Sum4::next_aakk
<true>, &Sum4::next_aakk
<false> >();
534 case calc_ScalarRate
:
535 set_vector_calc_function
<Sum4
, &Sum4::next_aaki
<true>, &Sum4::next_aaki
<false> >();
542 case calc_ScalarRate
:
544 case calc_ScalarRate
:
545 set_vector_calc_function
<Sum4
, &Sum4::next_aaii
<true>, &Sum4::next_aaii
<false> >();
557 set_vector_calc_function
<Sum4
, &Sum4::next_akkk
<true>, &Sum4::next_akkk
<false> >();
560 case calc_ScalarRate
:
561 set_vector_calc_function
<Sum4
, &Sum4::next_akki
<true>, &Sum4::next_akki
<false> >();
568 case calc_ScalarRate
:
570 case calc_ScalarRate
:
571 set_vector_calc_function
<Sum4
, &Sum4::next_akii
<true>, &Sum4::next_akii
<false> >();
579 case calc_ScalarRate
:
581 case calc_ScalarRate
:
583 case calc_ScalarRate
:
584 set_vector_calc_function
<Sum4
, &Sum4::next_aiii
<true>, &Sum4::next_aiii
<false> >();
600 void next_scalar(int inNumSamples
)
602 out0(0) = in0(0) + in0(1) + in0(2) + in0(3);
605 template <bool SIMD
, typename Arg1
, typename Arg2
, typename Arg3
, typename Arg4
>
606 static void sum_vec(float * out
, Arg1
const & arg1
, Arg2
const & arg2
, Arg3
const & arg3
, Arg4
const & arg4
, int inNumSamples
)
609 nova::sum_vec_simd(out
, arg1
, arg2
, arg3
, arg4
, inNumSamples
);
611 nova::sum_vec(out
, arg1
, arg2
, arg3
, arg4
, inNumSamples
);
615 void next_aaaa(int inNumSamples
)
617 sum_vec
<SIMD
>(out(0), in(0), in(1), in(2), in(3), inNumSamples
);
621 void next_aaak(int inNumSamples
)
623 if (in3
.changed(this))
624 sum_vec
<SIMD
>(out(0), in(0), in(1), in(2), in3
.slope(this), inNumSamples
);
626 next_aaai
<SIMD
>(inNumSamples
);
630 void next_aaai(int inNumSamples
)
632 sum_vec
<SIMD
>(out(0), in(0), in(1), in(2), in3
, inNumSamples
);
636 void next_aakk(int inNumSamples
)
638 if (in3
.changed(this)) {
639 if (in2
.changed(this))
640 sum_vec
<SIMD
>(out(0), in(0), in(1), in2
.slope(this), in3
.slope(this), inNumSamples
);
642 sum_vec
<SIMD
>(out(0), in(0), in(1), in2
, in3
.slope(this), inNumSamples
);
644 next_aaki
<SIMD
>(inNumSamples
);
648 void next_aaki(int inNumSamples
)
650 if (in2
.changed(this))
651 sum_vec
<SIMD
>(out(0), in(0), in(1), in2
.slope(this), in3
, inNumSamples
);
653 next_aaii
<SIMD
>(inNumSamples
);
657 void next_aaii(int inNumSamples
)
659 sum_vec
<SIMD
>(out(0), in(0), in(1), in2
, in3
, inNumSamples
);
663 void next_akkk(int inNumSamples
)
665 if (in3
.changed(this)) {
666 if (in2
.changed(this)) {
667 if (in1
.changed(this))
668 sum_vec
<SIMD
>(out(0), in(0), in1
.slope(this), in2
.slope(this), in3
.slope(this), inNumSamples
);
670 sum_vec
<SIMD
>(out(0), in(0), in1
, in2
.slope(this), in3
.slope(this), inNumSamples
);
672 if (in1
.changed(this))
673 sum_vec
<SIMD
>(out(0), in(0), in1
.slope(this), in2
, in3
.slope(this), inNumSamples
);
675 sum_vec
<SIMD
>(out(0), in(0), in1
, in2
, in3
.slope(this), inNumSamples
);
678 next_akki
<SIMD
>(inNumSamples
);
682 void next_akki(int inNumSamples
)
684 if (in2
.changed(this)) {
685 if (in1
.changed(this))
686 sum_vec
<SIMD
>(out(0), in(0), in1
.slope(this), in2
.slope(this), in3
, inNumSamples
);
688 sum_vec
<SIMD
>(out(0), in(0), in1
, in2
.slope(this), in3
, inNumSamples
);
690 next_akii
<SIMD
>(inNumSamples
);
694 void next_akii(int inNumSamples
)
696 if (in1
.changed(this))
697 sum_vec
<SIMD
>(out(0), in(0), in1
.slope(this), in2
, in3
, inNumSamples
);
699 next_aiii
<SIMD
>(inNumSamples
);
703 void next_aiii(int inNumSamples
)
705 sum_vec
<SIMD
>(out(0), in(0), in1
, in2
, in3
, inNumSamples
);
713 ////////////////////////////////////////////////////////////////////////////////////////////////////////
719 DefineSimpleUnit(MulAdd
);
720 DefineSimpleUnit(Sum3
);
721 DefineSimpleUnit(Sum4
);