2 * SuperCollider real time audio synthesis system
3 * Copyright (c) 2002 James McCartney. All rights reserved.
4 * Copyright (c) 2011 Tim Blechmann.
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
24 #include "SC_PlugIn.hpp"
26 #include "simd_memory.hpp"
27 #include "simd_binary_arithmetic.hpp"
28 #include "simd_ternary_arithmetic.hpp"
29 #include "simd_mix.hpp"
31 using nova::slope_argument
;
33 #if defined(__GNUC__) && !defined(__clang__)
34 #define inline_functions __attribute__ ((flatten))
36 #define inline_functions
42 enum { scalar
, unrolled
, unrolled_64
};
44 bool canUseSIMD (void) const
46 return (mBufLength
& (nova::vec
< float >::objects_per_cacheline
- 1)) == 0;
50 struct ControlRateInput
54 void init(const SIMD_Unit
* parent
)
56 value
= parent
->in0(index
);
59 bool changed(const SIMD_Unit
* parent
) const
61 return value
!= parent
->in0(index
);
64 #if __cplusplus <= 199711L
65 nova::detail::scalar_ramp_argument
<float> slope(const SIMD_Unit
* parent
)
67 decltype(nova::slope_argument(0.f
, 0.f
)) slope(const SIMD_Unit
* parent
)
70 float next
= parent
->in0(index
);
71 float current
= value
;
72 float slope
= parent
->calcSlope(next
, current
);
74 return slope_argument(current
, slope
);
83 template <typename UnitType
, void (UnitType::*UnrolledCalcFunc
)(int), void (UnitType::*VectorCalcFunc
)(int), void (UnitType::*ScalarCalcFunc
)(int)>
84 void set_unrolled_calc_function(void)
86 if (bufferSize() == 64)
87 SCUnit::set_vector_calc_function
<UnitType
, UnrolledCalcFunc
, ScalarCalcFunc
>();
89 set_vector_calc_function
<UnitType
, VectorCalcFunc
, ScalarCalcFunc
>();
92 template <typename UnitType
, void (UnitType::*VectorCalcFunc
)(int), void (UnitType::*ScalarCalcFunc
)(int)>
93 void set_vector_calc_function(void)
96 SCUnit::set_vector_calc_function
<UnitType
, VectorCalcFunc
, ScalarCalcFunc
>();
98 SCUnit::set_calc_function
<UnitType
, ScalarCalcFunc
>();
101 template <int type
, typename Arg1
, typename Arg2
, typename Arg3
>
102 static void muladd(float * out
, Arg1
const & arg1
, Arg2
const & arg2
, Arg3
const & arg3
, int inNumSamples
)
105 nova::muladd_vec(out
, arg1
, arg2
, arg3
, inNumSamples
);
106 if (type
== unrolled
)
107 nova::muladd_vec_simd(out
, arg1
, arg2
, arg3
, inNumSamples
);
108 if (type
== unrolled_64
)
109 nova::muladd_vec_simd
<64>(out
, arg1
, arg2
, arg3
);
112 template <int type
, typename Arg1
, typename Arg2
>
113 static void plus_vec(float * out
, Arg1
const & arg1
, Arg2
const & arg2
, int inNumSamples
)
116 nova::plus_vec(out
, arg1
, arg2
, inNumSamples
);
117 if (type
== unrolled
)
118 nova::plus_vec_simd(out
, arg1
, arg2
, inNumSamples
);
119 if (type
== unrolled_64
)
120 nova::plus_vec_simd
<64>(out
, arg1
, arg2
);
123 template <int type
, typename Arg1
, typename Arg2
>
124 static void times_vec(float * out
, Arg1
const & arg1
, Arg2
const & arg2
, int inNumSamples
)
127 nova::times_vec(out
, arg1
, arg2
, inNumSamples
);
128 if (type
== unrolled
)
129 nova::times_vec_simd(out
, arg1
, arg2
, inNumSamples
);
130 if (type
== unrolled_64
)
131 nova::times_vec_simd
<64>(out
, arg1
, arg2
);
134 template <int type
, typename Arg1
, typename Arg2
>
135 static void slope_vec(float * out
, Arg1
const & base
, Arg2
const & slope
, int inNumSamples
)
138 nova::set_slope_vec(out
, base
, slope
, inNumSamples
);
140 nova::set_slope_vec_simd(out
, base
, slope
, inNumSamples
);
143 template <int type
, typename Arg1
>
144 static void slope_vec(float * out
, Arg1
const & slope
, int inNumSamples
)
147 nova::set_slope_vec(out
, slope
.data
, slope
.slope_
, inNumSamples
);
149 nova::set_slope_vec_simd(out
, slope
.data
, slope
.slope_
, inNumSamples
);
153 static void copy_vec(float * out
, const float * in
, int inNumSamples
)
159 nova::copyvec(out
, in
, inNumSamples
);
160 if (type
== unrolled
)
161 nova::copyvec_simd(out
, in
, inNumSamples
);
162 if (type
== unrolled_64
)
163 nova::copyvec_simd
<64>(out
, in
);
167 static void set_vec(float * out
, float value
, int inNumSamples
)
170 nova::setvec(out
, value
, inNumSamples
);
171 if (type
== unrolled
)
172 nova::setvec_simd(out
, value
, inNumSamples
);
173 if (type
== unrolled_64
)
174 nova::setvec_simd
<64>(out
, value
);
178 static void zero_vec(float * out
, int inNumSamples
)
181 nova::zerovec(out
, inNumSamples
);
182 if (type
== unrolled
)
183 nova::zerovec_simd(out
, inNumSamples
);
184 if (type
== unrolled_64
)
185 nova::zerovec_simd
<64>(out
);
189 #endif /* SIMD_UNIT_HPP */