1 /*
2 * Copyright (C) 2014 Guitarix project MOD project
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 * --------------------------------------------------------------------------
18 */
19
20
21 #include <cstdlib>
22 #include <cmath>
23 #include <iostream>
24 #include <cstring>
25 #include <unistd.h>
26
27 ///////////////////////// MACRO SUPPORT ////////////////////////////////
28
29 #define __rt_func __attribute__((section(".rt.text")))
30 #define __rt_data __attribute__((section(".rt.data")))
31
32 ///////////////////////// FAUST SUPPORT ////////////////////////////////
33
34 #define FAUSTFLOAT float
35 #ifndef N_
36 #define N_(String) (String)
37 #endif
38 #define max(x, y) (((x) > (y)) ? (x) : (y))
39 #define min(x, y) (((x) < (y)) ? (x) : (y))
40
41 #define always_inline inline __attribute__((always_inline))
42
43 #ifndef signbit
44 #define signbit(x) std::signbit(x)
45 #endif
46
mydsp_faustpower2_f(T x)47 template<class T> inline T mydsp_faustpower2_f(T x) {return (x * x);}
mydsp_faustpower3_f(T x)48 template<class T> inline T mydsp_faustpower3_f(T x) {return ((x * x) * x);}
mydsp_faustpower4_f(T x)49 template<class T> inline T mydsp_faustpower4_f(T x) {return (((x * x) * x) * x);}
mydsp_faustpower5_f(T x)50 template<class T> inline T mydsp_faustpower5_f(T x) {return ((((x * x) * x) * x) * x);}
mydsp_faustpower6_f(T x)51 template<class T> inline T mydsp_faustpower6_f(T x) {return (((((x * x) * x) * x) * x) * x);}
52
53 ////////////////////////////// LOCAL INCLUDES //////////////////////////
54
55 #include "gx_sceleton.h" // define struct PortIndex
56 #include "gx_pluginlv2.h" // define struct PluginLV2
57 #include "sceleton.cc" // dsp class generated by faust -> dsp2cc
58
59 ////////////////////////////// PLUG-IN CLASS ///////////////////////////
60
61 namespace sceleton {
62
63 class Gx_sceleton_
64 {
65 private:
66 // pointer to buffer
67 float* output;
68 float* input;
69 float* output1;
70 float* input1;
71 // pointer to dsp class
72 PluginLV2* sceleton;
73
74 // bypass ramping
75 float* bypass;
76 uint32_t bypass_;
77
78 bool needs_ramp_down;
79 bool needs_ramp_up;
80 float ramp_down;
81 float ramp_up;
82 float ramp_up_step;
83 float ramp_down_step;
84 bool bypassed;
85
86 // private functions
87 inline void run_dsp_(uint32_t n_samples);
88 inline void connect_(uint32_t port,void* data);
89 inline void init_dsp_(uint32_t rate);
90 inline void connect_all__ports(uint32_t port, void* data);
91 inline void activate_f();
92 inline void clean_up();
93 inline void deactivate_f();
94
95 public:
96 // LV2 Descriptor
97 static const LV2_Descriptor descriptor;
98 // static wrapper to private functions
99 static void deactivate(LV2_Handle instance);
100 static void cleanup(LV2_Handle instance);
101 static void run(LV2_Handle instance, uint32_t n_samples);
102 static void activate(LV2_Handle instance);
103 static void connect_port(LV2_Handle instance, uint32_t port, void* data);
104 static LV2_Handle instantiate(const LV2_Descriptor* descriptor,
105 double rate, const char* bundle_path,
106 const LV2_Feature* const* features);
107 Gx_sceleton_();
108 ~Gx_sceleton_();
109 };
110
111 // constructor
Gx_sceleton_()112 Gx_sceleton_::Gx_sceleton_() :
113 output(NULL),
114 input(NULL),
115 sceleton(sceleton::plugin()),
116 bypass(0),
117 bypass_(2),
118 needs_ramp_down(false),
119 needs_ramp_up(false),
120 bypassed(false) {};
121
122 // destructor
~Gx_sceleton_()123 Gx_sceleton_::~Gx_sceleton_()
124 {
125 // just to be sure the plug have given free the allocated mem
126 // it didn't hurd if the mem is already given free by clean_up()
127 if (sceleton->activate_plugin !=0)
128 sceleton->activate_plugin(false, sceleton);
129 // delete DSP class
130 sceleton->delete_instance(sceleton);
131 };
132
133 ///////////////////////// PRIVATE CLASS FUNCTIONS /////////////////////
134
init_dsp_(uint32_t rate)135 void Gx_sceleton_::init_dsp_(uint32_t rate)
136 {
137 // set values for internal ramping
138 ramp_down_step = 32 * (256 * rate) / 48000;
139 ramp_up_step = ramp_down_step;
140 ramp_down = ramp_down_step;
141 ramp_up = 0.0;
142
143 sceleton->set_samplerate(rate, sceleton); // init the DSP class
144 }
145
146 // connect the Ports used by the plug-in class
connect_(uint32_t port,void * data)147 void Gx_sceleton_::connect_(uint32_t port,void* data)
148 {
149 switch ((PortIndex)port)
150 {
151 case EFFECTS_OUTPUT:
152 output = static_cast<float*>(data);
153 break;
154 case EFFECTS_INPUT:
155 input = static_cast<float*>(data);
156 break;
157 case EFFECTS_OUTPUT1:
158 output1 = static_cast<float*>(data);
159 break;
160 case EFFECTS_INPUT1:
161 input1 = static_cast<float*>(data);
162 break;
163 case BYPASS:
164 bypass = static_cast<float*>(data); // , 0.0, 0.0, 1.0, 1.0
165 break;
166 default:
167 break;
168 }
169 }
170
activate_f()171 void Gx_sceleton_::activate_f()
172 {
173 // allocate the internal DSP mem
174 if (sceleton->activate_plugin !=0)
175 sceleton->activate_plugin(true, sceleton);
176 }
177
clean_up()178 void Gx_sceleton_::clean_up()
179 {
180 // delete the internal DSP mem
181 if (sceleton->activate_plugin !=0)
182 sceleton->activate_plugin(false, sceleton);
183 }
184
deactivate_f()185 void Gx_sceleton_::deactivate_f()
186 {
187 // delete the internal DSP mem
188 if (sceleton->activate_plugin !=0)
189 sceleton->activate_plugin(false, sceleton);
190 }
191
run_dsp_(uint32_t n_samples)192 void Gx_sceleton_::run_dsp_(uint32_t n_samples)
193 {
194 FAUSTFLOAT buf[n_samples];
195 FAUSTFLOAT buf1[n_samples];
196 // do inplace processing at default
197 memcpy(output, input, n_samples*sizeof(float));
198 memcpy(output1, input1, n_samples*sizeof(float));
199 // check if bypass is pressed
200 if (bypass_ != static_cast<uint32_t>(*(bypass))) {
201 bypass_ = static_cast<uint32_t>(*(bypass));
202 if (!bypass_) {
203 needs_ramp_down = true;
204 needs_ramp_up = false;
205 } else {
206 needs_ramp_down = false;
207 needs_ramp_up = true;
208 bypassed = false;
209 }
210 }
211
212 if (needs_ramp_down || needs_ramp_up) {
213 memcpy(buf, input, n_samples*sizeof(float));
214 memcpy(buf1, input1, n_samples*sizeof(float));
215 }
216
217 if (!bypassed) {
218 sceleton->stereo_audio(static_cast<int>(n_samples), output, output1, output, output1, sceleton);
219 }
220
221 // check if ramping is needed
222 if (needs_ramp_down) {
223 float fade = 0;
224 for (uint32_t i=0; i<n_samples; i++) {
225 if (ramp_down >= 0.0) {
226 --ramp_down;
227 }
228 fade = max(0.0,ramp_down) /ramp_down_step ;
229 output[i] = output[i] * fade + buf[i] * (1.0 - fade);
230 output1[i] = output1[i] * fade + buf1[i] * (1.0 - fade);
231 }
232
233 if (ramp_down <= 0.0) {
234 // when ramped down, clear buffer from sceleton class
235 sceleton->clear_state(sceleton);
236 needs_ramp_down = false;
237 bypassed = true;
238 ramp_down = ramp_down_step;
239 ramp_up = 0.0;
240 } else {
241 ramp_up = ramp_down;
242 }
243
244 } else if (needs_ramp_up) {
245 float fade = 0;
246 for (uint32_t i=0; i<n_samples; i++) {
247 if (ramp_up < ramp_up_step) {
248 ++ramp_up ;
249 }
250 fade = min(ramp_up_step,ramp_up) /ramp_up_step ;
251 output[i] = output[i] * fade + buf[i] * (1.0 - fade);
252 output1[i] = output1[i] * fade + buf1[i] * (1.0 - fade);
253 }
254
255 if (ramp_up >= ramp_up_step) {
256 needs_ramp_up = false;
257 ramp_up = 0.0;
258 ramp_down = ramp_down_step;
259 } else {
260 ramp_down = ramp_up;
261 }
262 }
263
264 }
265
connect_all__ports(uint32_t port,void * data)266 void Gx_sceleton_::connect_all__ports(uint32_t port, void* data)
267 {
268 // connect the Ports used by the plug-in class
269 connect_(port,data);
270 // connect the Ports used by the DSP class
271 sceleton->connect_ports(port, data, sceleton);
272 }
273
274 ////////////////////// STATIC CLASS FUNCTIONS ////////////////////////
275
276 LV2_Handle
instantiate(const LV2_Descriptor * descriptor,double rate,const char * bundle_path,const LV2_Feature * const * features)277 Gx_sceleton_::instantiate(const LV2_Descriptor* descriptor,
278 double rate, const char* bundle_path,
279 const LV2_Feature* const* features)
280 {
281 // init the plug-in class
282 Gx_sceleton_ *self = new Gx_sceleton_();
283 if (!self) {
284 return NULL;
285 }
286
287 self->init_dsp_((uint32_t)rate);
288
289 return (LV2_Handle)self;
290 }
291
connect_port(LV2_Handle instance,uint32_t port,void * data)292 void Gx_sceleton_::connect_port(LV2_Handle instance,
293 uint32_t port, void* data)
294 {
295 // connect all ports
296 static_cast<Gx_sceleton_*>(instance)->connect_all__ports(port, data);
297 }
298
activate(LV2_Handle instance)299 void Gx_sceleton_::activate(LV2_Handle instance)
300 {
301 // allocate needed mem
302 static_cast<Gx_sceleton_*>(instance)->activate_f();
303 }
304
run(LV2_Handle instance,uint32_t n_samples)305 void Gx_sceleton_::run(LV2_Handle instance, uint32_t n_samples)
306 {
307 // run dsp
308 static_cast<Gx_sceleton_*>(instance)->run_dsp_(n_samples);
309 }
310
deactivate(LV2_Handle instance)311 void Gx_sceleton_::deactivate(LV2_Handle instance)
312 {
313 // free allocated mem
314 static_cast<Gx_sceleton_*>(instance)->deactivate_f();
315 }
316
cleanup(LV2_Handle instance)317 void Gx_sceleton_::cleanup(LV2_Handle instance)
318 {
319 // well, clean up after us
320 Gx_sceleton_* self = static_cast<Gx_sceleton_*>(instance);
321 self->clean_up();
322 delete self;
323 }
324
325 const LV2_Descriptor Gx_sceleton_::descriptor =
326 {
327 GXPLUGIN_URI "#_sceleton_",
328 Gx_sceleton_::instantiate,
329 Gx_sceleton_::connect_port,
330 Gx_sceleton_::activate,
331 Gx_sceleton_::run,
332 Gx_sceleton_::deactivate,
333 Gx_sceleton_::cleanup,
334 NULL
335 };
336
337
338 } // end namespace sceleton
339
340 ////////////////////////// LV2 SYMBOL EXPORT ///////////////////////////
341
342 extern "C"
343 LV2_SYMBOL_EXPORT
344 const LV2_Descriptor*
lv2_descriptor(uint32_t index)345 lv2_descriptor(uint32_t index)
346 {
347 switch (index)
348 {
349 case 0:
350 return &sceleton::Gx_sceleton_::descriptor;
351 default:
352 return NULL;
353 }
354 }
355
356 ///////////////////////////// FIN //////////////////////////////////////
357