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