-
Notifications
You must be signed in to change notification settings - Fork 758
/
SC_PlugIn.hpp
252 lines (204 loc) · 7.96 KB
/
SC_PlugIn.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/*
* SuperCollider real time audio synthesis system
* Copyright (c) 2002 James McCartney. All rights reserved.
* Copyright (c) 2011 Tim Blechmann
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <cassert>
#include "SC_PlugIn.h"
#include "function_attributes.h"
#include <type_traits>
/// c++ wrapper for Unit struct
class SCUnit : public Unit {
public:
///@{
/// generic signal wrappers
template <typename FloatType> struct ScalarSignal {
explicit ScalarSignal(FloatType value): value(value) {}
FloatType consume() const { return value; }
FloatType value;
};
template <typename FloatType> struct SlopeSignal {
SlopeSignal(FloatType value, FloatType slope): value(value), slope(slope) {}
FloatType consume() {
FloatType ret = value;
value += slope;
return ret;
}
FloatType value, slope;
};
template <typename FloatType> struct AudioSignal {
explicit AudioSignal(const FloatType* pointer): pointer(pointer) {}
FloatType consume() { return *pointer++; }
const FloatType* pointer;
};
template <typename FloatType> inline ScalarSignal<FloatType> makeScalar(FloatType value) const {
return ScalarSignal<FloatType>(value);
}
template <typename FloatType> inline SlopeSignal<FloatType> makeSlope(FloatType next, FloatType last) const {
return SlopeSignal<FloatType>(last, calcSlope(next, last));
}
inline AudioSignal<float> makeSignal(int index) const {
const float* input = in(index);
return AudioSignal<float>(input);
}
///@}
/// get input signal at index
const float* in(int index) const {
assert(uint32(index) < mNumInputs);
const Unit* unit = this;
return IN(index);
}
/// get input signal at index (to be used with ZXP)
const float* zin(int index) const {
assert(uint32(index) < mNumInputs);
const Unit* unit = this;
return ZIN(index);
}
/// get first sample of input signal
float in0(int index) const {
assert(uint32(index) < mNumInputs);
const Unit* unit = this;
return IN0(index);
}
/// get output signal at index
float* out(int index) const {
assert(uint32(index) < mNumOutputs);
const Unit* unit = this;
return OUT(index);
}
/// get output signal at index (to be used with ZXP)
float* zout(int index) const {
assert(uint32(index) < mNumOutputs);
const Unit* unit = this;
return ZOUT(index);
}
/// get reference to first sample of output signal
float& out0(int index) const {
assert(uint32(index) < mNumOutputs);
const Unit* unit = this;
return OUT0(index);
}
/// get rate of input signal
int inRate(int index) const {
assert(uint32(index) < mNumInputs);
const Unit* unit = this;
return INRATE(index);
}
/// get number of inputs
int numInputs() const { return int(mNumInputs); }
/// get number of outputs
int numOutputs() const { return int(mNumOutputs); }
/// test if input signal at index is scalar rate
bool isScalarRateIn(int index) const {
assert(uint32(index) < mNumInputs);
return inRate(index) == calc_ScalarRate;
}
/// test if input signal at index is demand rate
bool isDemandRateIn(int index) const {
assert(uint32(index) < mNumInputs);
return inRate(index) == calc_DemandRate;
}
/// test if input signal at index is control rate
bool isControlRateIn(int index) const {
assert(uint32(index) < mNumInputs);
return inRate(index) == calc_BufRate;
}
/// test if input signal at index is audio rate
bool isAudioRateIn(int index) const {
assert(uint32(index) < mNumInputs);
return inRate(index) == calc_FullRate;
}
/// get the blocksize of the input
int inBufferSize(int index) const {
assert(uint32(index) < mNumInputs);
const Unit* unit = this;
return INBUFLENGTH(index);
}
/// get sample rate of ugen
double sampleRate() const {
const Unit* unit = this;
return SAMPLERATE;
}
/// get sample duration
double sampleDur() const {
const Unit* unit = this;
return SAMPLEDUR;
}
/// get buffer size of ugen
int bufferSize() const { return mBufLength; }
/// get control rate
double controlRate() const {
const Unit* unit = this;
return BUFRATE;
}
/// get duration of a control block
double controlDur() const {
const Unit* unit = this;
return BUFDUR;
}
/// get sampling rate of audio signal
double fullSampleRate() const {
const Unit* unit = this;
return FULLRATE;
}
/// get buffer size of audio signals
int fullBufferSize() const {
const Unit* unit = this;
return FULLBUFLENGTH;
}
/// calculate slope value
template <typename FloatType> FloatType calcSlope(FloatType next, FloatType prev) const {
const Unit* unit = this;
return CALCSLOPE(next, prev);
}
template <typename UnitType, void (UnitType::*PointerToMember)(int)> static UnitCalcFunc make_calc_function(void) {
return &run_member_function<UnitType, PointerToMember>;
}
/// set calc function & compute initial sample
template <typename UnitType, void (UnitType::*PointerToMember)(int)> void set_calc_function(void) {
mCalcFunc = make_calc_function<UnitType, PointerToMember>();
(mCalcFunc)(this, 1);
}
/// set calc function & compute initial sample
template <typename UnitType, void (UnitType::*VectorCalcFunc)(int), void (UnitType::*ScalarCalcFunc)(int)>
void set_vector_calc_function(void) {
mCalcFunc = make_calc_function<UnitType, VectorCalcFunc>();
make_calc_function<UnitType, ScalarCalcFunc>()(this, 1);
}
/// @}
private:
template <typename UnitType, void (UnitType::*PointerToMember)(int)>
HOT static void run_member_function(struct Unit* unit, int inNumSamples) {
UnitType* realUnit = static_cast<UnitType*>(unit);
((realUnit)->*(PointerToMember))(inNumSamples);
}
};
/// define Ctor/Dtor functions for a class
#define DEFINE_XTORS(CLASSNAME) \
void CLASSNAME##_Ctor(CLASSNAME* unit) { new (unit) CLASSNAME(); } \
\
void CLASSNAME##_Dtor(CLASSNAME* unit) { unit->~CLASSNAME(); }
namespace detail {
template <class UGenClass> void constructClass(Unit* unit) { new (static_cast<UGenClass*>(unit)) UGenClass(); }
template <class UGenClass> void destroyClass(Unit* unit) { static_cast<UGenClass*>(unit)->~UGenClass(); }
}
template <class Unit> void registerUnit(InterfaceTable* ft, const char* name, bool disableBufferAliasing = false) {
UnitCtorFunc ctor = detail::constructClass<Unit>;
UnitDtorFunc dtor = std::is_trivially_destructible<Unit>::value ? nullptr : detail::destroyClass<Unit>;
(*ft->fDefineUnit)(name, sizeof(Unit), ctor, dtor, uint32(disableBufferAliasing ? 1 : 0));
}