1 /*
2 * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert
3 * Copyright (C) 2011 Pete Shorthose
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * --------------------------------------------------------------------------
19 *
20 *
21 * This is part of the Guitarix Audio Engine
22 *
23 *
24 *
25 * --------------------------------------------------------------------------
26 */
27
28 #include "engine.h"
29 #include "gx_faust_support.h"
30
31 namespace gx_engine {
32
33 /****************************************************************
34 ** class NoiseGate
35 */
36
37 PluginDef NoiseGate::inputdef = PluginDef();
38 float NoiseGate::fnglevel = 0;
39 float NoiseGate::ngate = 1;
40 bool NoiseGate::off = true;
41 Plugin NoiseGate::inputlevel = Plugin();
42 PluginDef NoiseGate::outputgate = PluginDef();
43
NoiseGate()44 NoiseGate::NoiseGate() {
45
46 inputdef.version = PLUGINDEF_VERSION;
47 inputdef.flags = PGN_SNOOP;
48 inputdef.id = "noise_gate";
49 inputdef.name = N_("Noise Gate");
50 inputdef.mono_audio = inputlevel_compute;
51 inputdef.register_params = noisegate_register;
52
53 inputlevel.set_pdef(&inputdef);
54
55 outputgate.version = PLUGINDEF_VERSION;
56 outputgate.id = "noiseshut";
57 outputgate.name = "?noiseshut";
58 outputgate.mono_audio = outputgate_compute;
59 outputgate.activate_plugin = outputgate_activate;
60
61 }
62
sqrf(float x)63 inline float sqrf(float x) {
64 return x * x;
65 }
66
inputlevel_compute(int count,float * input,float * output,PluginDef *)67 void NoiseGate::inputlevel_compute(int count, float *input, float *output, PluginDef*) {
68 float sumnoise = 0;
69 for (int i = 0; i < count; i++) {
70 sumnoise += sqrf(input[i]);
71 }
72 if (sumnoise/count > sqrf(fnglevel * 0.01)) {
73 ngate = 1; // -75db 0.001 = 65db
74 } else if (ngate > 0.01) {
75 ngate *= 0.996;
76 }
77 }
78
noisegate_register(const ParamReg & reg)79 int NoiseGate::noisegate_register(const ParamReg& reg) {
80 reg.registerFloatVar("noise_gate.threshold", N_("Threshold"), "S", "", &fnglevel,
81 0.017f, 0.01f, 0.31f, 0.001f, 0);
82 return 0;
83 }
84
outputgate_compute(int count,float * input,float * output,PluginDef *)85 void NoiseGate::outputgate_compute(int count, float *input, float *output, PluginDef*) {
86 if (off) {
87 return;
88 }
89 while (count--) {
90 *output++ = ngate * *input++;
91 }
92 }
93
outputgate_activate(bool start,PluginDef * pdef)94 int NoiseGate::outputgate_activate(bool start, PluginDef *pdef) {
95 if (start) {
96 off = !inputlevel.get_on_off();
97 }
98 return 0;
99 }
100
101 /****************************************************************
102 ** class GxSeqSettings
103 */
104
GxSeqSettings()105 GxSeqSettings::GxSeqSettings()
106 : seqline() {
107 }
108
operator =(GxSeqSettings const & seqset)109 GxSeqSettings& GxSeqSettings::operator=(GxSeqSettings const& seqset) {
110 seqline = seqset.seqline;
111 return *this;
112 }
113
writeJSON(gx_system::JsonWriter & w) const114 void GxSeqSettings::writeJSON(gx_system::JsonWriter& w) const {
115 w.begin_object(true);
116 w.write_key("seq.seqline");
117 w.begin_array();
118 for (unsigned int i = 0; i < seqline.size(); i++) {
119 w.write(seqline[i]);
120 }
121 w.end_array(true);
122 w.end_object(true);
123 }
124
operator ==(const GxSeqSettings & seqset) const125 bool GxSeqSettings::operator==(const GxSeqSettings& seqset) const {
126 if (seqline != seqset.seqline) {
127 return false;
128 }
129 return true;
130 }
131
read_seqline(gx_system::JsonParser & jp)132 void GxSeqSettings::read_seqline(gx_system::JsonParser& jp) {
133 seqline.clear();
134 jp.next(gx_system::JsonParser::begin_array);
135 while (jp.peek() == gx_system::JsonParser::value_number) {
136 jp.next(gx_system::JsonParser::value_number);
137 int p = jp.current_value_int();
138 seqline.push_back(p);
139 }
140 jp.next(gx_system::JsonParser::end_array);
141 }
142
readJSON(gx_system::JsonParser & jp)143 void GxSeqSettings::readJSON(gx_system::JsonParser& jp) {
144 jp.next(gx_system::JsonParser::begin_object);
145 do {
146 jp.next(gx_system::JsonParser::value_key);
147 if (jp.current_value() == "seq.seqline") {
148 read_seqline(jp);
149 } else {
150 gx_print_warning("seq settings", "unknown key: " + jp.current_value());
151 jp.skip_object();
152 }
153 } while (jp.peek() == gx_system::JsonParser::value_key);
154 jp.next(gx_system::JsonParser::end_object);
155 }
156
157 /****************************************************************
158 ** class SeqParameter
159 */
160
ParameterV(const string & id,GxSeqSettings * v)161 ParameterV<GxSeqSettings>::ParameterV(const string& id, GxSeqSettings *v)
162 : Parameter(id, "", tp_special, None, true, false),
163 json_value(),
164 value(v),
165 std_value(),
166 value_storage(),
167 changed() {
168 std_value.seqline = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
169 }
170
insert_param(ParamMap & pmap,const string & id,GxSeqSettings * v)171 SeqParameter *SeqParameter::insert_param(
172 ParamMap &pmap, const string& id, GxSeqSettings *v) {
173 SeqParameter *p = new SeqParameter(id, v);
174 pmap.insert(p);
175 return p;
176 }
177
~ParameterV()178 SeqParameter::~ParameterV() {
179 }
180
ParameterV(gx_system::JsonParser & jp)181 SeqParameter::ParameterV(gx_system::JsonParser& jp)
182 : Parameter(jp_next(jp, "Parameter")),
183 json_value(),
184 value(&value_storage),
185 std_value() {
186 while (jp.peek() != gx_system::JsonParser::end_object) {
187 jp.next(gx_system::JsonParser::value_key);
188 if (jp.current_value() == "value") {
189 value->readJSON(jp);
190 } else if (jp.current_value() == "std_value") {
191 std_value.readJSON(jp);
192 } else {
193 gx_print_warning(
194 "SeqParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
195 jp.skip_object();
196 }
197 }
198 jp.next(gx_system::JsonParser::end_object);
199 }
200
serializeJSON(gx_system::JsonWriter & jw)201 void SeqParameter::serializeJSON(gx_system::JsonWriter& jw) {
202 jw.begin_object();
203 jw.write_key("Parameter"); Parameter::serializeJSON(jw);
204 jw.write_key("value"); value->writeJSON(jw);
205 jw.write_key("std_value"); std_value.writeJSON(jw);
206 jw.end_object();
207 }
208
on_off_value()209 bool SeqParameter::on_off_value() {
210 assert(false);
211 return false;
212 }
213
stdJSON_value()214 void SeqParameter::stdJSON_value() {
215 json_value = std_value;
216 }
217
writeJSON(gx_system::JsonWriter & jw) const218 void SeqParameter::writeJSON(gx_system::JsonWriter& jw) const {
219 jw.write_key(_id.c_str());
220 value->writeJSON(jw);
221 }
222
readJSON_value(gx_system::JsonParser & jp)223 void SeqParameter::readJSON_value(gx_system::JsonParser& jp) {
224 json_value.readJSON(jp);
225 }
226
compareJSON_value()227 bool SeqParameter::compareJSON_value() {
228 return json_value == *value;
229 }
230
set(const GxSeqSettings & val) const231 bool SeqParameter::set(const GxSeqSettings& val) const {
232 if (val == *value) {
233 return false;
234 }
235 *value = val;
236 changed(value);
237 return true;
238 }
239
setJSON_value()240 void SeqParameter::setJSON_value() {
241 set(json_value);
242 }
243
244 /****************************************************************
245 ** class GxJConvSettings
246 */
247
GxJConvSettings()248 GxJConvSettings::GxJConvSettings()
249 : fIRFile(),
250 fIRDir(),
251 fGain(0),
252 fOffset(0),
253 fLength(0),
254 fDelay(0),
255 gainline(),
256 fGainCor(false) {
257 }
258
operator =(GxJConvSettings const & jcset)259 GxJConvSettings& GxJConvSettings::operator=(GxJConvSettings const& jcset) {
260 fIRFile = jcset.fIRFile;
261 fIRDir = jcset.fIRDir;
262 fGain = jcset.fGain;
263 fOffset = jcset.fOffset;
264 fLength = jcset.fLength;
265 fDelay = jcset.fDelay;
266 gainline = jcset.gainline;
267 fGainCor = jcset.fGainCor;
268 return *this;
269 }
270
getFullIRPath() const271 std::string GxJConvSettings::getFullIRPath() const {
272 if (fIRFile.empty()) {
273 return fIRFile;
274 } else {
275 return Glib::build_filename(fIRDir, fIRFile);
276 }
277 }
278
setFullIRPath(string name)279 void GxJConvSettings::setFullIRPath(string name) {
280 fIRDir = Glib::path_get_dirname(name);
281 fIRFile= Glib::path_get_basename(name);
282 }
283
writeJSON(gx_system::JsonWriter & w) const284 void GxJConvSettings::writeJSON(gx_system::JsonWriter& w) const {
285 w.begin_object(true);
286 w.write_kv("jconv.IRFile", fIRFile);
287 w.write_kv("jconv.IRDir", gx_system::get_options().get_IR_prefixmap().replace_path(fIRDir));
288 w.write_kv("jconv.Gain", fGain);
289 w.write_kv("jconv.GainCor", fGainCor);
290 w.write_kv("jconv.Offset", fOffset);
291 w.write_kv("jconv.Length", fLength);
292 w.write_kv("jconv.Delay", fDelay);
293 w.write_key("jconv.gainline");
294 w.begin_array();
295 for (unsigned int i = 0; i < gainline.size(); i++) {
296 w.begin_array();
297 w.write(gainline[i].i);
298 w.write(gainline[i].g);
299 w.end_array();
300 }
301 w.end_array(true);
302 w.end_object(true);
303 }
304
operator ==(const GxJConvSettings & jcset) const305 bool GxJConvSettings::operator==(const GxJConvSettings& jcset) const {
306 if (fIRFile != jcset.fIRFile || fIRDir != jcset.fIRDir) {
307 return false;
308 }
309 if (fOffset != jcset.fOffset || fLength != jcset.fLength || fDelay != jcset.fDelay) {
310 return false;
311 }
312 if (fGainCor != jcset.fGainCor) {
313 return false;
314 }
315 if (fGainCor && std::abs(fGain - jcset.fGain) > 1e-4 * (fGain + jcset.fGain)) {
316 return false;
317 }
318 if (gainline == jcset.gainline) {
319 return false;
320 }
321 return true;
322 }
323
read_gainline(gx_system::JsonParser & jp)324 void GxJConvSettings::read_gainline(gx_system::JsonParser& jp) {
325 gainline.clear();
326 jp.next(gx_system::JsonParser::begin_array);
327 while (jp.peek() == gx_system::JsonParser::begin_array) {
328 jp.next();
329 jp.next(gx_system::JsonParser::value_number);
330 gain_points p;
331 p.i = jp.current_value_int();
332 jp.next(gx_system::JsonParser::value_number);
333 p.g = jp.current_value_float();
334 jp.next(gx_system::JsonParser::end_array);
335 gainline.push_back(p);
336 }
337 jp.next(gx_system::JsonParser::end_array);
338 }
339
readJSON(gx_system::JsonParser & jp)340 void GxJConvSettings::readJSON(gx_system::JsonParser& jp) {
341 jp.next(gx_system::JsonParser::begin_object);
342 do {
343 jp.next(gx_system::JsonParser::value_key);
344 if (jp.read_kv("jconv.IRFile", fIRFile) ||
345 jp.read_kv("jconv.IRDir", fIRDir) ||
346 jp.read_kv("jconv.Gain", fGain) ||
347 jp.read_kv("jconv.GainCor", fGainCor) ||
348 jp.read_kv("jconv.Offset", fOffset) ||
349 jp.read_kv("jconv.Length", fLength) ||
350 jp.read_kv("jconv.Delay", fDelay)) {
351 } else if (jp.current_value() == "jconv.gainline") {
352 read_gainline(jp);
353 } else if (jp.current_value() == "jconv.favorits") {
354 jp.skip_object();
355 } else {
356 gx_print_warning("jconv settings", "unknown key: " + jp.current_value());
357 jp.skip_object();
358 }
359 } while (jp.peek() == gx_system::JsonParser::value_key);
360 jp.next(gx_system::JsonParser::end_object);
361 if (!fIRFile.empty()) {
362 if (fIRDir.empty()) {
363 gx_system::get_options().get_IR_pathlist().find_dir(&fIRDir, fIRFile);
364 } else {
365 fIRDir = gx_system::get_options().get_IR_prefixmap().replace_symbol(fIRDir);
366 }
367 }
368 }
369
370
371 /****************************************************************
372 ** class JConvParameter
373 */
374
ParameterV(const string & id,gx_engine::ConvolverAdapter & conv,GxJConvSettings * v)375 ParameterV<GxJConvSettings>::ParameterV(const string& id, gx_engine::ConvolverAdapter& conv, GxJConvSettings *v)
376 : Parameter(id, "", tp_special, None, true, false),
377 json_value(),
378 value(v),
379 std_value(),
380 value_storage(),
381 changed() {
382 std_value.setFullIRPath(gx_system::get_options().get_IR_prefixmap().replace_symbol("%S/greathall.wav"));
383 std_value.fGainCor = true;
384 std_value.fGain = 0.598717;
385 const int ir_len = 112561;
386 std_value.fLength = ir_len;
387 static gain_points g[2] = {{0, 0}, {ir_len-1, 0}};
388 std_value.gainline = Gainline(g, sizeof(g) / sizeof(g[0]));
389 }
390
insert_param(ParamMap & pmap,const string & id,ConvolverAdapter & conv,GxJConvSettings * v)391 JConvParameter *JConvParameter::insert_param(
392 ParamMap &pmap, const string& id, ConvolverAdapter &conv, GxJConvSettings *v) {
393 JConvParameter *p = new JConvParameter(id, conv, v);
394 pmap.insert(p);
395 return p;
396 }
397
~ParameterV()398 JConvParameter::~ParameterV() {
399 }
400
ParameterV(gx_system::JsonParser & jp)401 JConvParameter::ParameterV(gx_system::JsonParser& jp)
402 : Parameter(jp_next(jp, "Parameter")),
403 json_value(),
404 value(&value_storage),
405 std_value() {
406 while (jp.peek() != gx_system::JsonParser::end_object) {
407 jp.next(gx_system::JsonParser::value_key);
408 if (jp.current_value() == "value") {
409 value->readJSON(jp);
410 } else if (jp.current_value() == "std_value") {
411 std_value.readJSON(jp);
412 } else {
413 gx_print_warning(
414 "JConvParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
415 jp.skip_object();
416 }
417 }
418 jp.next(gx_system::JsonParser::end_object);
419 }
420
serializeJSON(gx_system::JsonWriter & jw)421 void JConvParameter::serializeJSON(gx_system::JsonWriter& jw) {
422 jw.begin_object();
423 jw.write_key("Parameter"); Parameter::serializeJSON(jw);
424 jw.write_key("value"); value->writeJSON(jw);
425 jw.write_key("std_value"); std_value.writeJSON(jw);
426 jw.end_object();
427 }
428
on_off_value()429 bool JConvParameter::on_off_value() {
430 assert(false);
431 return false;
432 }
433
stdJSON_value()434 void JConvParameter::stdJSON_value() {
435 json_value = std_value;
436 }
437
writeJSON(gx_system::JsonWriter & jw) const438 void JConvParameter::writeJSON(gx_system::JsonWriter& jw) const {
439 jw.write_key(_id.c_str());
440 value->writeJSON(jw);
441 }
442
readJSON_value(gx_system::JsonParser & jp)443 void JConvParameter::readJSON_value(gx_system::JsonParser& jp) {
444 json_value.readJSON(jp);
445 }
446
compareJSON_value()447 bool JConvParameter::compareJSON_value() {
448 return json_value == *value;
449 }
450
set(const GxJConvSettings & val) const451 bool JConvParameter::set(const GxJConvSettings& val) const {
452 if (val == *value) {
453 return false;
454 }
455 *value = val;
456 changed(value);
457 return true;
458 }
459
setJSON_value()460 void JConvParameter::setJSON_value() {
461 set(json_value);
462 }
463
464
465 /****************************************************************
466 ** class ConvolverAdapter
467 */
468
469 #include "faust/jconv_post.cc"
470 #include "faust/jconv_post_mono.cc"
471
ConvolverAdapter(EngineControl & engine_,sigc::slot<void> sync_)472 ConvolverAdapter::ConvolverAdapter(
473 EngineControl& engine_, sigc::slot<void> sync_)
474 : PluginDef(),
475 conv(),
476 activate_mutex(),
477 engine(engine_),
478 sync(sync_),
479 activated(false),
480 jcset(),
481 jcp(0),
482 plugin() {
483 version = PLUGINDEF_VERSION;
484 category = N_("Reverb");
485 //FIXME: add clear_state
486 plugin = this;
487 engine.signal_buffersize_change().connect(
488 sigc::mem_fun(*this, &ConvolverAdapter::change_buffersize));
489 }
490
~ConvolverAdapter()491 ConvolverAdapter::~ConvolverAdapter() {
492 }
493
change_buffersize(unsigned int size)494 void ConvolverAdapter::change_buffersize(unsigned int size) {
495 boost::mutex::scoped_lock lock(activate_mutex);
496 if (activated) {
497 conv.stop_process();
498 while (conv.is_runnable()) {
499 conv.checkstate();
500 }
501 conv.set_buffersize(size);
502 if (size) {
503 conv_start();
504 }
505 } else {
506 conv.set_buffersize(size);
507 }
508 }
509
restart()510 void ConvolverAdapter::restart() {
511 if (!plugin.get_on_off()) {
512 return;
513 }
514 conv.set_not_runnable();
515 sync();
516 conv.stop_process();
517 while (!conv.checkstate());
518 float gain;
519 if (jcset.getGainCor()) {
520 gain = jcset.getGain();
521 } else {
522 gain = 1.0;
523 }
524 bool rc = conv.configure(
525 jcset.getFullIRPath(), gain, gain, jcset.getDelay(), jcset.getDelay(),
526 jcset.getOffset(), jcset.getLength(), 0, 0, jcset.getGainline());
527 int policy, priority;
528 engine.get_sched_priority(policy, priority);
529 if (!rc || !conv.start(policy, priority)) {
530 plugin.set_on_off(false);
531 }
532 }
533
conv_start()534 bool ConvolverAdapter::conv_start() {
535 if (!conv.get_buffersize() || !conv.get_samplerate()) {
536 return false;
537 }
538 string path = jcset.getFullIRPath();
539 if (path.empty()) {
540 gx_print_warning(_("convolver"), _("no impulseresponse file"));
541 plugin.set_on_off(false);
542 return false;
543 }
544 while (!conv.checkstate());
545 if (conv.is_runnable()) {
546 return true;
547 }
548 float gain;
549 if (jcset.getGainCor()) {
550 gain = jcset.getGain();
551 } else {
552 gain = 1.0;
553 }
554 if (!conv.configure(
555 path, gain, gain, jcset.getDelay(), jcset.getDelay(),
556 jcset.getOffset(), jcset.getLength(), 0, 0, jcset.getGainline())) {
557 return false;
558 }
559 int policy, priority;
560 engine.get_sched_priority(policy, priority);
561 return conv.start(policy, priority);
562 }
563
564
565 /****************************************************************
566 ** class ConvolverStereoAdapter
567 */
568
ConvolverStereoAdapter(EngineControl & engine_,sigc::slot<void> sync_)569 ConvolverStereoAdapter::ConvolverStereoAdapter(
570 EngineControl& engine_, sigc::slot<void> sync_)
571 : ConvolverAdapter(engine_, sync_) {
572 id = "jconv";
573 name = N_("Convolver");
574 register_params = convolver_register;
575 set_samplerate = convolver_init;
576 activate_plugin = activate;
577 load_ui = jconv_load_ui;
578 stereo_audio = convolver;
579 }
580
~ConvolverStereoAdapter()581 ConvolverStereoAdapter::~ConvolverStereoAdapter() {
582 }
583
convolver(int count,float * input0,float * input1,float * output0,float * output1,PluginDef * plugin)584 void ConvolverStereoAdapter::convolver(int count, float *input0, float *input1,
585 float *output0, float *output1, PluginDef* plugin) {
586 ConvolverStereoAdapter& self = *static_cast<ConvolverStereoAdapter*>(plugin);
587 if (self.conv.is_runnable()) {
588 float conv_out0[count];
589 float conv_out1[count];
590 if (self.conv.compute(count, input0, input1, conv_out0, conv_out1)) {
591 self.jc_post.compute(count, input0, input1,
592 conv_out0, conv_out1, output0, output1);
593 return;
594 }
595 self.engine.overload(EngineControl::ov_Convolver, self.id);
596 }
597 if (input0 != output0) {
598 memcpy(output0, input0, count * sizeof(float));
599 }
600 if (input1 != output1) {
601 memcpy(output1, input1, count * sizeof(float));
602 }
603 }
604
convolver_register(const ParamReg & reg)605 int ConvolverStereoAdapter::convolver_register(const ParamReg& reg) {
606 ConvolverStereoAdapter& self = *static_cast<ConvolverStereoAdapter*>(reg.plugin);
607 self.jcp = JConvParameter::insert_param(self.get_parameter_map(), "jconv.convolver", self, &self.jcset);
608 self.jcp->signal_changed().connect(
609 sigc::hide(
610 sigc::mem_fun(self, &ConvolverStereoAdapter::restart)));
611 return self.jc_post.register_par(reg);
612 }
613
convolver_init(unsigned int samplingFreq,PluginDef * p)614 void ConvolverStereoAdapter::convolver_init(unsigned int samplingFreq, PluginDef *p) {
615 ConvolverStereoAdapter& self = *static_cast<ConvolverStereoAdapter*>(p);
616 boost::mutex::scoped_lock lock(self.activate_mutex);
617 if (self.activated) {
618 self.conv.stop_process();
619 self.conv.set_samplerate(samplingFreq);
620 self.jc_post.init(samplingFreq);
621 while (self.conv.is_runnable()) {
622 self.conv.checkstate();
623 }
624 self.conv_start();
625 } else {
626 self.conv.set_samplerate(samplingFreq);
627 self.jc_post.init(samplingFreq);
628 }
629 }
630
activate(bool start,PluginDef * p)631 int ConvolverStereoAdapter::activate(bool start, PluginDef *p) {
632 ConvolverStereoAdapter& self = *static_cast<ConvolverStereoAdapter*>(p);
633 boost::mutex::scoped_lock lock(self.activate_mutex);
634 if (start) {
635 if (self.activated && self.conv.is_runnable()) {
636 return 0;
637 }
638 } else {
639 if (!self.activated) {
640 return 0;
641 }
642 }
643 self.activated = start;
644 if (start) {
645 if (self.jc_post.activate(true) != 0) {
646 gx_print_error(_("convolver"), "jconv post activate error?!");
647 return -1;
648 }
649 if (!self.conv_start()) {
650 return -1;
651 }
652 } else {
653 self.conv.stop_process();
654 self.jc_post.activate(false);
655 }
656 return 0;
657 }
658
659 //static
jconv_load_ui(const UiBuilder & builder,int format)660 int ConvolverStereoAdapter::jconv_load_ui(const UiBuilder& builder, int format) {
661 if (format & UI_FORM_GLADE) {
662 builder.load_glade_file("jconv_st_ui.glade");
663 return 0;
664 } else if (format & UI_FORM_STACK) {
665 //static gx_jconv::IRWindow *irw = gx_jconv::IRWindow::create("jconv", window_icon, machine, accels, 2);
666 builder.openHorizontalhideBox("");
667 {
668 builder.create_master_slider("jconv.wet_dry", _("Dry/Wet"));
669 builder.insertSpacer();
670 builder.insertSpacer();
671 //builder.addSmallJConvFavButton(C_("Setup", "S"), irw);
672 }
673 builder.closeBox();
674 builder.openVerticalBox("");
675 {
676 //builder.openSetLabelBox();
677 //builder.closeBox();
678 builder.insertSpacer();
679 builder.openHorizontalBox("");
680 {
681 builder.insertSpacer();
682 builder.insertSpacer();
683 builder.insertSpacer();
684 builder.insertSpacer();
685 builder.create_mid_rackknob("jconv.gain", _("Gain"));
686 builder.create_small_rackknobr("jconv.diff_delay", _("Delta Delay"));
687 builder.create_small_rackknobr("jconv.balance", _("Balance"));
688 builder.create_small_rackknobr("jconv.wet_dry", _("Dry/Wet"));
689 builder.openVerticalBox("");
690 {
691 builder.insertSpacer();
692 builder.insertSpacer();
693 //builder.addJConvButton(_("Setup"), irw);
694 builder.insertSpacer();
695 }
696 builder.closeBox();
697 builder.insertSpacer();
698 builder.insertSpacer();
699 builder.insertSpacer();
700 }
701 builder.closeBox();
702 }
703 builder.closeBox();
704 return 0;
705 } else {
706 return -1;
707 }
708 }
709
710
711 /****************************************************************
712 ** class ConvolverMonoAdapter
713 */
714
ConvolverMonoAdapter(EngineControl & engine_,sigc::slot<void> sync_)715 ConvolverMonoAdapter::ConvolverMonoAdapter(
716 EngineControl& engine_, sigc::slot<void> sync_)
717 : ConvolverAdapter(engine_, sync_) {
718 id = "jconv_mono";
719 name = N_("Convolver");
720 register_params = convolver_register;
721 set_samplerate = convolver_init;
722 activate_plugin = activate;
723 load_ui = jconv_load_ui;
724 mono_audio = convolver;
725 }
726
~ConvolverMonoAdapter()727 ConvolverMonoAdapter::~ConvolverMonoAdapter() {
728 }
729
convolver(int count,float * input,float * output,PluginDef * plugin)730 void ConvolverMonoAdapter::convolver(int count, float *input, float *output, PluginDef* plugin) {
731 ConvolverMonoAdapter& self = *static_cast<ConvolverMonoAdapter*>(plugin);
732 if (self.conv.is_runnable()) {
733 float conv_out[count];
734 if (self.conv.compute(count, input, conv_out)) {
735 self.jc_post_mono.compute(count, output, conv_out, output);
736 return;
737 }
738 self.engine.overload(EngineControl::ov_Convolver, self.id);
739 }
740 if (input != output) {
741 memcpy(output, input, count * sizeof(float));
742 }
743 }
744
convolver_register(const ParamReg & reg)745 int ConvolverMonoAdapter::convolver_register(const ParamReg& reg) {
746 ConvolverMonoAdapter& self = *static_cast<ConvolverMonoAdapter*>(reg.plugin);
747 self.jcp = JConvParameter::insert_param(self.get_parameter_map(), "jconv_mono.convolver", self, &self.jcset);
748 self.jcp->signal_changed().connect(
749 sigc::hide(
750 sigc::mem_fun(self, &ConvolverMonoAdapter::restart)));
751 return self.jc_post_mono.register_par(reg);;
752 }
753
convolver_init(unsigned int samplingFreq,PluginDef * p)754 void ConvolverMonoAdapter::convolver_init(unsigned int samplingFreq, PluginDef *p) {
755 ConvolverMonoAdapter& self = *static_cast<ConvolverMonoAdapter*>(p);
756 boost::mutex::scoped_lock lock(self.activate_mutex);
757 if (self.activated) {
758 self.conv.stop_process();
759 self.conv.set_samplerate(samplingFreq);
760 while (self.conv.is_runnable()) {
761 self.conv.checkstate();
762 }
763 self.conv_start();
764 } else {
765 self.conv.set_samplerate(samplingFreq);
766 }
767 }
768
activate(bool start,PluginDef * p)769 int ConvolverMonoAdapter::activate(bool start, PluginDef *p) {
770 ConvolverMonoAdapter& self = *static_cast<ConvolverMonoAdapter*>(p);
771 boost::mutex::scoped_lock lock(self.activate_mutex);
772 if (start) {
773 if (self.activated && self.conv.is_runnable()) {
774 return 0;
775 }
776 } else {
777 if (!self.activated) {
778 return 0;
779 }
780 }
781 self.activated = start;
782 if (start) {
783 if (!self.conv_start()) {
784 return -1;
785 }
786 } else {
787 self.conv.stop_process();
788 }
789 return 0;
790 }
791
792 //static
jconv_load_ui(const UiBuilder & builder,int format)793 int ConvolverMonoAdapter::jconv_load_ui(const UiBuilder& builder, int format) {
794 if (format & UI_FORM_GLADE) {
795 builder.load_glade_file("jconv_ui.glade");
796 return 0;
797 } else if (format & UI_FORM_STACK) {
798 //static gx_jconv::IRWindow *irw = gx_jconv::IRWindow::create(
799 // "jconv_mono", b->window_icon, b->machine, b->accels, 1);
800 builder.openHorizontalhideBox("");
801 builder.create_master_slider("jconv_mono.wet_dry", _("Dry/Wet"));
802 builder.insertSpacer();
803 builder.insertSpacer();
804 //builder.addSmallJConvFavButton(C_("Setup", "S"), irw);
805 builder.closeBox();
806 builder.openVerticalBox("");
807 {
808 //builder.openSetMonoLabelBox();
809 //builder.closeBox();
810 builder.insertSpacer();
811 builder.openHorizontalBox("");
812 {
813 builder.insertSpacer();
814 builder.insertSpacer();
815 builder.insertSpacer();
816 builder.insertSpacer();
817 builder.insertSpacer();
818 builder.insertSpacer();
819 builder.create_mid_rackknob("jconv_mono.gain", _("Gain"));
820 builder.create_small_rackknobr("jconv_mono.wet_dry", _("Dry/Wet"));
821 builder.openVerticalBox("");
822 builder.insertSpacer();
823 builder.insertSpacer();
824 //builder.addJConvButton(_("Setup"), irw);
825 builder.insertSpacer();
826 builder.closeBox();
827 builder.insertSpacer();
828 builder.insertSpacer();
829 builder.insertSpacer();
830 builder.insertSpacer();
831 builder.insertSpacer();
832 builder.insertSpacer();
833 }
834 builder.closeBox();
835 }
836 builder.closeBox();
837 return 0;
838 } else {
839 return -1;
840 }
841 }
842
843 /****************************************************************
844 ** class BaseConvolver
845 */
846
847
BaseConvolver(EngineControl & engine_,sigc::slot<void> sync_,gx_resample::BufferResampler & resamp)848 BaseConvolver::BaseConvolver(EngineControl& engine_, sigc::slot<void> sync_, gx_resample::BufferResampler& resamp)
849 : PluginDef(),
850 conv(resamp),
851 activate_mutex(),
852 engine(engine_),
853 sync(sync_),
854 activated(false),
855 plugin() {
856 version = PLUGINDEF_VERSION;
857 set_samplerate = init;
858 activate_plugin = activate;
859 plugin = this;
860 engine.signal_buffersize_change().connect(
861 sigc::mem_fun(*this, &BaseConvolver::change_buffersize));
862 }
863
~BaseConvolver()864 BaseConvolver::~BaseConvolver() {
865 update_conn.disconnect();
866 }
867
change_buffersize(unsigned int bufsize)868 void BaseConvolver::change_buffersize(unsigned int bufsize) {
869 boost::mutex::scoped_lock lock(activate_mutex);
870 conv.set_buffersize(bufsize);
871 if (activated) {
872 if (!bufsize) {
873 conv.stop_process();
874 } else {
875 start(true);
876 }
877 }
878 }
879
init(unsigned int samplingFreq,PluginDef * p)880 void BaseConvolver::init(unsigned int samplingFreq, PluginDef *p) {
881 BaseConvolver& self = *static_cast<BaseConvolver*>(p);
882 boost::mutex::scoped_lock lock(self.activate_mutex);
883 self.conv.set_samplerate(samplingFreq);
884 if (self.activated) {
885 self.start(true);
886 }
887 }
888
check_update_timeout()889 bool BaseConvolver::check_update_timeout() {
890 if (!activated || !plugin.get_on_off()) {
891 return false;
892 }
893 check_update();
894 return true;
895 }
896
activate(bool start,PluginDef * p)897 int BaseConvolver::activate(bool start, PluginDef *p) {
898 BaseConvolver& self = *static_cast<BaseConvolver*>(p);
899 boost::mutex::scoped_lock lock(self.activate_mutex);
900 if (start) {
901 if (!self.conv.get_buffersize()) {
902 start = false;
903 }
904 }
905 if (start == self.activated) {
906 return 0;
907 }
908 if (start) {
909 if (!self.start()) {
910 return -1;
911 }
912 self.update_conn = Glib::signal_timeout().connect(
913 sigc::mem_fun(self, &BaseConvolver::check_update_timeout), 200);
914 } else {
915 self.conv.stop_process();
916 }
917 self.activated = start;
918 return 0;
919 }
920
conv_start()921 int BaseConvolver::conv_start() {
922 int policy, priority;
923 engine.get_sched_priority(policy, priority);
924 return conv.start(policy, priority);
925 }
926
927 /****************************************************************
928 ** class FixedBaseConvolver
929 */
930
931
FixedBaseConvolver(EngineControl & engine_,sigc::slot<void> sync_,gx_resample::BufferResampler & resamp)932 FixedBaseConvolver::FixedBaseConvolver(EngineControl& engine_, sigc::slot<void> sync_, gx_resample::BufferResampler& resamp)
933 : PluginDef(),
934 conv(resamp),
935 activate_mutex(),
936 engine(engine_),
937 sync(sync_),
938 activated(false),
939 SamplingFreq(0),
940 buffersize(0),
941 bz(0.0),
942 plugin() {
943 version = PLUGINDEF_VERSION;
944 set_samplerate = init;
945 activate_plugin = activate;
946 plugin = this;
947 engine.signal_buffersize_change().connect(
948 sigc::mem_fun(*this, &FixedBaseConvolver::change_buffersize));
949 }
950
~FixedBaseConvolver()951 FixedBaseConvolver::~FixedBaseConvolver() {
952 update_conn.disconnect();
953 }
954
change_buffersize(unsigned int bufsize)955 void FixedBaseConvolver::change_buffersize(unsigned int bufsize) {
956 boost::mutex::scoped_lock lock(activate_mutex);
957 buffersize = bufsize;
958 conv.set_buffersize(static_cast<int>(ceil((bufsize*bz))));
959 if (activated) {
960 if (!bufsize) {
961 conv.stop_process();
962 } else {
963 start(true);
964 }
965 }
966 }
967
init(unsigned int samplingFreq,PluginDef * p)968 void FixedBaseConvolver::init(unsigned int samplingFreq, PluginDef *p) {
969 FixedBaseConvolver& self = *static_cast<FixedBaseConvolver*>(p);
970 boost::mutex::scoped_lock lock(self.activate_mutex);
971 self.SamplingFreq = samplingFreq;
972 self.bz = 96000/samplingFreq;
973 self.conv.set_buffersize(static_cast<int>(ceil((self.buffersize*self.bz))));
974 self.conv.set_samplerate(self.bz*self.SamplingFreq);
975 if (self.activated) {
976 self.start(true);
977 }
978 }
979
check_update_timeout()980 bool FixedBaseConvolver::check_update_timeout() {
981 if (!activated || !plugin.get_on_off()) {
982 return false;
983 }
984 check_update();
985 return true;
986 }
987
activate(bool start,PluginDef * p)988 int FixedBaseConvolver::activate(bool start, PluginDef *p) {
989 FixedBaseConvolver& self = *static_cast<FixedBaseConvolver*>(p);
990 boost::mutex::scoped_lock lock(self.activate_mutex);
991 if (start) {
992 if (!self.conv.get_buffersize()) {
993 start = false;
994 }
995 }
996 if (start == self.activated) {
997 return 0;
998 }
999 if (start) {
1000 if (!self.start()) {
1001 return -1;
1002 }
1003 self.update_conn = Glib::signal_timeout().connect(
1004 sigc::mem_fun(self, &FixedBaseConvolver::check_update_timeout), 200);
1005 } else {
1006 self.conv.stop_process();
1007 }
1008 self.activated = start;
1009 return 0;
1010 }
1011
conv_start()1012 int FixedBaseConvolver::conv_start() {
1013 int policy, priority;
1014 engine.get_sched_priority(policy, priority);
1015 return conv.start(policy, priority);
1016 }
1017
1018 /****************************************************************
1019 ** class CabinetConvolver
1020 */
1021
1022 struct CabDesc {
1023 int ir_count;
1024 int ir_sr;
1025 float ir_data[];
1026 };
1027
1028 template <int tab_size>
1029 struct CabDesc_imp {
1030 int ir_count;
1031 int ir_sr;
1032 float ir_data[tab_size];
operator CabDesc&gx_engine::CabDesc_imp1033 operator CabDesc&() { return *(CabDesc*)this; }
1034 };
1035
1036 #include "gx_cabinet_data.cc"
1037
1038 struct CabEntry {
1039 const char *value_id;
1040 const char *value_label;
1041 CabDesc *data;
1042 } cab_table[] = {
1043 { "4x12", N_("4x12"), &static_cast<CabDesc&>(cab_data_4x12) },
1044 { "2x12", N_("2x12"), &static_cast<CabDesc&>(cab_data_2x12) },
1045 { "1x12", N_("1x12"), &static_cast<CabDesc&>(cab_data_1x12) },
1046 { "4x10", N_("4x10"), &static_cast<CabDesc&>(cab_data_4x10) },
1047 { "2x10", N_("2x10"), &static_cast<CabDesc&>(cab_data_2x10) },
1048 { "HighGain", N_("HighGain Style"), &static_cast<CabDesc&>(cab_data_HighGain) },
1049 { "Twin", N_("Twin Style"), &static_cast<CabDesc&>(cab_data_Twin) },
1050 { "Bassman", N_("Bassman Style"), &static_cast<CabDesc&>(cab_data_Bassman) },
1051 { "Marshall", N_("Marshall Style"), &static_cast<CabDesc&>(cab_data_Marshall) },
1052 { "AC-30", N_("AC-30 Style"), &static_cast<CabDesc&>(cab_data_AC30) },
1053 { "Princeton", N_("Princeton Style"), &static_cast<CabDesc&>(cab_data_Princeton) },
1054 { "A2", N_("A2 Style"), &static_cast<CabDesc&>(cab_data_A2) },
1055 { "1x15", N_("1x15"), &static_cast<CabDesc&>(cab_data_1x15) },
1056 { "Mesa Boogie", N_("Mesa Boogie Style"), &static_cast<CabDesc&>(cab_data_mesa) },
1057 { "Briliant", N_("Briliant"), &static_cast<CabDesc&>(cab_data_briliant) },
1058 { "Vitalize", N_("Vitalize"), &static_cast<CabDesc&>(cab_data_vitalize) },
1059 { "Charisma", N_("Charisma"), &static_cast<CabDesc&>(cab_data_charisma) },
1060 };
1061 static const unsigned int cab_table_size = sizeof(cab_table) / sizeof(cab_table[0]);
1062
getCabEntry(unsigned int n)1063 static CabEntry& getCabEntry(unsigned int n) {
1064 if (n >= cab_table_size) {
1065 n = cab_table_size - 1;
1066 }
1067 return cab_table[n];
1068 }
1069
1070 static const float no_sum = 1e10;
1071
1072 #include "faust/cabinet_impulse_former.cc"
1073
cab_load_ui(const UiBuilder & builder,int format)1074 static int cab_load_ui(const UiBuilder& builder, int format) {
1075 if (format & UI_FORM_GLADE) {
1076 builder.load_glade_file("cabinet_ui.glade");
1077 return 0;
1078 } else if (format & UI_FORM_STACK) {
1079 builder.openHorizontalhideBox("");
1080 builder.create_selector_no_caption("cab.select");
1081 builder.closeBox();
1082 builder.openVerticalBox("");
1083 {
1084 builder.openHorizontalBox("");
1085 {
1086 builder.insertSpacer();
1087 builder.create_selector_no_caption("cab.select");
1088 builder.create_small_rackknobr("cab.bass", "Bass");
1089 builder.create_small_rackknobr("cab.treble", "Treble");
1090 builder.create_mid_rackknob("cab.Level", "Level");
1091 }
1092 builder.closeBox();
1093 }
1094 builder.closeBox();
1095 return 0;
1096 } else {
1097 return -1;
1098 }
1099
1100 }
1101
CabinetConvolver(EngineControl & engine,sigc::slot<void> sync,gx_resample::BufferResampler & resamp)1102 CabinetConvolver::CabinetConvolver(EngineControl& engine, sigc::slot<void> sync,
1103 gx_resample::BufferResampler& resamp):
1104 FixedBaseConvolver(engine, sync, resamp),
1105 current_cab(-1),
1106 level(0),
1107 cabinet(0),
1108 bass(0),
1109 treble(0),
1110 sum(no_sum),
1111 cab_names(new value_pair[cab_table_size+1]),
1112 impf(),
1113 smp() {
1114 for (unsigned int i = 0; i < cab_table_size; ++i) {
1115 CabEntry& cab = getCabEntry(i);
1116 cab_names[i].value_id = cab.value_id;
1117 cab_names[i].value_label = cab.value_label;
1118 }
1119 cab_names[cab_table_size].value_id = 0;
1120 cab_names[cab_table_size].value_label = 0;
1121 id = "cab";
1122 name = N_("Cabinet");
1123 category = N_("Tone Control");
1124 load_ui = cab_load_ui;
1125 mono_audio = run_cab_conf;
1126 register_params = register_cab;
1127 }
1128
~CabinetConvolver()1129 CabinetConvolver::~CabinetConvolver() {
1130 delete[] cab_names;
1131 }
1132
do_update()1133 bool CabinetConvolver::do_update() {
1134 bool configure = cabinet_changed();
1135 if (conv.is_runnable()) {
1136 conv.set_not_runnable();
1137 sync();
1138 conv.stop_process();
1139 }
1140 CabDesc& cab = *getCabEntry(cabinet).data;
1141 if (current_cab == -1) {
1142 unsigned int sr = getSamplingFreq();
1143 unsigned int sru = 96000;
1144 unsigned int fact = sru/sr;
1145
1146 smp.setup(sr, fact*sr);
1147 impf.init(cab.ir_sr);
1148 }
1149 float cab_irdata_c[cab.ir_count];
1150 impf.clear_state_f();
1151 impf.compute(cab.ir_count,cab.ir_data,cab_irdata_c);
1152 while (!conv.checkstate());
1153 if (configure) {
1154 if (!conv.configure(cab.ir_count, cab_irdata_c, cab.ir_sr)) {
1155 return false;
1156 }
1157 } else {
1158 if (!conv.update(cab.ir_count, cab_irdata_c, cab.ir_sr)) {
1159 return false;
1160 }
1161 }
1162 update_cabinet();
1163 update_sum();
1164 return conv_start();
1165 }
1166
start(bool force)1167 bool CabinetConvolver::start(bool force) {
1168 if (force) {
1169 current_cab = -1;
1170 }
1171 if (cabinet_changed() || sum_changed()) {
1172 return do_update();
1173 } else {
1174 while (!conv.checkstate());
1175 if (!conv.is_runnable()) {
1176 return conv_start();
1177 }
1178 return true;
1179 }
1180 }
1181
check_update()1182 void CabinetConvolver::check_update() {
1183 if (cabinet_changed() || sum_changed()) {
1184 do_update();
1185 }
1186 }
1187
run_cab_conf(int count,float * input0,float * output0,PluginDef * p)1188 void CabinetConvolver::run_cab_conf(int count, float *input0, float *output0, PluginDef *p) {
1189 CabinetConvolver& self = *static_cast<CabinetConvolver*>(p);
1190 FAUSTFLOAT buf[self.smp.max_out_count(count)];
1191 int ReCount = self.smp.up(count, output0, buf);
1192 if (!self.conv.compute(ReCount,buf)) {
1193 self.engine.overload(EngineControl::ov_Convolver, "cab");
1194 }
1195 self.smp.down(buf, output0);
1196 }
1197
register_cab(const ParamReg & reg)1198 int CabinetConvolver::register_cab(const ParamReg& reg) {
1199 CabinetConvolver& cab = *static_cast<CabinetConvolver*>(reg.plugin);
1200 reg.registerIntVar("cab.select", "select", "B", "", &cab.cabinet, 0, 0, 0, cab.cab_names);
1201 reg.registerFloatVar("cab.Level", N_("Level"), "S", N_("Level"), &cab.level, 1.0, 0.5, 5.0, 0.5, 0);
1202 reg.registerFloatVar("cab.bass", N_("Bass"), "S", N_("Bass"), &cab.bass, 0.0, -10.0, 10.0, 0.5, 0);
1203 reg.registerFloatVar("cab.treble", N_("Treble"), "S", N_("Treble"), &cab.treble, 0.0, -10.0, 10.0, 0.5, 0);
1204 cab.impf.register_par(reg);
1205 return 0;
1206 }
1207
1208 //// STEREO /////
1209 #include "faust/cabinet_impulse_former_st.cc"
1210
cab_load_stereo_ui(const UiBuilder & builder,int format)1211 static int cab_load_stereo_ui(const UiBuilder& builder, int format) {
1212 if (format & UI_FORM_GLADE) {
1213 builder.load_glade_file("cabinet_stereo_ui.glade");
1214 return 0;
1215 } else if (format & UI_FORM_STACK) {
1216 builder.openHorizontalhideBox("");
1217 builder.create_selector_no_caption("cab_st.select");
1218 builder.closeBox();
1219 builder.openVerticalBox("");
1220 {
1221 builder.openHorizontalBox("");
1222 {
1223 builder.insertSpacer();
1224 builder.create_selector_no_caption("cab_st.select");
1225 builder.create_small_rackknobr("cab_st.bass", "Bass");
1226 builder.create_small_rackknobr("cab_st.treble", "Treble");
1227 builder.create_mid_rackknob("cab_st.Level", "Level");
1228 }
1229 builder.closeBox();
1230 }
1231 builder.closeBox();
1232 return 0;
1233 } else {
1234 return -1;
1235 }
1236
1237 }
1238
CabinetStereoConvolver(EngineControl & engine,sigc::slot<void> sync,gx_resample::BufferResampler & resamp)1239 CabinetStereoConvolver::CabinetStereoConvolver(EngineControl& engine, sigc::slot<void> sync,
1240 gx_resample::BufferResampler& resamp):
1241 FixedBaseConvolver(engine, sync, resamp),
1242 current_cab(-1),
1243 level(0),
1244 cabinet(0),
1245 bass(0),
1246 treble(0),
1247 sum(no_sum),
1248 cab_names(new value_pair[cab_table_size+1]),
1249 impf(),
1250 smp(),
1251 smps() {
1252 for (unsigned int i = 0; i < cab_table_size; ++i) {
1253 CabEntry& cab = getCabEntry(i);
1254 cab_names[i].value_id = cab.value_id;
1255 cab_names[i].value_label = cab.value_label;
1256 }
1257 cab_names[cab_table_size].value_id = 0;
1258 cab_names[cab_table_size].value_label = 0;
1259 id = "cab_st";
1260 name = N_("Cabinet");
1261 category = N_("Tone Control");
1262 load_ui = cab_load_stereo_ui;
1263 stereo_audio = run_cab_conf;
1264 register_params = register_cab;
1265 }
1266
~CabinetStereoConvolver()1267 CabinetStereoConvolver::~CabinetStereoConvolver() {
1268 delete[] cab_names;
1269 }
1270
do_update()1271 bool CabinetStereoConvolver::do_update() {
1272 bool configure = cabinet_changed();
1273 if (conv.is_runnable()) {
1274 conv.set_not_runnable();
1275 sync();
1276 conv.stop_process();
1277 }
1278 CabDesc& cab = *getCabEntry(cabinet).data;
1279 if (current_cab == -1) {
1280 unsigned int sr = getSamplingFreq();
1281 unsigned int sru = 96000;
1282 unsigned int fact = sru/sr;
1283
1284 smp.setup(sr, fact*sr);
1285 smps.setup(sr, fact*sr);
1286 impf.init(cab.ir_sr);
1287 }
1288 float cab_irdata_c[cab.ir_count];
1289 impf.clear_state_f();
1290 impf.compute(cab.ir_count,cab.ir_data,cab_irdata_c);
1291 while (!conv.checkstate());
1292 if (configure) {
1293 if (!conv.configure_stereo(cab.ir_count, cab_irdata_c, cab.ir_sr)) {
1294 return false;
1295 }
1296 } else {
1297 if (!conv.update_stereo(cab.ir_count, cab_irdata_c, cab.ir_sr)) {
1298 return false;
1299 }
1300 }
1301 update_cabinet();
1302 update_sum();
1303 return conv_start();
1304 }
1305
start(bool force)1306 bool CabinetStereoConvolver::start(bool force) {
1307 if (force) {
1308 current_cab = -1;
1309 }
1310 if (cabinet_changed() || sum_changed()) {
1311 return do_update();
1312 } else {
1313 while (!conv.checkstate());
1314 if (!conv.is_runnable()) {
1315 return conv_start();
1316 }
1317 return true;
1318 }
1319 }
1320
check_update()1321 void CabinetStereoConvolver::check_update() {
1322 if (cabinet_changed() || sum_changed()) {
1323 do_update();
1324 }
1325 }
1326
run_cab_conf(int count,float * input0,float * input1,float * output0,float * output1,PluginDef * p)1327 void CabinetStereoConvolver::run_cab_conf(int count, float *input0, float *input1, float *output0, float *output1, PluginDef *p) {
1328 CabinetStereoConvolver& self = *static_cast<CabinetStereoConvolver*>(p);
1329 FAUSTFLOAT buf[self.smp.max_out_count(count)];
1330 FAUSTFLOAT buf1[self.smps.max_out_count(count)];
1331 int ReCount = self.smp.up(count, output0, buf);
1332 self.smps.up(count, output1, buf1);
1333 if (!self.conv.compute_stereo(ReCount,buf,buf1)) {
1334 self.engine.overload(EngineControl::ov_Convolver, "cab_st");
1335 }
1336 self.smp.down(buf, output0);
1337 self.smps.down(buf1, output1);
1338 }
1339
register_cab(const ParamReg & reg)1340 int CabinetStereoConvolver::register_cab(const ParamReg& reg) {
1341 CabinetStereoConvolver& cab = *static_cast<CabinetStereoConvolver*>(reg.plugin);
1342 reg.registerIntVar("cab_st.select", "select", "B", "", &cab.cabinet, 0, 0, 0, cab.cab_names);
1343 reg.registerFloatVar("cab_st.Level", N_("Level"), "S", N_("Level"), &cab.level, 1.0, 0.5, 5.0, 0.5, 0);
1344 reg.registerFloatVar("cab_st.bass", N_("Bass"), "S", N_("Bass"), &cab.bass, 0.0, -10.0, 10.0, 0.5, 0);
1345 reg.registerFloatVar("cab_st.treble", N_("Treble"), "S", N_("Treble"), &cab.treble, 0.0, -10.0, 10.0, 0.5, 0);
1346 cab.impf.register_par(reg);
1347 return 0;
1348 }
1349
1350 /****************************************************************
1351 ** class PreampConvolver
1352 */
1353
1354 struct PreDesc {
1355 int ir_count;
1356 int ir_sr;
1357 float ir_data[];
1358 };
1359
1360 template <int tab_size>
1361 struct PreDesc_imp {
1362 int ir_count;
1363 int ir_sr;
1364 float ir_data[tab_size];
operator PreDesc&gx_engine::PreDesc_imp1365 operator PreDesc&() { return *(PreDesc*)this; }
1366 };
1367
1368 #include "gx_preamp_data.cc"
1369
1370 struct PreEntry {
1371 const char *value_id;
1372 const char *value_label;
1373 PreDesc *data;
1374 } pre_table[] = {
1375 { "AC30", N_("AC30 Style"), &static_cast<PreDesc&>(pre_data_ac30) },
1376 { "Bassman", N_("Bassman Style"), &static_cast<PreDesc&>(pre_data_bassman) },
1377 { "Tube", N_("Tube Style"), &static_cast<PreDesc&>(pre_data_tube) },
1378 { "Fender", N_("Fender Style"), &static_cast<PreDesc&>(pre_data_fender) },
1379 { "JCM800", N_("JCM800 Style"), &static_cast<PreDesc&>(pre_data_jcm800) },
1380 { "JTM45", N_("JTM45 Style"), &static_cast<PreDesc&>(pre_data_jtm45) },
1381 { "Mesa Boogie", N_("Mesa Boogie Style"), &static_cast<PreDesc&>(pre_data_mesaboogie) },
1382 { "Boutique", N_("Boutique Style"), &static_cast<PreDesc&>(pre_data_boutique) },
1383 { "Ampeg", N_("Ampeg Style"), &static_cast<PreDesc&>(pre_data_ampeg) },
1384 { "Rectifier", N_("Rectifier Style"), &static_cast<PreDesc&>(pre_data_rectifier) },
1385 };
1386 static const unsigned int pre_table_size = sizeof(pre_table) / sizeof(pre_table[0]);
1387
getPreEntry(unsigned int n)1388 static PreEntry& getPreEntry(unsigned int n) {
1389 if (n >= pre_table_size) {
1390 n = pre_table_size - 1;
1391 }
1392 return pre_table[n];
1393 }
1394
1395 #include "faust/preamp_impulse_former.cc"
1396
pre_load_ui(const UiBuilder & builder,int format)1397 static int pre_load_ui(const UiBuilder& builder, int format) {
1398 if (format & UI_FORM_GLADE) {
1399 builder.load_glade_file("ampimpulse_ui.glade");
1400 return 0;
1401 } else if (format & UI_FORM_STACK) {
1402 builder.openHorizontalhideBox("");
1403 builder.create_selector_no_caption("pre.select");
1404 builder.closeBox();
1405 builder.openVerticalBox("");
1406 {
1407 builder.openHorizontalBox("");
1408 {
1409 builder.insertSpacer();
1410 builder.create_selector_no_caption("pre.select");
1411 builder.create_small_rackknobr("pre.bass", "Bass");
1412 builder.create_small_rackknobr("pre.treble", "Treble");
1413 builder.create_mid_rackknob("pre.Level", "Level");
1414 }
1415 builder.closeBox();
1416 }
1417 builder.closeBox();
1418 return 0;
1419 } else {
1420 return -1;
1421 }
1422
1423 }
1424
PreampConvolver(EngineControl & engine,sigc::slot<void> sync,gx_resample::BufferResampler & resamp)1425 PreampConvolver::PreampConvolver(EngineControl& engine, sigc::slot<void> sync,
1426 gx_resample::BufferResampler& resamp):
1427 FixedBaseConvolver(engine, sync, resamp),
1428 current_pre(-1),
1429 level(0),
1430 preamp(0),
1431 bass(0),
1432 treble(0),
1433 sum(no_sum),
1434 pre_names(new value_pair[pre_table_size+1]),
1435 impf(),
1436 smp() {
1437 for (unsigned int i = 0; i < pre_table_size; ++i) {
1438 PreEntry& pre = getPreEntry(i);
1439 pre_names[i].value_id = pre.value_id;
1440 pre_names[i].value_label = pre.value_label;
1441 }
1442 pre_names[pre_table_size].value_id = 0;
1443 pre_names[pre_table_size].value_label = 0;
1444 id = "pre";
1445 name = N_("Amp Impulse");
1446 category = N_("Tone Control");
1447 load_ui = pre_load_ui;
1448 mono_audio = run_pre_conf;
1449 register_params = register_pre;
1450 }
1451
~PreampConvolver()1452 PreampConvolver::~PreampConvolver() {
1453 delete[] pre_names;
1454 }
1455
do_update()1456 bool PreampConvolver::do_update() {
1457 bool configure = preamp_changed();
1458 if (conv.is_runnable()) {
1459 conv.set_not_runnable();
1460 sync();
1461 conv.stop_process();
1462 }
1463 PreDesc& pre = *getPreEntry(preamp).data;
1464 if (current_pre == -1) {
1465 unsigned int sr = getSamplingFreq();
1466 unsigned int sru = 96000;
1467 unsigned int fact = sru/sr;
1468
1469 smp.setup(sr, fact*sr);
1470 impf.init(pre.ir_sr);
1471 }
1472 float pre_irdata_c[pre.ir_count];
1473 impf.clear_state_f();
1474 impf.compute(pre.ir_count,pre.ir_data,pre_irdata_c);
1475 while (!conv.checkstate());
1476 if (configure) {
1477 if (!conv.configure(pre.ir_count, pre_irdata_c, pre.ir_sr)) {
1478 return false;
1479 }
1480 } else {
1481 if (!conv.update(pre.ir_count, pre_irdata_c, pre.ir_sr)) {
1482 return false;
1483 }
1484 }
1485 update_preamp();
1486 update_sum();
1487 return conv_start();
1488 }
1489
start(bool force)1490 bool PreampConvolver::start(bool force) {
1491 if (force) {
1492 current_pre = -1;
1493 }
1494 if (preamp_changed() || sum_changed()) {
1495 return do_update();
1496 } else {
1497 while (!conv.checkstate());
1498 if (!conv.is_runnable()) {
1499 return conv_start();
1500 }
1501 return true;
1502 }
1503 }
1504
check_update()1505 void PreampConvolver::check_update() {
1506 if (preamp_changed() || sum_changed()) {
1507 do_update();
1508 }
1509 }
1510
run_pre_conf(int count,float * input0,float * output0,PluginDef * p)1511 void PreampConvolver::run_pre_conf(int count, float *input0, float *output0, PluginDef *p) {
1512 PreampConvolver& self = *static_cast<PreampConvolver*>(p);
1513 FAUSTFLOAT buf[self.smp.max_out_count(count)];
1514 int ReCount = self.smp.up(count, output0, buf);
1515 if (!self.conv.compute(ReCount, buf)) {
1516 self.engine.overload(EngineControl::ov_Convolver, "pre");
1517 }
1518 self.smp.down(buf, output0);
1519 }
1520
register_pre(const ParamReg & reg)1521 int PreampConvolver::register_pre(const ParamReg& reg) {
1522 PreampConvolver& pre = *static_cast<PreampConvolver*>(reg.plugin);
1523 reg.registerIntVar("pre.select", "select", "B", "", &pre.preamp, 0, 0, 0, pre.pre_names);
1524 reg.registerFloatVar("pre.Level", N_("Level"), "S", N_("Level"), &pre.level, 1.0, 0.1, 2.1, 0.1, 0);
1525 reg.registerFloatVar("pre.bass", N_("Bass"), "S", N_("Bass"), &pre.bass, 0.0, -10.0, 10.0, 0.5, 0);
1526 reg.registerFloatVar("pre.treble", N_("Treble"), "S", N_("Treble"), &pre.treble, 0.0, -10.0, 10.0, 0.5, 0);
1527 pre.impf.register_par(reg);
1528 return 0;
1529 }
1530
1531 //// STEREO /////
1532 #include "faust/preamp_impulse_former_st.cc"
1533
pre_load_stereo_ui(const UiBuilder & builder,int format)1534 static int pre_load_stereo_ui(const UiBuilder& builder, int format) {
1535 if (format & UI_FORM_GLADE) {
1536 builder.load_glade_file("ampimpulse_st_ui.glade");
1537 return 0;
1538 } else if (format & UI_FORM_STACK) {
1539 builder.openHorizontalhideBox("");
1540 builder.create_selector_no_caption("pre_st.select");
1541 builder.closeBox();
1542 builder.openVerticalBox("");
1543 {
1544 builder.openHorizontalBox("");
1545 {
1546 builder.insertSpacer();
1547 builder.create_selector_no_caption("pre_st.select");
1548 builder.create_small_rackknobr("pre_st.bass", "Bass");
1549 builder.create_small_rackknobr("pre_st.treble", "Treble");
1550 builder.create_mid_rackknob("pre_st.Level", "Level");
1551 }
1552 builder.closeBox();
1553 }
1554 builder.closeBox();
1555 return 0;
1556 } else {
1557 return -1;
1558 }
1559
1560 }
1561
PreampStereoConvolver(EngineControl & engine,sigc::slot<void> sync,gx_resample::BufferResampler & resamp)1562 PreampStereoConvolver::PreampStereoConvolver(EngineControl& engine, sigc::slot<void> sync,
1563 gx_resample::BufferResampler& resamp):
1564 FixedBaseConvolver(engine, sync, resamp),
1565 current_pre(-1),
1566 level(0),
1567 preamp(0),
1568 bass(0),
1569 treble(0),
1570 sum(no_sum),
1571 pre_names(new value_pair[pre_table_size+1]),
1572 impf(),
1573 smp(),
1574 smps() {
1575 for (unsigned int i = 0; i < pre_table_size; ++i) {
1576 PreEntry& pre = getPreEntry(i);
1577 pre_names[i].value_id = pre.value_id;
1578 pre_names[i].value_label = pre.value_label;
1579 }
1580 pre_names[pre_table_size].value_id = 0;
1581 pre_names[pre_table_size].value_label = 0;
1582 id = "pre_st";
1583 name = N_("Amp Impulse");
1584 category = N_("Tone Control");
1585 load_ui = pre_load_stereo_ui;
1586 stereo_audio = run_pre_conf;
1587 register_params = register_pre;
1588 }
1589
~PreampStereoConvolver()1590 PreampStereoConvolver::~PreampStereoConvolver() {
1591 delete[] pre_names;
1592 }
1593
do_update()1594 bool PreampStereoConvolver::do_update() {
1595 bool configure = preamp_changed();
1596 if (conv.is_runnable()) {
1597 conv.set_not_runnable();
1598 sync();
1599 conv.stop_process();
1600 }
1601 PreDesc& pre = *getPreEntry(preamp).data;
1602 if (current_pre == -1) {
1603 unsigned int sr = getSamplingFreq();
1604 unsigned int sru = 96000;
1605 unsigned int fact = sru/sr;
1606
1607 smp.setup(sr, fact*sr);
1608 smps.setup(sr, fact*sr);
1609 impf.init(pre.ir_sr);
1610 }
1611 float pre_irdata_c[pre.ir_count];
1612 impf.clear_state_f();
1613 impf.compute(pre.ir_count,pre.ir_data,pre_irdata_c);
1614 while (!conv.checkstate());
1615 if (configure) {
1616 if (!conv.configure_stereo(pre.ir_count, pre_irdata_c, pre.ir_sr)) {
1617 return false;
1618 }
1619 } else {
1620 if (!conv.update_stereo(pre.ir_count, pre_irdata_c, pre.ir_sr)) {
1621 return false;
1622 }
1623 }
1624 update_preamp();
1625 update_sum();
1626 return conv_start();
1627 }
1628
start(bool force)1629 bool PreampStereoConvolver::start(bool force) {
1630 if (force) {
1631 current_pre = -1;
1632 }
1633 if (preamp_changed() || sum_changed()) {
1634 return do_update();
1635 } else {
1636 while (!conv.checkstate());
1637 if (!conv.is_runnable()) {
1638 return conv_start();
1639 }
1640 return true;
1641 }
1642 }
1643
check_update()1644 void PreampStereoConvolver::check_update() {
1645 if (preamp_changed() || sum_changed()) {
1646 do_update();
1647 }
1648 }
1649
run_pre_conf(int count,float * input0,float * input1,float * output0,float * output1,PluginDef * p)1650 void PreampStereoConvolver::run_pre_conf(int count, float *input0, float *input1, float *output0, float *output1, PluginDef *p) {
1651 PreampStereoConvolver& self = *static_cast<PreampStereoConvolver*>(p);
1652 FAUSTFLOAT buf[self.smp.max_out_count(count)];
1653 FAUSTFLOAT buf1[self.smps.max_out_count(count)];
1654 int ReCount = self.smp.up(count, output0, buf);
1655 self.smps.up(count, output1, buf1);
1656 if (!self.conv.compute_stereo(ReCount,buf,buf1)) {
1657 self.engine.overload(EngineControl::ov_Convolver, "pre_st");
1658 }
1659 self.smp.down(buf, output0);
1660 self.smps.down(buf1, output1);
1661 }
1662
register_pre(const ParamReg & reg)1663 int PreampStereoConvolver::register_pre(const ParamReg& reg) {
1664 PreampStereoConvolver& pre = *static_cast<PreampStereoConvolver*>(reg.plugin);
1665 reg.registerIntVar("pre_st.select", "select", "B", "", &pre.preamp, 0, 0, 0, pre.pre_names);
1666 reg.registerFloatVar("pre_st.Level", N_("Level"), "SA", N_("Level"), &pre.level, 1.0, 0.1, 2.1, 0.1, 0);
1667 reg.registerFloatVar("pre_st.bass", N_("Bass"), "SA", N_("Bass"), &pre.bass, 0.0, -10.0, 10.0, 0.5, 0);
1668 reg.registerFloatVar("pre_st.treble", N_("Treble"), "SA", N_("Treble"), &pre.treble, 0.0, -10.0, 10.0, 0.5, 0);
1669 pre.impf.register_par(reg);
1670 return 0;
1671 }
1672
1673 /****************************************************************
1674 ** class ContrastConvolver
1675 */
1676
1677 #include "faust/presence_level.cc"
1678
ContrastConvolver(EngineControl & engine,sigc::slot<void> sync,gx_resample::BufferResampler & resamp)1679 ContrastConvolver::ContrastConvolver(EngineControl& engine, sigc::slot<void> sync,
1680 gx_resample::BufferResampler& resamp)
1681 : FixedBaseConvolver(engine, sync, resamp),
1682 level(0),
1683 sum(no_sum),
1684 presl(),
1685 smp() {
1686 id = "con";
1687 name = N_("Contrast convolver");
1688 mono_audio = run_contrast;
1689 register_params = register_con;
1690 }
1691
~ContrastConvolver()1692 ContrastConvolver::~ContrastConvolver() {
1693 }
1694
do_update()1695 bool ContrastConvolver::do_update() {
1696 bool configure = (sum == no_sum);
1697 if (conv.is_runnable()) {
1698 conv.set_not_runnable();
1699 sync();
1700 conv.stop_process();
1701 }
1702 if (configure) {
1703 unsigned int sr = getSamplingFreq();
1704 unsigned int sru = 96000;
1705 unsigned int fact = sru/sr;
1706
1707 smp.setup(sr, fact*sr);
1708 presl.init(contrast_ir_desc.ir_sr);
1709 }
1710 float contrast_irdata_c[contrast_ir_desc.ir_count];
1711 presl.compute(contrast_ir_desc.ir_count,contrast_ir_desc.ir_data,contrast_irdata_c);
1712 while (!conv.checkstate());
1713 if (configure) {
1714 if (!conv.configure(contrast_ir_desc.ir_count, contrast_irdata_c, contrast_ir_desc.ir_sr)) {
1715 return false;
1716 }
1717 } else {
1718 if (!conv.update(contrast_ir_desc.ir_count, contrast_irdata_c, contrast_ir_desc.ir_sr)) {
1719 return false;
1720 }
1721 }
1722 update_sum();
1723 return conv_start();
1724 }
1725
start(bool force)1726 bool ContrastConvolver::start(bool force) {
1727 if (force) {
1728 sum = no_sum;
1729 }
1730 if (sum_changed()) {
1731 return do_update();
1732 } else {
1733 while (!conv.checkstate());
1734 if (!conv.is_runnable()) {
1735 return conv_start();
1736 }
1737 return true;
1738 }
1739 }
1740
check_update()1741 void ContrastConvolver::check_update() {
1742 if (sum_changed()) {
1743 do_update();
1744 }
1745 }
1746
register_con(const ParamReg & reg)1747 int ContrastConvolver::register_con(const ParamReg& reg) {
1748 ContrastConvolver& self = *static_cast<ContrastConvolver*>(reg.plugin);
1749 reg.registerFloatVar("con.Level", "", "S", "", &self.level, 1.0, 0.5, 5.0, 0.5, 0);
1750 self.presl.register_par(reg);
1751 return 0;
1752 }
1753
run_contrast(int count,float * input0,float * output0,PluginDef * p)1754 void ContrastConvolver::run_contrast(int count, float *input0, float *output0, PluginDef *p) {
1755 ContrastConvolver& self = *static_cast<ContrastConvolver*>(p);
1756 FAUSTFLOAT buf[self.smp.max_out_count(count)];
1757 int ReCount = self.smp.up(count, output0, buf);
1758 if (!self.conv.compute(ReCount,buf)) {
1759 self.engine.overload(EngineControl::ov_Convolver, "contrast");
1760 }
1761 self.smp.down(buf, output0);
1762 }
1763
1764 /****************************************************************
1765 ** class Directout
1766 */
1767 Plugin Directout::directoutput = Plugin();
1768
Directout(EngineControl & engine_,sigc::slot<void> sync_)1769 Directout::Directout(EngineControl& engine_, sigc::slot<void> sync_)
1770 : PluginDef(),
1771 outdata(0),
1772 engine(engine_),
1773 sync(sync_),
1774 mem_allocated(false),
1775 plugin() {
1776 directoutput.set_pdef(this);
1777 version = PLUGINDEF_VERSION;
1778 flags = 0;
1779 id = "dout";
1780 name = N_("Directoutputr");
1781 stereo_audio = compute_static;
1782 set_samplerate = init_static;
1783 activate_plugin = 0;
1784 plugin = this;
1785 engine.signal_buffersize_change().connect(
1786 sigc::mem_fun(*this, &Directout::change_buffersize));
1787 }
1788
~Directout()1789 Directout::~Directout() {
1790 mem_free();
1791 }
1792
init(unsigned int samplingFreq)1793 inline void Directout::init(unsigned int samplingFreq)
1794 {
1795 bsize = int(engine.get_buffersize());
1796 fSamplingFreq = samplingFreq;
1797 mem_alloc();
1798 }
1799
init_static(unsigned int samplingFreq,PluginDef * p)1800 void Directout::init_static(unsigned int samplingFreq, PluginDef *p)
1801 {
1802 static_cast<Directout*>(p)->init(samplingFreq);
1803 }
1804
mem_alloc()1805 void Directout::mem_alloc()
1806 {
1807 if (mem_allocated) {
1808 return;
1809 }
1810 bsize = int(engine.get_buffersize());
1811 assert(bsize>0);
1812 try {
1813 outdata = new float[bsize]();
1814 } catch(...) {
1815 gx_print_error("Directout", "cant allocate memory pool");
1816 return;
1817 }
1818 mem_allocated = true;
1819 }
1820
mem_free()1821 void Directout::mem_free()
1822 {
1823 mem_allocated = false;
1824 if (outdata) {
1825 delete[] outdata;
1826 outdata = 0;
1827 }
1828 }
1829
change_buffersize(unsigned int size)1830 void Directout::change_buffersize(unsigned int size)
1831 {
1832 sync();
1833 if (mem_allocated) {
1834 mem_free();
1835 mem_alloc();
1836 }
1837 }
1838
compute(int count,float * input0,float * input1,float * output0,float * output1)1839 void always_inline Directout::compute(int count, float *input0, float *input1, float *output0, float *output1) {
1840 if (!fdfill) {
1841 return;
1842 }
1843 for (int i=0; i<count; i++) {
1844 output0[i] = input0[i] + outdata[i];
1845 output1[i] = input1[i] + outdata[i];
1846 }
1847 memset(outdata,0,count*sizeof(float));
1848 fdfill = false;
1849 }
1850
set_data(bool dfill)1851 void Directout::set_data(bool dfill) {
1852 fdfill = dfill;
1853 }
1854
compute_static(int count,FAUSTFLOAT * input0,FAUSTFLOAT * input1,FAUSTFLOAT * output0,FAUSTFLOAT * output1,PluginDef * p)1855 void __rt_func Directout::compute_static(int count, FAUSTFLOAT *input0, FAUSTFLOAT *input1, FAUSTFLOAT *output0, FAUSTFLOAT *output1, PluginDef *p)
1856 {
1857 static_cast<Directout*>(p)->compute(count, input0, input1, output0, output1);
1858 }
1859
1860
1861 /****************************************************************
1862 ** class LiveLooper
1863 */
1864
1865 #include "gx_livelooper.cc"
1866
1867 /****************************************************************
1868 ** class SCapture
1869 */
1870
1871 #include "gx_record.cc"
1872
1873 /****************************************************************
1874 ** class DrumSequencer
1875 */
1876
1877 #include "faust/drumseq.cc"
1878
1879
1880 float* Drumout::set = 0;
1881 float* Drumout::data = 0;
1882 bool Drumout::mb = false;
1883 Plugin Drumout::output_drum = Plugin();
1884 Plugin Drumout::input_drum = Plugin();
1885 PluginDef Drumout::outputdrum = PluginDef();
1886
Drumout()1887 Drumout::Drumout() {
1888
1889 output_drum.set_pdef(&outputdrum);
1890
1891 outputdrum.version = PLUGINDEF_VERSION;
1892 outputdrum.id = "drumout";
1893 outputdrum.name = "?drumout";
1894 outputdrum.stereo_audio = outputdrum_compute;
1895 }
1896
outputdrum_compute(int count,float * input0,float * input1,float * output0,float * output1,PluginDef *)1897 void always_inline Drumout::outputdrum_compute(int count, float *input0, float *input1, float *output0, float *output1, PluginDef*) {
1898 if (!(*set) || !input_drum.get_on_off() || !mb) {
1899 return;
1900 }
1901 for (int i=0; i<count; i++) {
1902 output0[i] = input0[i] + data[i];
1903 output1[i] = input1[i] + data[i];
1904 }
1905 memset(data,0,count*sizeof(float));
1906 }
1907
set_data(float * mode,bool ready,float * buf)1908 void Drumout::set_data(float* mode, bool ready, float* buf) {
1909 set = mode;
1910 mb = ready;
1911 data = buf;
1912 }
1913
set_plugin(Plugin p)1914 void Drumout::set_plugin(Plugin p) {
1915 input_drum = p;
1916 }
1917
1918 static const char* seq_groups[] = {
1919 "hat_closed.dsp", N_("DrumSequencer"),
1920 "kick.dsp", N_("DrumSequencer"),
1921 "snare.dsp", N_("DrumSequencer"),
1922 "tom.dsp", N_("DrumSequencer"),
1923 "sequencer", N_("DrumSequencer"),
1924 0
1925 };
1926
DrumSequencer(EngineControl & engine_,sigc::slot<void> sync_)1927 DrumSequencer::DrumSequencer(EngineControl& engine_, sigc::slot<void> sync_)
1928 : PluginDef(),
1929 Vectom(0),
1930 Vectom1(0),
1931 Vectom2(0),
1932 Veckick(0),
1933 Vecsnare(0),
1934 Vechat(0),
1935 engine(engine_),
1936 mem_allocated(false),
1937 sync(sync_),
1938 ready(false),
1939 outdata(0),
1940 tomset(),
1941 tomp(0),
1942 tomset1(),
1943 tomp1(0),
1944 tomset2(),
1945 tomp2(0),
1946 snareset(),
1947 snarep(0),
1948 hatset(),
1949 hatp(0),
1950 kickset(),
1951 kickp(0),
1952 plugin() {
1953 version = PLUGINDEF_VERSION;
1954 flags = 0;
1955 id = "seq";
1956 name = N_("DrumSequencer");
1957 groups = seq_groups;
1958 description = N_("Simple Drum Step Sequencer"); // description (tooltip)
1959 category = N_("Misc"); // category
1960 shortname = N_("Drum"); // shortname
1961 mono_audio = compute_static;
1962 stereo_audio = 0;
1963 set_samplerate = init_static;
1964 activate_plugin = 0;
1965 load_ui = drum_load_ui;
1966 register_params = register_params_static;
1967 delete_instance = del_instance;
1968 plugin = this;
1969 engine.signal_buffersize_change().connect(
1970 sigc::mem_fun(*this, &DrumSequencer::change_buffersize));
1971 }
1972
~DrumSequencer()1973 DrumSequencer::~DrumSequencer() {
1974 mem_free();
1975 }
1976
init(unsigned int samplingFreq)1977 inline void DrumSequencer::init(unsigned int samplingFreq)
1978 {
1979 bsize = int(engine.get_buffersize());
1980 fSamplingFreq = samplingFreq;
1981 counter = 0;
1982 step = 0;
1983 step_orig = 0;
1984 fSlow1 = 0.0;
1985 fSlow3 = 0.0;
1986 fSlow5 = 0.0;
1987 fSlow7 = 0.0;
1988 fSlow18 = 150.0;
1989 position = 0.0;
1990 mem_alloc();
1991 drums.init(samplingFreq);
1992 Drumout::set_plugin(plugin);
1993 }
1994
init_static(unsigned int samplingFreq,PluginDef * p)1995 void DrumSequencer::init_static(unsigned int samplingFreq, PluginDef *p)
1996 {
1997 static_cast<DrumSequencer*>(p)->init(samplingFreq);
1998 }
1999
mem_alloc()2000 void DrumSequencer::mem_alloc()
2001 {
2002 if (mem_allocated) {
2003 return;
2004 }
2005 bsize = int(engine.get_buffersize());
2006 assert(bsize>0);
2007 try {
2008 outdata = new float[bsize]();
2009 } catch(...) {
2010 gx_print_error("DrumSequencer", "cant allocate memory pool");
2011 return;
2012 }
2013 mem_allocated = true;
2014 Drumout::set_data(&fSlow22, mem_allocated, outdata);
2015 }
2016
mem_free()2017 void DrumSequencer::mem_free()
2018 {
2019 ready = false;
2020 mem_allocated = false;
2021 Drumout::set_data(0, mem_allocated, 0);
2022 if (outdata) {
2023 delete[] outdata;
2024 outdata = 0;
2025 }
2026 }
2027
change_buffersize(unsigned int size)2028 void DrumSequencer::change_buffersize(unsigned int size)
2029 {
2030 sync();
2031 ready = false;
2032 if (mem_allocated) {
2033 mem_free();
2034 mem_alloc();
2035 }
2036 }
2037
min_seq_size()2038 int DrumSequencer::min_seq_size(){
2039 int i = min(min(min(Vectom.size(),Veckick.size()),min(Vechat.size(),Vecsnare.size())),min(Vectom1.size(),Vectom2.size()));
2040 return i-1;
2041 }
2042
reset_tom()2043 void DrumSequencer::reset_tom() {
2044 Vectom = tomset.getseqline() ;
2045 seq_size = min_seq_size();
2046 }
2047
reset_tom1()2048 void DrumSequencer::reset_tom1() {
2049 Vectom1 = tomset1.getseqline() ;
2050 seq_size = min_seq_size();
2051 }
2052
reset_tom2()2053 void DrumSequencer::reset_tom2() {
2054 Vectom2 = tomset2.getseqline() ;
2055 seq_size = min_seq_size();
2056 }
2057
reset_kick()2058 void DrumSequencer::reset_kick() {
2059 Veckick = kickset.getseqline() ;
2060 seq_size = min_seq_size();
2061 }
2062
reset_hat()2063 void DrumSequencer::reset_hat() {
2064 Vechat = hatset.getseqline() ;
2065 seq_size = min_seq_size();
2066 }
2067
reset_snare()2068 void DrumSequencer::reset_snare() {
2069 Vecsnare = snareset.getseqline() ;
2070 seq_size = min_seq_size();
2071 }
2072
2073 // hat = 1600Hz
2074 // kick = 50Hz
2075 // toms = 90 - 128 - 150Hz
2076 // snare = 523 - 7040Hz
2077 // todo: add compressor
2078
compute(int count,FAUSTFLOAT * input0,FAUSTFLOAT * output0)2079 void always_inline DrumSequencer::compute(int count, FAUSTFLOAT *input0, FAUSTFLOAT *output0)
2080 {
2081 double fSlow15 = (60.0/double(fsliderbpm*ftact))*fSamplingFreq;
2082 counter += count;
2083 int iSlow15 = (int)fSlow15;
2084 // beat
2085 if (counter >= iSlow15) {
2086 int istep = (int)step;
2087 fSlow1 = double(Vecsnare[istep]);
2088 // disable hat when sequencer runs to fast
2089 if (iSlow15 > 4800) {
2090 fSlow3 = double(Vechat[istep]);
2091 }
2092 fSlow5 = double(Veckick[istep]);
2093 // only one tom at time
2094 if (Vectom2[istep]) {
2095 fSlow7 = double(Vectom2[istep]);
2096 fSlow18 = 150.0;
2097 fSlow20 = fSlow16;
2098 } else if (Vectom1[istep]) {
2099 fSlow7 = double(Vectom1[istep]);
2100 fSlow18 = 128.0;
2101 fSlow20 = fSlow14;
2102 } else if(Vectom[istep]) {
2103 fSlow7 = double(Vectom[istep]);
2104 fSlow18 = 90.0;
2105 fSlow20 = fSlow12;
2106 }
2107 int m = ftact;
2108 int r = rand()%(m+1 - (-m))+ (-m);
2109 counter -= iSlow15; //int(r*fsliderhum);
2110
2111 if (step<seq_size) step = fmin(seq_size,fmax(0,step + 1.0 + int(r*fsliderhum)));
2112 else step = 0.0;
2113 if (step_orig<seq_size) step_orig += 1.0;
2114 else step_orig = 0.0;
2115 double ph1 = 2300.0/seq_size;
2116 position = fmin(2300,fmax(0,(step*ph1)));
2117 } else {
2118 fSlow1 = 0.0;
2119 fSlow3 = 0.0;
2120 fSlow5 = 0.0;
2121 fSlow7 = 0.0;
2122 }
2123 if (int(fSlow22 && mem_allocated)) {
2124 memcpy(output0, input0, count * sizeof(float));
2125 drums.compute(count,outdata,outdata);
2126 } else {
2127 drums.compute(count,input0,output0);
2128 }
2129 }
2130
compute_static(int count,FAUSTFLOAT * input0,FAUSTFLOAT * output0,PluginDef * p)2131 void __rt_func DrumSequencer::compute_static(int count, FAUSTFLOAT *input0, FAUSTFLOAT *output0, PluginDef *p)
2132 {
2133 static_cast<DrumSequencer*>(p)->compute(count, input0, output0);
2134 }
2135
register_par(const ParamReg & reg)2136 int DrumSequencer::register_par(const ParamReg& reg)
2137 {
2138 reg.registerFloatVar("seq.hat_closed.dsp.gate","","BA","",&fSlow3, 0.0, 0.0, 1.0, 1.0, 0);
2139 reg.registerFloatVar("seq.kick.dsp.gate","","BA","",&fSlow5, 0.0, 0.0, 1.0, 1.0, 0);
2140 reg.registerFloatVar("seq.snare.dsp.gate","","BA","",&fSlow1, 0.0, 0.0, 1.0, 1.0, 0);
2141 reg.registerFloatVar("seq.tom.dsp.gate","","BA","",&fSlow7, 0.0, 0.0, 1.0, 1.0, 0);
2142 reg.registerFloatVar("seq.tom.dsp.Gainf","","SA","",&fSlow20, -2e+01, -6e+01, 4e+01, 0.1, 0);
2143 reg.registerFloatVar("seq.tom.dsp.Gain","","S",N_("Volume level in decibels"),&fSlow12, -2e+01, -6e+01, 4e+01, 0.1, 0);
2144 reg.registerFloatVar("seq.tom.dsp.Gain1","","S",N_("Volume level in decibels"),&fSlow14, -2e+01, -6e+01, 4e+01, 0.1, 0);
2145 reg.registerFloatVar("seq.tom.dsp.Gain2","","S",N_("Volume level in decibels"),&fSlow16, -2e+01, -6e+01, 4e+01, 0.1, 0);
2146 reg.registerFloatVar("seq.tom.dsp.freq","","SA","",&fSlow18, 9e+01, 9e+01, 1.5e+02, 1.0, 0);
2147 reg.registerFloatVar("seq.bpm","","S",N_("Beats per Minute"),&fsliderbpm, 120, 24, 360, 1, 0);
2148 static const value_pair ftact_values[] = {{"1/4"},{"2/4"},{"3/4"},{"4/4"},{0}};
2149 reg.registerFloatVar("seq.tact","","S",N_("select tact"),&ftact, 4.0, 1.0, 4.0, 1.0, ftact_values);
2150 reg.registerFloatVar("seq.asequences","","S",N_("Number of Sequences"),&fsec, 24.0, 24.0, 240.0, 4.0, 0);
2151 reg.registerFloatVar("seq.hum","","B",N_("Randomize Sequence"),&fsliderhum, 0.0, 0.0, 1.0, 1.0, 0);
2152 reg.registerFloatVar("seq.npreset","","BO",N_("Load next unit preset"),0, 0.0, 0.0, 1.0, 1.0, 0);
2153 reg.registerFloatVar("seq.ppreset","","BO",N_("Load previous unit preset"),0, 0.0, 0.0, 1.0, 1.0, 0);
2154 reg.registerFloatVar("seq.pos","","SN","",&position, 0.0, 0.0, 2300.0, 1.0, 0);
2155 reg.registerFloatVar("seq.step","","SN","",&step, 0.0, 0.0, 240.0, 1.0, 0);
2156 reg.registerFloatVar("seq.step_orig","","SN","",&step_orig, 0.0, 0.0, 240.0, 1.0, 0);
2157 reg.registerFloatVar("seq.set_step","","BO",N_("Set stepper one Beat back"),0, 0.0, 0.0, 1.0, 1.0, 0);
2158 reg.registerFloatVar("seq.set_fstep","","BO",N_("Set stepper one Beat forward"),0, 0.0, 0.0, 1.0, 1.0, 0);
2159 reg.registerFloatVar("seq.set_sync","","BO",N_("Set stepper back on Beat "),0, 0.0, 0.0, 1.0, 1.0, 0);
2160 reg.registerFloatVar("seq.reset_step","","BO",N_("Set stepper one Start"),0, 0.0, 0.0, 1.0, 1.0, 0);
2161 reg.registerFloatVar("seq.follow","","BA",N_("follow playhead"),0, 0.0, 0.0, 1.0, 1.0, 0);
2162 reg.registerFloatVar("seq.direct_out","","BA",N_("bypass the rack for direct output"),&fSlow22, 0.0, 0.0, 1.0, 1.0, 0);
2163 for (int i=0; i<24; i++) Vectom.push_back(0);
2164 for (int i=0; i<24; i++) Vectom1.push_back(0);
2165 for (int i=0; i<24; i++) Vectom2.push_back(0);
2166 for (int i=0; i<24; i++) Veckick.push_back(0);
2167 for (int i=0; i<24; i++) Vechat.push_back(0);
2168 for (int i=0; i<24; i++) Vecsnare.push_back(0);
2169 seq_size = min_seq_size();
2170 ParamMap& param = engine.get_param();
2171 tomp = SeqParameter::insert_param(param, "seq.sequencer.tom", &tomset);
2172 tomp1 = SeqParameter::insert_param(param, "seq.sequencer.tom1", &tomset1);
2173 tomp2 = SeqParameter::insert_param(param, "seq.sequencer.tom2", &tomset2);
2174 snarep = SeqParameter::insert_param(param, "seq.sequencer.snare", &snareset);
2175 hatp = SeqParameter::insert_param(param, "seq.sequencer.hat", &hatset);
2176 kickp = SeqParameter::insert_param(param, "seq.sequencer.kick", &kickset);
2177 tomp->signal_changed().connect(
2178 sigc::hide(
2179 sigc::mem_fun(this, &DrumSequencer::reset_tom)));
2180 tomp1->signal_changed().connect(
2181 sigc::hide(
2182 sigc::mem_fun(this, &DrumSequencer::reset_tom1)));
2183 tomp2->signal_changed().connect(
2184 sigc::hide(
2185 sigc::mem_fun(this, &DrumSequencer::reset_tom2)));
2186 snarep->signal_changed().connect(
2187 sigc::hide(
2188 sigc::mem_fun(this, &DrumSequencer::reset_snare)));
2189 hatp->signal_changed().connect(
2190 sigc::hide(
2191 sigc::mem_fun(this, &DrumSequencer::reset_hat)));
2192 kickp->signal_changed().connect(
2193 sigc::hide(
2194 sigc::mem_fun(this, &DrumSequencer::reset_kick)));
2195
2196 drums.register_par(reg);
2197 return 0;
2198 }
2199
register_params_static(const ParamReg & reg)2200 int DrumSequencer::register_params_static(const ParamReg& reg)
2201 {
2202 return static_cast<DrumSequencer*>(reg.plugin)->register_par(reg);
2203 }
2204
del_instance(PluginDef * p)2205 void DrumSequencer::del_instance(PluginDef *p)
2206 {
2207 delete static_cast<DrumSequencer*>(p);
2208 }
2209
2210 //static
drum_load_ui(const UiBuilder & builder,int format)2211 int DrumSequencer::drum_load_ui(const UiBuilder& builder, int format) {
2212 if (format & UI_FORM_GLADE) {
2213 builder.load_glade_file("drumsequencer_ui.glade");
2214 return 0;
2215 } else if (format & UI_FORM_STACK) {
2216 //static gx_seq::SEQWindow *seqw = gx_seq::SEQWindow::create("seq", machine);
2217 builder.openHorizontalhideBox("");
2218 builder.create_master_slider("seq.gain", _("Gain"));
2219 builder.insertSpacer();
2220 builder.insertSpacer();
2221 //builder.addSmallSeqButton(C_("Setup", "S"), seqw);
2222 builder.closeBox();
2223 builder.openVerticalBox("");
2224 {
2225 builder.openFrameBox("");
2226 builder.closeBox();
2227 builder.openHorizontalBox("");
2228 {
2229 builder.openFrameBox("");
2230 builder.closeBox();
2231 builder.openFrameBox("");
2232 //builder.addSeqButton(_("Setup"), seqw);
2233 builder.closeBox();
2234 }
2235 builder.closeBox();
2236 builder.openFrameBox("");
2237 builder.closeBox();
2238 }
2239 builder.closeBox();
2240 return 0;
2241 } else {
2242 return -1;
2243 }
2244 }
2245
2246 /****************************************************************************
2247 *
2248 * NAME: smbPitchShift.cpp
2249 * VERSION: 1.2
2250 * HOME URL: http://www.dspdimension.com
2251 * KNOWN BUGS: none
2252 *
2253 *
2254 * COPYRIGHT 1999-2009 Stephan M. Bernsee <smb [AT] dspdimension [DOT] com>
2255 *
2256 * Modified for guitarix by Hermann Meyer 2014
2257 *
2258 * The Wide Open License (WOL)
2259 *
2260 * Permission to use, copy, modify, distribute and sell this software and its
2261 * documentation for any purpose is hereby granted without fee, provided that
2262 * the above copyright notice and this license appear in all source copies.
2263 * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF
2264 * ANY KIND. See http://www.dspguru.com/wol.htm for more information.
2265 *
2266 *****************************************************************************/
2267
setParameters(int sampleRate_)2268 bool smbPitchShift::setParameters(int sampleRate_)
2269 {
2270 numSampsToProcess = int(engine.get_buffersize());
2271 fftFrameSize = numSampsToProcess/4;
2272 sampleRate = int(sampleRate_);
2273 assert(sampleRate>0);
2274 osamp = 8;
2275 osamp1 = 1./osamp;
2276 osamp2 = 2.*M_PI*osamp1;
2277 mpi = (1./(2.*M_PI)) * osamp;
2278 mpi1 = 1./M_PI;
2279 fpb = 0;
2280 expect = 0;
2281 hanning = 0;
2282 hanningd = 0;
2283 resampin = 0;
2284 resampout = 0;
2285 indata2 = 0;
2286 resamp.setup(sampleRate,4);
2287 gRover = inFifoLatency;
2288 return true;
2289 }
2290
smbPitchShift(EngineControl & engine_,sigc::slot<void> sync_)2291 smbPitchShift::smbPitchShift(EngineControl& engine_, sigc::slot<void> sync_):
2292 PluginDef(),
2293 engine(engine_),
2294 mem_allocated(false),
2295 sync(sync_),
2296 ready(false),
2297 ftPlanForward(0),
2298 ftPlanInverse(0),
2299 plugin() {
2300 memset(gInFIFO, 0, MAX_FRAME_LENGTH*sizeof(float));
2301 memset(gOutFIFO, 0, MAX_FRAME_LENGTH*sizeof(float));
2302 memset(gLastPhase, 0, (MAX_FRAME_LENGTH/2+1)*sizeof(float));
2303 memset(gSumPhase, 0, (MAX_FRAME_LENGTH/2+1)*sizeof(float));
2304 memset(gOutputAccum, 0, 2*MAX_FRAME_LENGTH*sizeof(float));
2305 memset(gAnaFreq, 0, MAX_FRAME_LENGTH*sizeof(float));
2306 memset(gAnaMagn, 0, MAX_FRAME_LENGTH*sizeof(float));
2307 version = PLUGINDEF_VERSION;
2308 id = "smbPitchShift";
2309 name = N_("Detune");
2310 groups = 0;
2311 description = N_("detune and pitch shift up"); // description (tooltip)
2312 category = N_("Misc"); // category
2313 mono_audio = compute_static;
2314 stereo_audio = 0;
2315 set_samplerate = init;
2316 activate_plugin = activate_static;
2317 register_params = registerparam;
2318 delete_instance = del_instance;
2319 load_ui = load_ui_f_static;
2320 plugin = this;
2321 engine.signal_buffersize_change().connect(
2322 sigc::mem_fun(*this, &smbPitchShift::change_buffersize));
2323 }
2324
init(unsigned int samplingFreq,PluginDef * plugin)2325 void smbPitchShift::init(unsigned int samplingFreq, PluginDef *plugin) {
2326 static_cast<smbPitchShift*>(plugin)->setParameters(samplingFreq);
2327
2328 }
2329
clear_state()2330 void smbPitchShift::clear_state()
2331 {
2332 stepSize = fftFrameSize/osamp;
2333 freqPerBin = (double)(sampleRate/4)/(double)fftFrameSize;
2334 freqPerBin1 = (1/freqPerBin)*osamp2;
2335 freqPerBin2 = freqPerBin*mpi;
2336 expct = 2.*M_PI*(double)stepSize/(double)fftFrameSize;
2337 inFifoLatency = fftFrameSize-stepSize;
2338 fftFrameSize3 = 2. * (1./ ((double)(fftFrameSize2)*osamp));
2339 fftFrameSize4 = 1./(double)fftFrameSize;
2340 ai = 0;
2341 aio = 0;
2342 ii = 0;
2343 tone =0;
2344 memset(gInFIFO, 0, MAX_FRAME_LENGTH*sizeof(float));
2345 memset(gOutFIFO, 0, MAX_FRAME_LENGTH*sizeof(float));
2346 memset(gLastPhase, 0, (MAX_FRAME_LENGTH/2+1)*sizeof(float));
2347 memset(gSumPhase, 0, (MAX_FRAME_LENGTH/2+1)*sizeof(float));
2348 memset(gOutputAccum, 0, 2*MAX_FRAME_LENGTH*sizeof(float));
2349 memset(gAnaFreq, 0, MAX_FRAME_LENGTH*sizeof(float));
2350 memset(gAnaMagn, 0, MAX_FRAME_LENGTH*sizeof(float));
2351 for (k = 0; k < fftFrameSize2;k++) {
2352 fpb[k] = (double)k*freqPerBin;
2353 }
2354 for (k = 0; k < fftFrameSize2;k++) {
2355 expect[k] = (double)k*expct;
2356 }
2357 for (k = 0; k < fftFrameSize;k++) {
2358 hanning[k] = 0.5*(1-cos(2.*M_PI*(double)k/((double)fftFrameSize)));
2359 }
2360 for (k = 0; k < fftFrameSize;k++) {
2361 hanningd[k] = 0.5*(1-cos(2.*M_PI*(double)k * fftFrameSize4)) * fftFrameSize3;
2362 }
2363 for (k = 0; k < fftFrameSize;k++) {
2364 resampin[k] = 0.0;
2365 }
2366 for (k = 0; k < fftFrameSize;k++) {
2367 resampin2[k] = 0.0;
2368 }
2369 for (k = 0; k < fftFrameSize*4;k++) {
2370 resampout[k] = 0.0;
2371 }
2372 for (k = 0; k < fftFrameSize*4;k++) {
2373 indata2[k] = 0.0;
2374 }
2375 gRover = inFifoLatency;
2376 mem_allocated = true;
2377 ready = true;
2378 }
2379
mem_alloc()2380 void smbPitchShift::mem_alloc()
2381 {
2382 numSampsToProcess = int(engine.get_buffersize());
2383 assert(numSampsToProcess>0);
2384 numSampsToResamp = numSampsToProcess/4;
2385 sampleRate = int(engine.get_samplerate());
2386 assert(sampleRate>0);
2387
2388 switch(latency) {
2389 case(0):
2390 if (numSampsToProcess <= 2048) {
2391 fftFrameSize = 512 ;
2392 } else {
2393 fftFrameSize = numSampsToProcess*0.25 ;
2394 }
2395 break;
2396 case(1):
2397 fftFrameSize = numSampsToProcess;
2398 break;
2399 case(2):
2400 fftFrameSize = numSampsToProcess*0.25;
2401 break;
2402 default:
2403 if (numSampsToProcess <= 2048) {
2404 fftFrameSize = 512 ;
2405 } else {
2406 fftFrameSize = numSampsToProcess*0.25 ;
2407 }
2408 break;
2409 }
2410 fftFrameSize2 = fftFrameSize/2;
2411
2412 try {
2413 //create FFTW plan
2414 ftPlanForward = fftwf_plan_dft_1d(fftFrameSize, fftw_in, fftw_out, FFTW_FORWARD, FFTW_ESTIMATE);
2415 ftPlanInverse = fftwf_plan_dft_1d(fftFrameSize, fftw_in, fftw_out, FFTW_BACKWARD, FFTW_ESTIMATE);
2416 // alloc buffers
2417 fpb = new float[fftFrameSize2];
2418 expect = new float[fftFrameSize2];
2419 hanning = new float[fftFrameSize];
2420 hanningd = new float[fftFrameSize];
2421 resampin = new float[fftFrameSize];
2422 resampin2 = new float[fftFrameSize];
2423 resampout = new float[fftFrameSize*4];
2424 indata2 = new float[fftFrameSize*4];
2425 } catch(...) {
2426 gx_print_error("detune", "cant allocate memory pool");
2427 return;
2428 }
2429 clear_state();
2430 }
2431
mem_free()2432 void smbPitchShift::mem_free()
2433 {
2434 ready = false;
2435 mem_allocated = false;
2436 if (fpb) { delete fpb; fpb = 0; }
2437 if (expect) { delete expect; expect = 0; }
2438 if (hanning) { delete hanning; hanning = 0; }
2439 if (hanningd) { delete hanningd; hanningd = 0; }
2440 if (resampin) { delete resampin; resampin = 0; }
2441 if (resampin2) { delete resampin2; resampin2 = 0; }
2442 if (resampout) { delete resampout; resampout = 0; }
2443 if (indata2) { delete indata2; indata2 = 0; }
2444 if (ftPlanForward)
2445 {fftwf_destroy_plan(ftPlanForward);ftPlanForward = 0; }
2446 if (ftPlanInverse)
2447 { fftwf_destroy_plan(ftPlanInverse);ftPlanInverse = 0; }
2448 }
2449
activate(bool start)2450 int smbPitchShift::activate(bool start)
2451 {
2452 if (start) {
2453 if (!mem_allocated) {
2454 mem_alloc();
2455 }
2456 } else if (mem_allocated) {
2457 mem_free();
2458 }
2459 return 0;
2460 }
2461
change_buffersize(unsigned int size)2462 void smbPitchShift::change_buffersize(unsigned int size)
2463 {
2464 sync();
2465 ready = false;
2466 if (mem_allocated) {
2467 mem_free();
2468 mem_alloc();
2469 }
2470 }
2471
change_latency()2472 void smbPitchShift::change_latency()
2473 {
2474 sync();
2475 ready = false;
2476 if (mem_allocated) {
2477 mem_free();
2478 mem_alloc();
2479 }
2480 }
2481
~smbPitchShift()2482 smbPitchShift::~smbPitchShift()
2483 {
2484 if (mem_allocated) {
2485 mem_free();
2486 }
2487 }
2488
2489 // -----------------------------------------------------------------------------------------------------------------
compute_static(int count,float * input0,float * output0,PluginDef * p)2490 void __rt_func smbPitchShift::compute_static(int count, float *input0, float *output0, PluginDef *p)
2491 {
2492 static_cast<smbPitchShift*>(p)->PitchShift(count, input0, output0);
2493 }
2494
2495
PitchShift(int count,float * indata,float * outdata)2496 void always_inline smbPitchShift::PitchShift(int count, float *indata, float *outdata)
2497 {
2498
2499 if (!ready || count != numSampsToProcess) {
2500 if (indata != outdata) {
2501 memcpy(outdata,indata,count*sizeof(float));
2502 }
2503 return;
2504 }
2505
2506 resamp.down(numSampsToResamp,indata,resampin);
2507 double fSlow0 = (0.01 * wet);
2508 double fSlow1 = (0.01 * dry);
2509
2510 // collect data for latency compensation
2511 for (i = 0; i < count; i++) {
2512 indata2[ii] = indata[i];
2513 ii++;
2514 }
2515 // collect data for fft
2516 for (i = 0; i < numSampsToResamp; i++) {
2517 resampin2[ai] = resampin[i];
2518 ai++;
2519 }
2520 // now we have enough data
2521 if (ai>=fftFrameSize) {
2522 ai = 0;
2523 ii = 0;
2524 switch(octave) {
2525 case(0):
2526 tone =0;
2527 break;
2528 case(1):
2529 tone =12;
2530 break;
2531 case(2):
2532 tone =-12;
2533 break;
2534 default:
2535 tone =0;
2536 break;
2537 }
2538 float pitchShift = pow(2., (semitones+tone)*0.0833333333);
2539 /* main processing loop */
2540 for (i = 0; i < fftFrameSize; i++) {
2541
2542 /* As long as we have not yet collected enough data just read in */
2543 float fTemp = resampin2[i];
2544 gInFIFO[gRover] = fTemp;
2545 resampin2[i] = gOutFIFO[gRover-inFifoLatency];
2546 gRover++;
2547
2548 /* now we have enough data for processing */
2549 if (gRover >= fftFrameSize) {
2550 gRover = inFifoLatency;
2551
2552 /* do windowing and re,im interleave */
2553 for (k = 0; k < fftFrameSize;k++) {
2554 fftw_in[k][0] = gInFIFO[k] * hanning[k];
2555 fftw_in[k][1] = 0.0;
2556 }
2557
2558
2559 /* ***************** ANALYSIS ******************* */
2560 /* do transform */
2561 fftwf_execute(ftPlanForward);
2562
2563 /* this is the analysis step */
2564 for (k = 0; k < fftFrameSize2; k++) {
2565
2566 /* de-interlace FFT buffer */
2567 real = fftw_out[k][0];
2568 imag = fftw_out[k][1];
2569
2570 /* compute magnitude and phase */
2571 magn = 2.*sqrt(real*real + imag*imag);
2572 phase = atan2(imag,real);
2573
2574 /* compute phase difference */
2575 tmp = phase - gLastPhase[k];
2576 gLastPhase[k] = phase;
2577
2578 /* subtract expected phase difference */
2579 tmp -= expect[k];
2580
2581 /* map delta phase into +/- Pi interval */
2582 qpd = tmp*mpi1;
2583 if (qpd >= 0) qpd += qpd&1;
2584 else qpd -= qpd&1;
2585 tmp -= M_PI*(double)qpd;
2586
2587 /* get deviation from bin frequency from the +/- Pi interval */
2588 /* compute the k-th partials' true frequency */
2589 tmp = fpb[k] + tmp*freqPerBin2;
2590
2591 /* store magnitude and true frequency in analysis arrays */
2592 gAnaMagn[k] = magn;
2593 gAnaFreq[k] = tmp;
2594
2595 }
2596
2597 /* ***************** PROCESSING ******************* */
2598 /* this does the actual pitch shifting */
2599 memset(gSynMagn, 0, fftFrameSize*sizeof(float));
2600 memset(gSynFreq, 0, fftFrameSize*sizeof(float));
2601 for (k = 1; k < fftFrameSize2-2; k++) {
2602 index = k*pitchShift;
2603 if (index < fftFrameSize2) {
2604 if (index < fftFrameSize2*0.20)
2605 gSynMagn[index] += gAnaMagn[k]*a;
2606 else if (index < fftFrameSize2*0.45)
2607 gSynMagn[index] += gAnaMagn[k]*b;
2608 else if (index < fftFrameSize2*0.667)
2609 gSynMagn[index] += gAnaMagn[k]*c;
2610 else
2611 gSynMagn[index] += gAnaMagn[k]*d;
2612 gSynFreq[index] = gAnaFreq[k] * pitchShift;
2613 }
2614 }
2615
2616 /* ***************** SYNTHESIS ******************* */
2617 /* this is the synthesis step */
2618 for (k = 0; k < fftFrameSize2; k++) {
2619
2620 /* get magnitude and true frequency from synthesis arrays */
2621 magn = gSynMagn[k];
2622 //tmp = gSynFreq[k];
2623
2624 /* subtract bin mid frequency */
2625 /* get bin deviation from freq deviation */
2626 /* take osamp into account */
2627 /* add the overlap phase advance back in */
2628 tmp = ((gSynFreq[k] - fpb[k]) * freqPerBin1) + expect[k];
2629
2630 /* accumulate delta phase to get bin phase */
2631 gSumPhase[k] += tmp;
2632 phase = gSumPhase[k];
2633 if (magn == 0.0) continue;
2634
2635 /* get real and imag part and re-interleave */
2636 fftw_in[k][0] = magn * cos (phase);
2637 fftw_in[k][1] = magn * sin (phase);
2638 }
2639
2640 /* do inverse transform */
2641 fftwf_execute(ftPlanInverse);
2642 /* do windowing and add to output accumulator */
2643 for(k=0; k < fftFrameSize; k++) {
2644 gOutputAccum[k] += hanningd[k] * fftw_out[ k][0] ;
2645 }
2646 for (k = 0; k < stepSize; k++) gOutFIFO[k] = gOutputAccum[k];
2647
2648 /* shift accumulator */
2649 memmove(gOutputAccum, gOutputAccum+stepSize, fftFrameSize*sizeof(float));
2650
2651 /* move input FIFO */
2652 for (k = 0; k < inFifoLatency; k++) gInFIFO[k] = gInFIFO[k+stepSize];
2653 }
2654 }
2655 resamp.up(fftFrameSize,resampin2,resampout);
2656 aio = 0;
2657 }
2658 if(l) {
2659 for (i = 0; i < count; i++){
2660 outdata[i] = ((fSlow0 * resampout[aio]) + (fSlow1 *indata2[aio]));
2661 aio++;
2662 }
2663 } else {
2664 for (i = 0; i < count; i++){
2665 outdata[i] = ((fSlow0 * resampout[aio]) + (fSlow1 *indata[i]));
2666 aio++;
2667 }
2668 }
2669 }
2670
register_par(const ParamReg & reg)2671 int smbPitchShift::register_par(const ParamReg& reg)
2672 {
2673 reg.registerFloatVar("smbPitchShift.semitone", N_("Detune"), "S", "", &semitones, 0.0, -12., 12., 0.1, 0);
2674 static const value_pair octave_values[] = {{"unison"},{"octave up"},{"octave down"},{0}};
2675 reg.registerIntVar("smbPitchShift.octave",N_("add harmonics"),"B",N_("add harmonics"),&octave, 0, 0, 0, octave_values);
2676 static const value_pair latency_values[] = {{"latency "},{"compensate"},{0}};
2677 reg.registerFloatVar("smbPitchShift.l",N_("compensate latency"),"S",N_("compensate latency"),&l, 0.0f, 0.0f, 1.0f, 1.0f, latency_values);
2678 static const value_pair latency_set[] = {{"high quality"},{"low quality"},{"realtime"},{0}};
2679 reg.registerIntVar("smbPitchShift.latency",N_("latency settings"),"B",N_("latency settings"),&latency, 0, 0, 0, latency_set);
2680 reg.registerFloatVar("smbPitchShift.wet", N_("Wet"), "S", N_("Wet amount"), &wet, 50.0, 0.0, 100.0, 1, 0);
2681 reg.registerFloatVar("smbPitchShift.dry", N_("Dry"), "S", N_("Dry amount"), &dry, 50.0, 0.0, 100.0, 1, 0);
2682 reg.registerFloatVar("smbPitchShift.a", N_("low"), "S", N_("Sub"), &a, 1.0, 0.0, 2.0, 0.01, 0);
2683 reg.registerFloatVar("smbPitchShift.b", N_("middle low"), "S", N_("Low"), &b, 1.0, 0.0, 2.0, 0.01, 0);
2684 reg.registerFloatVar("smbPitchShift.c", N_("middle treble"), "S", N_("Mid"), &c, 1.0, 0.0, 2.0, 0.01, 0);
2685 reg.registerFloatVar("smbPitchShift.d", N_("treble"), "S", N_("Hi"), &d, 1.0, 0.0, 2.0, 0.01, 0);
2686 engine.get_param()["smbPitchShift.latency"].signal_changed_int().connect(
2687 sigc::hide(sigc::mem_fun(this, &smbPitchShift::change_latency)));
2688 return 0;
2689 }
2690
registerparam(const ParamReg & reg)2691 int smbPitchShift::registerparam(const ParamReg& reg)
2692 {
2693 return static_cast<smbPitchShift*>(reg.plugin)->register_par(reg);
2694 }
2695
load_ui_f(const UiBuilder & b,int form)2696 int smbPitchShift::load_ui_f(const UiBuilder& b, int form)
2697 {
2698 if (form & UI_FORM_GLADE) {
2699 b.load_glade_file("gx_detune_ui.glade");
2700 return 0;
2701 }
2702 if (form & UI_FORM_STACK) {
2703 b.openHorizontalhideBox("");
2704 {
2705 b.create_master_slider("smbPitchShift.semitone",N_("Detune"));
2706 }
2707 b.closeBox();
2708 b.openVerticalBox("");
2709 {
2710 b.openHorizontalBox("");
2711 {
2712 b.openVerticalBox("");
2713 {
2714 b.insertSpacer();
2715 b.create_selector_no_caption("smbPitchShift.octave");
2716 b.create_selector_no_caption("smbPitchShift.l");
2717 b.create_selector_no_caption("smbPitchShift.latency");
2718 b.insertSpacer();
2719 }
2720 b.closeBox();
2721 b.create_mid_rackknob("smbPitchShift.semitone",N_("Detune"));
2722 b.create_small_rackknobr("smbPitchShift.dry",N_("Dry"));
2723 b.create_small_rackknobr("smbPitchShift.wet",N_("Wet"));
2724 }
2725 b.closeBox();
2726 b.insertSpacer();
2727 b.openHorizontalBox("");
2728 {
2729 b.set_next_flags(UI_LABEL_INVERSE);
2730 b.create_small_rackknobr("smbPitchShift.a",N_("Lo"));
2731 b.set_next_flags(UI_LABEL_INVERSE);
2732 b.create_small_rackknobr("smbPitchShift.b",N_("LoMid"));
2733 b.set_next_flags(UI_LABEL_INVERSE);
2734 b.create_small_rackknobr("smbPitchShift.c",N_("HiMid"));
2735 b.set_next_flags(UI_LABEL_INVERSE);
2736 b.create_small_rackknobr("smbPitchShift.d",N_("Hi"));
2737 }
2738 b.closeBox();
2739 }
2740 b.closeBox();
2741 return 0;
2742 }
2743 return -1;
2744 }
2745
activate_static(bool start,PluginDef * p)2746 int smbPitchShift::activate_static(bool start, PluginDef *p)
2747 {
2748 return static_cast<smbPitchShift*>(p)->activate(start);
2749 }
2750
load_ui_f_static(const UiBuilder & b,int form)2751 int smbPitchShift::load_ui_f_static(const UiBuilder& b, int form)
2752 {
2753 return static_cast<smbPitchShift*>(b.plugin)->load_ui_f(b, form);
2754 }
2755
del_instance(PluginDef * p)2756 void smbPitchShift::del_instance(PluginDef *p)
2757 {
2758 delete static_cast<smbPitchShift*>(p);
2759 }
2760
2761
2762 } // namespace gx_engine
2763