Guitarix
gx_internal_plugins.cpp
Go to the documentation of this file.
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;
43 
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 
56  outputgate.id = "noiseshut";
57  outputgate.name = "?noiseshut";
58  outputgate.mono_audio = outputgate_compute;
59  outputgate.activate_plugin = outputgate_activate;
60 
61 }
62 
63 inline float sqrf(float x) {
64  return x * x;
65 }
66 
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 
79 int NoiseGate::noisegate_register(const ParamReg& reg) {
80  reg.registerVar("noise_gate.threshold", N_("Threshold"), "S", "", &fnglevel,
81  0.017f, 0.01f, 0.31f, 0.001f);
82  return 0;
83 }
84 
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 
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 /****************************************************************
103  ** class GxJConvSettings
104  */
105 
107  : fIRFile(),
108  fIRDir(),
109  fGain(0),
110  fOffset(0),
111  fLength(0),
112  fDelay(0),
113  gainline(),
114  fGainCor(false) {
115 }
118  fIRFile = jcset.fIRFile;
119  fIRDir = jcset.fIRDir;
120  fGain = jcset.fGain;
121  fOffset = jcset.fOffset;
122  fLength = jcset.fLength;
123  fDelay = jcset.fDelay;
124  gainline = jcset.gainline;
125  fGainCor = jcset.fGainCor;
126  return *this;
127 }
128 
129 std::string GxJConvSettings::getFullIRPath() const {
130  if (fIRFile.empty()) {
131  return fIRFile;
132  } else {
133  return Glib::build_filename(fIRDir, fIRFile);
134  }
135 }
136 
138  fIRDir = Glib::path_get_dirname(name);
139  fIRFile= Glib::path_get_basename(name);
140 }
141 
143  w.begin_object(true);
144  w.write_kv("jconv.IRFile", fIRFile);
145  w.write_kv("jconv.IRDir", gx_system::get_options().get_IR_prefixmap().replace_path(fIRDir));
146  w.write_kv("jconv.Gain", fGain);
147  w.write_kv("jconv.GainCor", fGainCor);
148  w.write_kv("jconv.Offset", fOffset);
149  w.write_kv("jconv.Length", fLength);
150  w.write_kv("jconv.Delay", fDelay);
151  w.write_key("jconv.gainline");
152  w.begin_array();
153  for (unsigned int i = 0; i < gainline.size(); i++) {
154  w.begin_array();
155  w.write(gainline[i].i);
156  w.write(gainline[i].g);
157  w.end_array();
158  }
159  w.end_array(true);
160  w.end_object(true);
161 }
162 
164  if (fIRFile != jcset.fIRFile || fIRDir != jcset.fIRDir) {
165  return false;
166  }
167  if (fOffset != jcset.fOffset || fLength != jcset.fLength || fDelay != jcset.fDelay) {
168  return false;
169  }
170  if (fGainCor != jcset.fGainCor) {
171  return false;
172  }
173  if (fGainCor && abs(fGain - jcset.fGain) > 1e-4 * (fGain + jcset.fGain)) {
174  return false;
175  }
176  if (gainline == jcset.gainline) {
177  return false;
178  }
179  return true;
180 }
181 
182 void GxJConvSettings::read_gainline(gx_system::JsonParser& jp) {
183  gainline.clear();
185  while (jp.peek() == gx_system::JsonParser::begin_array) {
186  jp.next();
188  gain_points p;
189  p.i = jp.current_value_int();
191  p.g = jp.current_value_float();
193  gainline.push_back(p);
194  }
196 }
197 
200  do {
202  if (jp.read_kv("jconv.IRFile", fIRFile) ||
203  jp.read_kv("jconv.IRDir", fIRDir) ||
204  jp.read_kv("jconv.Gain", fGain) ||
205  jp.read_kv("jconv.GainCor", fGainCor) ||
206  jp.read_kv("jconv.Offset", fOffset) ||
207  jp.read_kv("jconv.Length", fLength) ||
208  jp.read_kv("jconv.Delay", fDelay)) {
209  } else if (jp.current_value() == "jconv.gainline") {
210  read_gainline(jp);
211  } else if (jp.current_value() == "jconv.favorits") {
212  jp.skip_object();
213  } else {
214  gx_print_warning("jconv settings", "unknown key: " + jp.current_value());
215  jp.skip_object();
216  }
217  } while (jp.peek() == gx_system::JsonParser::value_key);
219  if (!fIRFile.empty()) {
220  if (fIRDir.empty()) {
221  gx_system::get_options().get_IR_pathlist().find_dir(&fIRDir, fIRFile);
222  } else {
224  }
225  }
226 }
227 
228 
229 /****************************************************************
230  ** class JConvParameter
231  */
232 
234  : Parameter(id, "", tp_special, None, true, false),
235  json_value(),
236  value(v),
237  std_value(),
238  value_storage(),
239  changed() {
240  std_value.setFullIRPath(gx_system::get_options().get_IR_prefixmap().replace_symbol("%S/greathall.wav"));
241  std_value.fGainCor = true;
242  std_value.fGain = 0.598717;
243  const int ir_len = 112561;
244  std_value.fLength = ir_len;
245  static gain_points g[2] = {{0, 0}, {ir_len-1, 0}};
246  std_value.gainline = Gainline(g, sizeof(g) / sizeof(g[0]));
247 }
248 
250  ParamMap &pmap, const string& id, ConvolverAdapter &conv, GxJConvSettings *v) {
251  JConvParameter *p = new JConvParameter(id, conv, v);
252  pmap.insert(p);
253  return p;
254 }
255 
257 }
258 
260  : Parameter(jp_next(jp, "Parameter")),
261  searchpath(0),
262  pfx_conv(0),
263  json_value(),
264  value(&value_storage),
265  std_value() {
266  while (jp.peek() != gx_system::JsonParser::end_object) {
268  if (jp.current_value() == "value") {
269  value->readJSON(jp);
270  } else if (jp.current_value() == "std_value") {
271  std_value.readJSON(jp);
272  } else {
274  "JConvParameter", Glib::ustring::compose("%1: unknown key: %2", _id, jp.current_value()));
275  jp.skip_object();
276  }
277  }
279 }
280 
282  jw.begin_object();
283  jw.write_key("Parameter"); Parameter::serializeJSON(jw);
284  jw.write_key("value"); value->writeJSON(jw);
285  jw.write_key("std_value"); std_value.writeJSON(jw);
286  jw.end_object();
287 }
288 
290  assert(false);
291  return false;
292 }
293 
295  json_value = std_value;
296 }
297 
299  jw.write_key(_id.c_str());
300  value->writeJSON(jw);
301 }
302 
304  json_value.readJSON(jp);
305 }
306 
308  return json_value == *value;
309 }
310 
311 bool JConvParameter::set(const GxJConvSettings& val) const {
312  if (val == *value) {
313  return false;
314  }
315  *value = val;
316  changed(value);
317  return true;
318 }
319 
321  set(json_value);
322 }
323 
324 
325 /****************************************************************
326  ** class ConvolverAdapter
327  */
328 
329 #include "faust/jconv_post.cc"
330 #include "faust/jconv_post_mono.cc"
331 
333  EngineControl& engine_, sigc::slot<void> sync_, ParamMap& param_)
334  : PluginDef(),
335  conv(),
336  activate_mutex(),
337  engine(engine_),
338  sync(sync_),
339  param(param_),
340  activated(false),
341  jcset(),
342  jcp(0),
343  plugin() {
345  category = N_("Reverb");
346  //FIXME: add clear_state
347  plugin = this;
349  sigc::mem_fun(*this, &ConvolverAdapter::change_buffersize));
350 }
351 
353 }
354 
355 void ConvolverAdapter::change_buffersize(unsigned int size) {
356  boost::mutex::scoped_lock lock(activate_mutex);
357  if (activated) {
358  conv.stop_process();
359  while (conv.is_runnable()) {
360  conv.checkstate();
361  }
362  conv.set_buffersize(size);
363  if (size) {
364  conv_start();
365  }
366  } else {
367  conv.set_buffersize(size);
368  }
369 }
370 
372  if (!plugin.get_on_off()) {
373  return;
374  }
375  conv.set_not_runnable();
376  sync();
377  conv.stop_process();
378  while (!conv.checkstate());
379  float gain;
380  if (jcset.getGainCor()) {
381  gain = jcset.getGain();
382  } else {
383  gain = 1.0;
384  }
385  bool rc = conv.configure(
386  jcset.getFullIRPath(), gain, gain, jcset.getDelay(), jcset.getDelay(),
388  int policy, priority;
389  engine.get_sched_priority(policy, priority);
390  if (!rc || !conv.start(policy, priority)) {
391  plugin.set_on_off(false);
392  }
393 }
394 
396  if (!conv.get_buffersize() || !conv.get_samplerate()) {
397  return false;
398  }
399  string path = jcset.getFullIRPath();
400  if (path.empty()) {
401  gx_print_warning(_("convolver"), _("no impulseresponse file"));
402  plugin.set_on_off(false);
403  return false;
404  }
405  while (!conv.checkstate());
406  if (conv.is_runnable()) {
407  return true;
408  }
409  float gain;
410  if (jcset.getGainCor()) {
411  gain = jcset.getGain();
412  } else {
413  gain = 1.0;
414  }
415  if (!conv.configure(
416  path, gain, gain, jcset.getDelay(), jcset.getDelay(),
417  jcset.getOffset(), jcset.getLength(), 0, 0, jcset.getGainline())) {
418  return false;
419  }
420  int policy, priority;
421  engine.get_sched_priority(policy, priority);
422  return conv.start(policy, priority);
423 }
424 
425 
426 /****************************************************************
427  ** class ConvolverStereoAdapter
428  */
429 
431  EngineControl& engine_, sigc::slot<void> sync_, ParamMap& param_)
432  : ConvolverAdapter(engine_, sync_, param_) {
433  id = "jconv";
434  name = N_("Convolver");
435  register_params = convolver_register;
436  set_samplerate = convolver_init;
437  activate_plugin = activate;
438  stereo_audio = convolver;
439 }
440 
442 }
443 
444 void ConvolverStereoAdapter::convolver(int count, float *input0, float *input1,
445  float *output0, float *output1, PluginDef* plugin) {
446  ConvolverStereoAdapter& self = *static_cast<ConvolverStereoAdapter*>(plugin);
447  if (self.conv.is_runnable()) {
448  float conv_out0[count];
449  float conv_out1[count];
450  if (self.conv.compute(count, input0, input1, conv_out0, conv_out1)) {
451  self.jc_post.compute(count, input0, input1,
452  conv_out0, conv_out1, output0, output1);
453  return;
454  }
455  self.engine.overload(EngineControl::ov_Convolver, self.id);
456  }
457  if (input0 != output0) {
458  memcpy(output0, input0, count * sizeof(float));
459  }
460  if (input1 != output1) {
461  memcpy(output1, input1, count * sizeof(float));
462  }
463 }
464 
465 int ConvolverStereoAdapter::convolver_register(const ParamReg& reg) {
466  ConvolverStereoAdapter& self = *static_cast<ConvolverStereoAdapter*>(reg.plugin);
467  self.jcp = JConvParameter::insert_param(self.param, "jconv.convolver", self, &self.jcset);
468  self.jcp->signal_changed().connect(
469  sigc::hide(
470  sigc::mem_fun(self, &ConvolverStereoAdapter::restart)));
471  return self.jc_post.register_par(reg);
472 }
473 
474 void ConvolverStereoAdapter::convolver_init(unsigned int samplingFreq, PluginDef *p) {
475  ConvolverStereoAdapter& self = *static_cast<ConvolverStereoAdapter*>(p);
476  boost::mutex::scoped_lock lock(self.activate_mutex);
477  if (self.activated) {
478  self.conv.stop_process();
479  self.conv.set_samplerate(samplingFreq);
480  self.jc_post.init(samplingFreq);
481  while (self.conv.is_runnable()) {
482  self.conv.checkstate();
483  }
484  self.conv_start();
485  } else {
486  self.conv.set_samplerate(samplingFreq);
487  self.jc_post.init(samplingFreq);
488  }
489 }
490 
491 int ConvolverStereoAdapter::activate(bool start, PluginDef *p) {
492  ConvolverStereoAdapter& self = *static_cast<ConvolverStereoAdapter*>(p);
493  boost::mutex::scoped_lock lock(self.activate_mutex);
494  if (start) {
495  if (self.activated && self.conv.is_runnable()) {
496  return 0;
497  }
498  } else {
499  if (!self.activated) {
500  return 0;
501  }
502  }
503  self.activated = start;
504  if (start) {
505  if (self.jc_post.activate(true) != 0) {
506  gx_print_error(_("convolver"), "jconv post activate error?!");
507  return -1;
508  }
509  if (!self.conv_start()) {
510  return -1;
511  }
512  } else {
513  self.conv.stop_process();
514  self.jc_post.activate(false);
515  }
516  return 0;
517 }
518 
519 
520 /****************************************************************
521  ** class ConvolverMonoAdapter
522  */
523 
525  EngineControl& engine_, sigc::slot<void> sync_, ParamMap& param_)
526  : ConvolverAdapter(engine_, sync_, param_) {
527  id = "jconv_mono";
528  name = N_("Convolver");
529  register_params = convolver_register;
530  set_samplerate = convolver_init;
531  activate_plugin = activate;
532  mono_audio = convolver;
533 }
534 
536 }
537 
538 void ConvolverMonoAdapter::convolver(int count, float *input, float *output, PluginDef* plugin) {
539  ConvolverMonoAdapter& self = *static_cast<ConvolverMonoAdapter*>(plugin);
540  if (self.conv.is_runnable()) {
541  float conv_out[count];
542  if (self.conv.compute(count, input, conv_out)) {
543  self.jc_post_mono.compute(count, output, conv_out, output);
544  return;
545  }
546  self.engine.overload(EngineControl::ov_Convolver, self.id);
547  }
548  if (input != output) {
549  memcpy(output, input, count * sizeof(float));
550  }
551 }
552 
553 int ConvolverMonoAdapter::convolver_register(const ParamReg& reg) {
554  ConvolverMonoAdapter& self = *static_cast<ConvolverMonoAdapter*>(reg.plugin);
555  self.jcp = JConvParameter::insert_param(self.param, "jconv_mono.convolver", self, &self.jcset);
556  self.jcp->signal_changed().connect(
557  sigc::hide(
558  sigc::mem_fun(self, &ConvolverMonoAdapter::restart)));
559  return self.jc_post_mono.register_par(reg);;
560 }
561 
562 void ConvolverMonoAdapter::convolver_init(unsigned int samplingFreq, PluginDef *p) {
563  ConvolverMonoAdapter& self = *static_cast<ConvolverMonoAdapter*>(p);
564  boost::mutex::scoped_lock lock(self.activate_mutex);
565  if (self.activated) {
566  self.conv.stop_process();
567  self.conv.set_samplerate(samplingFreq);
568  while (self.conv.is_runnable()) {
569  self.conv.checkstate();
570  }
571  self.conv_start();
572  } else {
573  self.conv.set_samplerate(samplingFreq);
574  }
575 }
576 
577 int ConvolverMonoAdapter::activate(bool start, PluginDef *p) {
578  ConvolverMonoAdapter& self = *static_cast<ConvolverMonoAdapter*>(p);
579  boost::mutex::scoped_lock lock(self.activate_mutex);
580  if (start) {
581  if (self.activated && self.conv.is_runnable()) {
582  return 0;
583  }
584  } else {
585  if (!self.activated) {
586  return 0;
587  }
588  }
589  self.activated = start;
590  if (start) {
591  if (!self.conv_start()) {
592  return -1;
593  }
594  } else {
595  self.conv.stop_process();
596  }
597  return 0;
598 }
599 
600 /****************************************************************
601  ** class BaseConvolver
602  */
603 
604 
606  : PluginDef(),
607  conv(resamp),
608  activate_mutex(),
609  engine(engine_),
610  sync(sync_),
611  activated(false),
612  plugin() {
616  plugin = this;
618  sigc::mem_fun(*this, &BaseConvolver::change_buffersize));
619 }
620 
622  update_conn.disconnect();
623 }
624 
625 void BaseConvolver::change_buffersize(unsigned int bufsize) {
626  boost::mutex::scoped_lock lock(activate_mutex);
627  conv.set_buffersize(bufsize);
628  if (activated) {
629  if (!bufsize) {
630  conv.stop_process();
631  } else {
632  start(true);
633  }
634  }
635 }
636 
637 void BaseConvolver::init(unsigned int samplingFreq, PluginDef *p) {
638  BaseConvolver& self = *static_cast<BaseConvolver*>(p);
639  boost::mutex::scoped_lock lock(self.activate_mutex);
640  self.conv.set_samplerate(samplingFreq);
641  if (self.activated) {
642  self.start(true);
643  }
644 }
645 
647  if (!activated || !plugin.get_on_off()) {
648  return false;
649  }
650  check_update();
651  return true;
652 }
653 
654 int BaseConvolver::activate(bool start, PluginDef *p) {
655  BaseConvolver& self = *static_cast<BaseConvolver*>(p);
656  boost::mutex::scoped_lock lock(self.activate_mutex);
657  if (start) {
658  if (!self.conv.get_buffersize()) {
659  start = false;
660  }
661  }
662  if (start == self.activated) {
663  return 0;
664  }
665  if (start) {
666  if (!self.start()) {
667  return -1;
668  }
669  self.update_conn = Glib::signal_timeout().connect(
670  sigc::mem_fun(self, &BaseConvolver::check_update_timeout), 200);
671  } else {
672  self.conv.stop_process();
673  }
674  self.activated = start;
675  return 0;
676 }
677 
679  int policy, priority;
680  engine.get_sched_priority(policy, priority);
681  return conv.start(policy, priority);
682 }
683 
684 /****************************************************************
685  ** class CabinetConvolver
686  */
687 
688 struct CabDesc {
689  int ir_count;
690  int ir_sr;
691  float ir_data[];
692 };
693 
694 template <int tab_size>
695 struct CabDesc_imp {
696  int ir_count;
697  int ir_sr;
698  float ir_data[tab_size];
699  operator CabDesc&() { return *(CabDesc*)this; }
700 };
701 
702 #include "gx_cabinet_data.cc"
703 
704 struct CabEntry {
705  const char *value_id;
706  const char *value_label;
708 } cab_table[] = {
709  { "4x12", N_("4x12"), &static_cast<CabDesc&>(cab_data_4x12) },
710  { "2x12", N_("2x12"), &static_cast<CabDesc&>(cab_data_2x12) },
711  { "1x12", N_("1x12"), &static_cast<CabDesc&>(cab_data_1x12) },
712  { "4x10", N_("4x10"), &static_cast<CabDesc&>(cab_data_4x10) },
713  { "2x10", N_("2x10"), &static_cast<CabDesc&>(cab_data_2x10) },
714  { "HighGain", N_("HighGain Style"), &static_cast<CabDesc&>(cab_data_HighGain) },
715  { "Twin", N_("Twin Style"), &static_cast<CabDesc&>(cab_data_Twin) },
716  { "Bassman", N_("Bassman Style"), &static_cast<CabDesc&>(cab_data_Bassman) },
717  { "Marshall", N_("Marshall Style"), &static_cast<CabDesc&>(cab_data_Marshall) },
718  { "AC-30", N_("AC-30 Style"), &static_cast<CabDesc&>(cab_data_AC30) },
719  { "Princeton", N_("Princeton Style"), &static_cast<CabDesc&>(cab_data_Princeton) },
720  { "A2", N_("A2 Style"), &static_cast<CabDesc&>(cab_data_A2) },
721  { "1x15", N_("1x15"), &static_cast<CabDesc&>(cab_data_1x15) },
722  { "Mesa Boogie", N_("Mesa Boogie Style"), &static_cast<CabDesc&>(cab_data_mesa) },
723  { "Briliant", N_("Briliant"), &static_cast<CabDesc&>(cab_data_briliant) },
724  { "Vitalize", N_("Vitalize"), &static_cast<CabDesc&>(cab_data_vitalize) },
725  { "Charisma", N_("Charisma"), &static_cast<CabDesc&>(cab_data_charisma) },
726 };
727 static const unsigned int cab_table_size = sizeof(cab_table) / sizeof(cab_table[0]);
728 
729 static CabEntry& getCabEntry(unsigned int n) {
730  if (n >= cab_table_size) {
731  n = cab_table_size - 1;
732  }
733  return cab_table[n];
734 }
735 
736 static const float no_sum = 1e10;
737 
738 #include "faust/cabinet_impulse_former.cc"
739 
740 static int cab_load_ui(const UiBuilder& builder, int format) {
741  if (format & UI_FORM_GLADE) {
742  builder.load_glade_file("cabinet_ui.glade");
743  return 0;
744  } else if (format & UI_FORM_STACK) {
745  builder.openHorizontalhideBox("");
746  builder.create_selector_no_caption("cab.select");
747  builder.closeBox();
748  builder.openVerticalBox("");
749  {
750  builder.openHorizontalBox("");
751  {
752  builder.insertSpacer();
753  builder.create_selector_no_caption("cab.select");
754  builder.create_small_rackknobr("cab.bass", "Bass");
755  builder.create_small_rackknobr("cab.treble", "Treble");
756  builder.create_mid_rackknob("cab.Level", "Level");
757  }
758  builder.closeBox();
759  }
760  builder.closeBox();
761  return 0;
762  } else {
763  return -1;
764  }
765 
766 }
767 
769  BaseConvolver(engine, sync, resamp),
770  current_cab(-1),
771  level(0),
772  cabinet(0),
773  bass(0),
774  treble(0),
775  sum(no_sum),
776  cab_names(new value_pair[cab_table_size+1]),
777  impf() {
778  for (unsigned int i = 0; i < cab_table_size; ++i) {
779  CabEntry& cab = getCabEntry(i);
780  cab_names[i].value_id = cab.value_id;
781  cab_names[i].value_label = cab.value_label;
782  }
783  cab_names[cab_table_size].value_id = 0;
784  cab_names[cab_table_size].value_label = 0;
785  id = "cab";
786  name = N_("Cabinet");
787  category = N_("Tone Control");
788  load_ui = cab_load_ui;
789  mono_audio = run_cab_conf;
790  register_params = register_cab;
791 }
792 
794  delete[] cab_names;
795 }
796 
797 bool CabinetConvolver::do_update() {
798  bool configure = cabinet_changed();
799  if (conv.is_runnable()) {
800  conv.set_not_runnable();
801  sync();
802  conv.stop_process();
803  }
804  CabDesc& cab = *getCabEntry(cabinet).data;
805  if (current_cab == -1) {
806  impf.init(cab.ir_sr);
807  }
808  float cab_irdata_c[cab.ir_count];
809  impf.clear_state_f();
810  impf.compute(cab.ir_count,cab.ir_data,cab_irdata_c);
811  while (!conv.checkstate());
812  if (configure) {
813  if (!conv.configure(cab.ir_count, cab_irdata_c, cab.ir_sr)) {
814  return false;
815  }
816  } else {
817  if (!conv.update(cab.ir_count, cab_irdata_c, cab.ir_sr)) {
818  return false;
819  }
820  }
821  update_cabinet();
822  update_sum();
823  return conv_start();
824 }
825 
826 bool CabinetConvolver::start(bool force) {
827  if (force) {
828  current_cab = -1;
829  }
830  if (cabinet_changed() || sum_changed()) {
831  return do_update();
832  } else {
833  while (!conv.checkstate());
834  if (!conv.is_runnable()) {
835  return conv_start();
836  }
837  return true;
838  }
839 }
840 
841 void CabinetConvolver::check_update() {
842  if (cabinet_changed() || sum_changed()) {
843  do_update();
844  }
845 }
846 
847 void CabinetConvolver::run_cab_conf(int count, float *input0, float *output0, PluginDef *p) {
848  CabinetConvolver& self = *static_cast<CabinetConvolver*>(p);
849  if (!self.conv.compute(count,output0)) {
851  }
852 }
853 
854 int CabinetConvolver::register_cab(const ParamReg& reg) {
855  CabinetConvolver& cab = *static_cast<CabinetConvolver*>(reg.plugin);
856  reg.registerIEnumVar("cab.select", "select", "B", "", cab.cab_names, &cab.cabinet, 0);
857  reg.registerVar("cab.Level", N_("Level"), "S", N_("Level"), &cab.level, 1.0, 0.5, 5.0, 0.5);
858  reg.registerVar("cab.bass", N_("Bass"), "S", N_("Bass"), &cab.bass, 0.0, -10.0, 10.0, 0.5);
859  reg.registerVar("cab.treble", N_("Treble"), "S", N_("Treble"), &cab.treble, 0.0, -10.0, 10.0, 0.5);
860  cab.impf.register_par(reg);
861  return 0;
862 }
863 
864 /****************************************************************
865  ** class PreampConvolver
866  */
867 
868 struct PreDesc {
869  int ir_count;
870  int ir_sr;
871  float ir_data[];
872 };
873 
874 template <int tab_size>
875 struct PreDesc_imp {
876  int ir_count;
877  int ir_sr;
878  float ir_data[tab_size];
879  operator PreDesc&() { return *(PreDesc*)this; }
880 };
881 
882 #include "gx_preamp_data.cc"
883 
884 struct PreEntry {
885  const char *value_id;
886  const char *value_label;
888 } pre_table[] = {
889  { "AC30", N_("AC30 Style"), &static_cast<PreDesc&>(pre_data_ac30) },
890  { "Bassman", N_("Bassman Style"), &static_cast<PreDesc&>(pre_data_bassman) },
891  { "Tube", N_("Tube Style"), &static_cast<PreDesc&>(pre_data_tube) },
892  { "Fender", N_("Fender Style"), &static_cast<PreDesc&>(pre_data_fender) },
893  { "JCM800", N_("JCM800 Style"), &static_cast<PreDesc&>(pre_data_jcm800) },
894  { "JTM45", N_("JTM45 Style"), &static_cast<PreDesc&>(pre_data_jtm45) },
895  { "Mesa Boogie", N_("Mesa Boogie Style"), &static_cast<PreDesc&>(pre_data_mesaboogie) },
896  { "Boutique", N_("Boutique Style"), &static_cast<PreDesc&>(pre_data_boutique) },
897  { "Ampeg", N_("Ampeg Style"), &static_cast<PreDesc&>(pre_data_ampeg) },
898  { "Rectifier", N_("Rectifier Style"), &static_cast<PreDesc&>(pre_data_rectifier) },
899 };
900 static const unsigned int pre_table_size = sizeof(pre_table) / sizeof(pre_table[0]);
901 
902 static PreEntry& getPreEntry(unsigned int n) {
903  if (n >= pre_table_size) {
904  n = pre_table_size - 1;
905  }
906  return pre_table[n];
907 }
908 
909 #include "faust/preamp_impulse_former.cc"
910 
911 static int pre_load_ui(const UiBuilder& builder, int format) {
912  if (format & UI_FORM_GLADE) {
913  builder.load_glade_file("ampimpulse_ui.glade");
914  return 0;
915  } else if (format & UI_FORM_STACK) {
916  builder.openHorizontalhideBox("");
917  builder.create_selector_no_caption("pre.select");
918  builder.closeBox();
919  builder.openVerticalBox("");
920  {
921  builder.openHorizontalBox("");
922  {
923  builder.insertSpacer();
924  builder.create_selector_no_caption("pre.select");
925  builder.create_small_rackknobr("pre.bass", "Bass");
926  builder.create_small_rackknobr("pre.treble", "Treble");
927  builder.create_mid_rackknob("pre.Level", "Level");
928  }
929  builder.closeBox();
930  }
931  builder.closeBox();
932  return 0;
933  } else {
934  return -1;
935  }
936 
937 }
938 
940  BaseConvolver(engine, sync, resamp),
941  current_pre(-1),
942  level(0),
943  preamp(0),
944  bass(0),
945  treble(0),
946  sum(no_sum),
947  pre_names(new value_pair[pre_table_size+1]),
948  impf() {
949  for (unsigned int i = 0; i < pre_table_size; ++i) {
950  PreEntry& pre = getPreEntry(i);
951  pre_names[i].value_id = pre.value_id;
952  pre_names[i].value_label = pre.value_label;
953  }
954  pre_names[pre_table_size].value_id = 0;
955  pre_names[pre_table_size].value_label = 0;
956  id = "pre";
957  name = N_("Amp Impulse");
958  category = N_("Tone Control");
959  load_ui = pre_load_ui;
960  mono_audio = run_pre_conf;
961  register_params = register_pre;
962 }
963 
965  delete[] pre_names;
966 }
967 
968 bool PreampConvolver::do_update() {
969  bool configure = preamp_changed();
970  if (conv.is_runnable()) {
971  conv.set_not_runnable();
972  sync();
973  conv.stop_process();
974  }
975  PreDesc& pre = *getPreEntry(preamp).data;
976  if (current_pre == -1) {
977  impf.init(pre.ir_sr);
978  }
979  float pre_irdata_c[pre.ir_count];
980  impf.clear_state_f();
981  impf.compute(pre.ir_count,pre.ir_data,pre_irdata_c);
982  while (!conv.checkstate());
983  if (configure) {
984  if (!conv.configure(pre.ir_count, pre_irdata_c, pre.ir_sr)) {
985  return false;
986  }
987  } else {
988  if (!conv.update(pre.ir_count, pre_irdata_c, pre.ir_sr)) {
989  return false;
990  }
991  }
992  update_preamp();
993  update_sum();
994  return conv_start();
995 }
996 
997 bool PreampConvolver::start(bool force) {
998  if (force) {
999  current_pre = -1;
1000  }
1001  if (preamp_changed() || sum_changed()) {
1002  return do_update();
1003  } else {
1004  while (!conv.checkstate());
1005  if (!conv.is_runnable()) {
1006  return conv_start();
1007  }
1008  return true;
1009  }
1010 }
1011 
1012 void PreampConvolver::check_update() {
1013  if (preamp_changed() || sum_changed()) {
1014  do_update();
1015  }
1016 }
1017 
1018 void PreampConvolver::run_pre_conf(int count, float *input0, float *output0, PluginDef *p) {
1019  PreampConvolver& self = *static_cast<PreampConvolver*>(p);
1020  if (!self.conv.compute(count, output0)) {
1022  }
1023 }
1024 
1025 int PreampConvolver::register_pre(const ParamReg& reg) {
1026  PreampConvolver& pre = *static_cast<PreampConvolver*>(reg.plugin);
1027  reg.registerIEnumVar("pre.select", "select", "B", "", pre.pre_names, &pre.preamp, 0);
1028  reg.registerVar("pre.Level", N_("Level"), "S", N_("Level"), &pre.level, 1.0, 0.1, 2.1, 0.1);
1029  reg.registerVar("pre.bass", N_("Bass"), "S", N_("Bass"), &pre.bass, 0.0, -10.0, 10.0, 0.5);
1030  reg.registerVar("pre.treble", N_("Treble"), "S", N_("Treble"), &pre.treble, 0.0, -10.0, 10.0, 0.5);
1031  pre.impf.register_par(reg);
1032  return 0;
1033 }
1034 
1035 /****************************************************************
1036  ** class ContrastConvolver
1037  */
1038 
1039 #include "faust/presence_level.cc"
1040 
1042  BaseConvolver(engine, sync, resamp),
1043  level(0),
1044  sum(no_sum),
1045  presl() {
1046  id = "con";
1047  name = N_("Contrast convolver");
1048  mono_audio = run_contrast;
1049  register_params = register_con;
1050 }
1051 
1053 }
1054 
1055 bool ContrastConvolver::do_update() {
1056  bool configure = (sum == no_sum);
1057  if (conv.is_runnable()) {
1058  conv.set_not_runnable();
1059  sync();
1060  conv.stop_process();
1061  }
1062  if (configure) {
1063  presl.init(contrast_ir_desc.ir_sr);
1064  }
1065  float contrast_irdata_c[contrast_ir_desc.ir_count];
1066  presl.compute(contrast_ir_desc.ir_count,contrast_ir_desc.ir_data,contrast_irdata_c);
1067  while (!conv.checkstate());
1068  if (configure) {
1069  if (!conv.configure(contrast_ir_desc.ir_count, contrast_irdata_c, contrast_ir_desc.ir_sr)) {
1070  return false;
1071  }
1072  } else {
1073  if (!conv.update(contrast_ir_desc.ir_count, contrast_irdata_c, contrast_ir_desc.ir_sr)) {
1074  return false;
1075  }
1076  }
1077  update_sum();
1078  return conv_start();
1079 }
1080 
1081 bool ContrastConvolver::start(bool force) {
1082  if (force) {
1083  sum = no_sum;
1084  }
1085  if (sum_changed()) {
1086  return do_update();
1087  } else {
1088  while (!conv.checkstate());
1089  if (!conv.is_runnable()) {
1090  return conv_start();
1091  }
1092  return true;
1093  }
1094 }
1095 
1096 void ContrastConvolver::check_update() {
1097  if (sum_changed()) {
1098  do_update();
1099  }
1100 }
1101 
1102 int ContrastConvolver::register_con(const ParamReg& reg) {
1103  ContrastConvolver& self = *static_cast<ContrastConvolver*>(reg.plugin);
1104  reg.registerVar("con.Level", "", "S", "", &self.level, 1.0, 0.5, 5.0, 0.5);
1105  self.presl.register_par(reg);
1106  return 0;
1107 }
1108 
1109 void ContrastConvolver::run_contrast(int count, float *input0, float *output0, PluginDef *p) {
1110  ContrastConvolver& self = *static_cast<ContrastConvolver*>(p);
1111  if (!self.conv.compute(count,output0)) {
1112  self.engine.overload(EngineControl::ov_Convolver, "contrast");
1113  }
1114 }
1115 
1116 /****************************************************************
1117  ** class smbPitchShift
1118  */
1119 
1120 #include "gx_livelooper.cc"
1121 
1122 /****************************************************************
1123  ** class SCapture
1124  */
1125 
1126 #include "gx_record.cc"
1127 
1128 
1129 /****************************************************************************
1130 *
1131 * NAME: smbPitchShift.cpp
1132 * VERSION: 1.2
1133 * HOME URL: http://www.dspdimension.com
1134 * KNOWN BUGS: none
1135 *
1136 *
1137 * COPYRIGHT 1999-2009 Stephan M. Bernsee <smb [AT] dspdimension [DOT] com>
1138 *
1139 * Modified for guitarix by Hermann Meyer 2014
1140 *
1141 * The Wide Open License (WOL)
1142 *
1143 * Permission to use, copy, modify, distribute and sell this software and its
1144 * documentation for any purpose is hereby granted without fee, provided that
1145 * the above copyright notice and this license appear in all source copies.
1146 * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF
1147 * ANY KIND. See http://www.dspguru.com/wol.htm for more information.
1148 *
1149 *****************************************************************************/
1150 
1151 bool smbPitchShift::setParameters(int sampleRate_)
1152 {
1153  numSampsToProcess = int(engine.get_buffersize());
1154  fftFrameSize = numSampsToProcess/4;
1155  sampleRate = int(sampleRate_);
1156  assert(sampleRate>0);
1157  osamp = 8;
1158  osamp1 = 1./osamp;
1159  osamp2 = 2.*M_PI*osamp1;
1160  mpi = (1./(2.*M_PI)) * osamp;
1161  mpi1 = 1./M_PI;
1162  fpb = 0;
1163  expect = 0;
1164  hanning = 0;
1165  hanningd = 0;
1166  resampin = 0;
1167  resampout = 0;
1168  indata2 = 0;
1169  resamp.setup(sampleRate,4);
1170  gRover = inFifoLatency;
1171  return true;
1172 }
1173 
1174 smbPitchShift::smbPitchShift(ParamMap& param_, EngineControl& engine_, sigc::slot<void> sync_):
1175  PluginDef(),
1176  engine(engine_),
1177  mem_allocated(false),
1178  sync(sync_),
1179  ready(false),
1180  param(param_),
1181  ftPlanForward(0),
1182  ftPlanInverse(0),
1183  plugin() {
1184  memset(gInFIFO, 0, MAX_FRAME_LENGTH*sizeof(float));
1185  memset(gOutFIFO, 0, MAX_FRAME_LENGTH*sizeof(float));
1186  memset(gLastPhase, 0, (MAX_FRAME_LENGTH/2+1)*sizeof(float));
1187  memset(gSumPhase, 0, (MAX_FRAME_LENGTH/2+1)*sizeof(float));
1188  memset(gOutputAccum, 0, 2*MAX_FRAME_LENGTH*sizeof(float));
1189  memset(gAnaFreq, 0, MAX_FRAME_LENGTH*sizeof(float));
1190  memset(gAnaMagn, 0, MAX_FRAME_LENGTH*sizeof(float));
1192  id = "smbPitchShift";
1193  name = N_("Detune");
1194  groups = 0;
1195  description = N_("detune and pitch shift up"); // description (tooltip)
1196  category = N_("Misc"); // category
1197  mono_audio = compute_static;
1198  stereo_audio = 0;
1199  set_samplerate = init;
1200  activate_plugin = activate_static;
1201  register_params = registerparam;
1202  delete_instance = del_instance;
1203  load_ui = load_ui_f_static;
1204  plugin = this;
1205  engine.signal_buffersize_change().connect(
1206  sigc::mem_fun(*this, &smbPitchShift::change_buffersize));
1207 }
1208 
1209 void smbPitchShift::init(unsigned int samplingFreq, PluginDef *plugin) {
1210  static_cast<smbPitchShift*>(plugin)->setParameters(samplingFreq);
1211 
1212 }
1213 
1214 void smbPitchShift::clear_state()
1215 {
1216  stepSize = fftFrameSize/osamp;
1217  freqPerBin = (double)(sampleRate/4)/(double)fftFrameSize;
1218  freqPerBin1 = (1/freqPerBin)*osamp2;
1219  freqPerBin2 = freqPerBin*mpi;
1220  expct = 2.*M_PI*(double)stepSize/(double)fftFrameSize;
1221  inFifoLatency = fftFrameSize-stepSize;
1222  fftFrameSize3 = 2. * (1./ ((double)(fftFrameSize2)*osamp));
1223  fftFrameSize4 = 1./(double)fftFrameSize;
1224  ai = 0;
1225  aio = 0;
1226  ii = 0;
1227  tone =0;
1228  memset(gInFIFO, 0, MAX_FRAME_LENGTH*sizeof(float));
1229  memset(gOutFIFO, 0, MAX_FRAME_LENGTH*sizeof(float));
1230  memset(gLastPhase, 0, (MAX_FRAME_LENGTH/2+1)*sizeof(float));
1231  memset(gSumPhase, 0, (MAX_FRAME_LENGTH/2+1)*sizeof(float));
1232  memset(gOutputAccum, 0, 2*MAX_FRAME_LENGTH*sizeof(float));
1233  memset(gAnaFreq, 0, MAX_FRAME_LENGTH*sizeof(float));
1234  memset(gAnaMagn, 0, MAX_FRAME_LENGTH*sizeof(float));
1235  for (k = 0; k < fftFrameSize2;k++) {
1236  fpb[k] = (double)k*freqPerBin;
1237  }
1238  for (k = 0; k < fftFrameSize2;k++) {
1239  expect[k] = (double)k*expct;
1240  }
1241  for (k = 0; k < fftFrameSize;k++) {
1242  hanning[k] = 0.5*(1-cos(2.*M_PI*(double)k/((double)fftFrameSize)));
1243  }
1244  for (k = 0; k < fftFrameSize;k++) {
1245  hanningd[k] = 0.5*(1-cos(2.*M_PI*(double)k * fftFrameSize4)) * fftFrameSize3;
1246  }
1247  for (k = 0; k < fftFrameSize;k++) {
1248  resampin[k] = 0.0;
1249  }
1250  for (k = 0; k < fftFrameSize;k++) {
1251  resampin2[k] = 0.0;
1252  }
1253  for (k = 0; k < fftFrameSize*4;k++) {
1254  resampout[k] = 0.0;
1255  }
1256  for (k = 0; k < fftFrameSize*4;k++) {
1257  indata2[k] = 0.0;
1258  }
1259  gRover = inFifoLatency;
1260  mem_allocated = true;
1261  ready = true;
1262 }
1263 
1264 void smbPitchShift::mem_alloc()
1265 {
1266  numSampsToProcess = int(engine.get_buffersize());
1267  assert(numSampsToProcess>0);
1268  numSampsToResamp = numSampsToProcess/4;
1269  sampleRate = int(engine.get_samplerate());
1270  assert(sampleRate>0);
1271 
1272  switch(latency) {
1273  case(0):
1274  if (numSampsToProcess <= 2048) {
1275  fftFrameSize = 512 ;
1276  } else {
1277  fftFrameSize = numSampsToProcess*0.25 ;
1278  }
1279  break;
1280  case(1):
1281  fftFrameSize = numSampsToProcess;
1282  break;
1283  case(2):
1284  fftFrameSize = numSampsToProcess*0.25;
1285  break;
1286  default:
1287  if (numSampsToProcess <= 2048) {
1288  fftFrameSize = 512 ;
1289  } else {
1290  fftFrameSize = numSampsToProcess*0.25 ;
1291  }
1292  break;
1293  }
1294  fftFrameSize2 = fftFrameSize/2;
1295 
1296  try {
1297  //create FFTW plan
1298  ftPlanForward = fftwf_plan_dft_1d(fftFrameSize, fftw_in, fftw_out, FFTW_FORWARD, FFTW_ESTIMATE);
1299  ftPlanInverse = fftwf_plan_dft_1d(fftFrameSize, fftw_in, fftw_out, FFTW_BACKWARD, FFTW_ESTIMATE);
1300  // alloc buffers
1301  fpb = new float[fftFrameSize2];
1302  expect = new float[fftFrameSize2];
1303  hanning = new float[fftFrameSize];
1304  hanningd = new float[fftFrameSize];
1305  resampin = new float[fftFrameSize];
1306  resampin2 = new float[fftFrameSize];
1307  resampout = new float[fftFrameSize*4];
1308  indata2 = new float[fftFrameSize*4];
1309  } catch(...) {
1310  gx_print_error("detune", "cant allocate memory pool");
1311  return;
1312  }
1313  clear_state();
1314 }
1315 
1316 void smbPitchShift::mem_free()
1317 {
1318  ready = false;
1319  mem_allocated = false;
1320  if (fpb) { delete fpb; fpb = 0; }
1321  if (expect) { delete expect; expect = 0; }
1322  if (hanning) { delete hanning; hanning = 0; }
1323  if (hanningd) { delete hanningd; hanningd = 0; }
1324  if (resampin) { delete resampin; resampin = 0; }
1325  if (resampin2) { delete resampin2; resampin2 = 0; }
1326  if (resampout) { delete resampout; resampout = 0; }
1327  if (indata2) { delete indata2; indata2 = 0; }
1328  if (ftPlanForward)
1329  {fftwf_destroy_plan(ftPlanForward);ftPlanForward = 0; }
1330  if (ftPlanInverse)
1331  { fftwf_destroy_plan(ftPlanInverse);ftPlanInverse = 0; }
1332 }
1333 
1334 int smbPitchShift::activate(bool start)
1335 {
1336  if (start) {
1337  if (!mem_allocated) {
1338  mem_alloc();
1339  }
1340  } else if (mem_allocated) {
1341  mem_free();
1342  }
1343  return 0;
1344 }
1345 
1346 void smbPitchShift::change_buffersize(unsigned int size)
1347 {
1348  sync();
1349  ready = false;
1350  if (mem_allocated) {
1351  mem_free();
1352  mem_alloc();
1353  }
1354 }
1355 
1356 void smbPitchShift::change_latency()
1357 {
1358  sync();
1359  ready = false;
1360  if (mem_allocated) {
1361  mem_free();
1362  mem_alloc();
1363  }
1364 }
1365 
1367 {
1368  if (mem_allocated) {
1369  mem_free();
1370  }
1371 }
1372 
1373 // -----------------------------------------------------------------------------------------------------------------
1374 void __rt_func smbPitchShift::compute_static(int count, float *input0, float *output0, PluginDef *p)
1375 {
1376  static_cast<smbPitchShift*>(p)->PitchShift(count, input0, output0);
1377 }
1378 
1379 
1380 void always_inline smbPitchShift::PitchShift(int count, float *indata, float *outdata)
1381 {
1382 
1383  if (!ready || count != numSampsToProcess) {
1384  if (indata != outdata)
1385  {
1386  memcpy(outdata,indata,count*sizeof(float));
1387  }
1388  return;
1389  }
1390 
1391  resamp.down(numSampsToResamp,indata,resampin);
1392  double fSlow0 = (0.01 * wet);
1393  double fSlow1 = (0.01 * dry);
1394 
1395  // collect data for latency compensation
1396  for (i = 0; i < count; i++){
1397  indata2[ii] = indata[i];
1398  ii++;
1399  }
1400  // collect data for fft
1401  for (i = 0; i < numSampsToResamp; i++){
1402  resampin2[ai] = resampin[i];
1403  ai++;
1404  }
1405  // now we have enough data
1406  if (ai>=fftFrameSize) {
1407  ai = 0;
1408  ii = 0;
1409  switch(octave) {
1410  case(0):
1411  tone =0;
1412  break;
1413  case(1):
1414  tone =12;
1415  break;
1416  case(2):
1417  tone =-12;
1418  break;
1419  default:
1420  tone =0;
1421  break;
1422  }
1423  float pitchShift = pow(2., (semitones+tone)*0.0833333333);
1424  /* main processing loop */
1425  for (i = 0; i < fftFrameSize; i++){
1426 
1427  /* As long as we have not yet collected enough data just read in */
1428  float fTemp = resampin2[i];
1429  gInFIFO[gRover] = fTemp;
1430  resampin2[i] = gOutFIFO[gRover-inFifoLatency];
1431  gRover++;
1432 
1433  /* now we have enough data for processing */
1434  if (gRover >= fftFrameSize) {
1435  gRover = inFifoLatency;
1436 
1437  /* do windowing and re,im interleave */
1438  for (k = 0; k < fftFrameSize;k++) {
1439  fftw_in[k][0] = gInFIFO[k] * hanning[k];
1440  fftw_in[k][1] = 0.0;
1441  }
1442 
1443 
1444  /* ***************** ANALYSIS ******************* */
1445  /* do transform */
1446  fftwf_execute(ftPlanForward);
1447 
1448  /* this is the analysis step */
1449  for (k = 0; k < fftFrameSize2; k++) {
1450 
1451  /* de-interlace FFT buffer */
1452  real = fftw_out[k][0];
1453  imag = fftw_out[k][1];
1454 
1455  /* compute magnitude and phase */
1456  magn = 2.*sqrt(real*real + imag*imag);
1457  phase = atan2(imag,real);
1458 
1459  /* compute phase difference */
1460  tmp = phase - gLastPhase[k];
1461  gLastPhase[k] = phase;
1462 
1463  /* subtract expected phase difference */
1464  tmp -= expect[k];
1465 
1466  /* map delta phase into +/- Pi interval */
1467  qpd = tmp*mpi1;
1468  if (qpd >= 0) qpd += qpd&1;
1469  else qpd -= qpd&1;
1470  tmp -= M_PI*(double)qpd;
1471 
1472  /* get deviation from bin frequency from the +/- Pi interval */
1473  /* compute the k-th partials' true frequency */
1474  tmp = fpb[k] + tmp*freqPerBin2;
1475 
1476  /* store magnitude and true frequency in analysis arrays */
1477  gAnaMagn[k] = magn;
1478  gAnaFreq[k] = tmp;
1479 
1480  }
1481 
1482  /* ***************** PROCESSING ******************* */
1483  /* this does the actual pitch shifting */
1484  memset(gSynMagn, 0, fftFrameSize*sizeof(float));
1485  memset(gSynFreq, 0, fftFrameSize*sizeof(float));
1486  for (k = 1; k < fftFrameSize2-2; k++) {
1487  index = k*pitchShift;
1488  if (index < fftFrameSize2) {
1489  if (index < fftFrameSize2*0.20)
1490  gSynMagn[index] += gAnaMagn[k]*a;
1491  else if (index < fftFrameSize2*0.45)
1492  gSynMagn[index] += gAnaMagn[k]*b;
1493  else if (index < fftFrameSize2*0.667)
1494  gSynMagn[index] += gAnaMagn[k]*c;
1495  else
1496  gSynMagn[index] += gAnaMagn[k]*d;
1497  gSynFreq[index] = gAnaFreq[k] * pitchShift;
1498  }
1499  }
1500 
1501  /* ***************** SYNTHESIS ******************* */
1502  /* this is the synthesis step */
1503  for (k = 0; k < fftFrameSize2; k++) {
1504 
1505  /* get magnitude and true frequency from synthesis arrays */
1506  magn = gSynMagn[k];
1507  //tmp = gSynFreq[k];
1508 
1509  /* subtract bin mid frequency */
1510  /* get bin deviation from freq deviation */
1511  /* take osamp into account */
1512  /* add the overlap phase advance back in */
1513  tmp = ((gSynFreq[k] - fpb[k]) * freqPerBin1) + expect[k];
1514 
1515  /* accumulate delta phase to get bin phase */
1516  gSumPhase[k] += tmp;
1517  phase = gSumPhase[k];
1518  if (magn == 0.0) continue;
1519 
1520  /* get real and imag part and re-interleave */
1521  fftw_in[k][0] = magn * cos (phase);
1522  fftw_in[k][1] = magn * sin (phase);
1523  }
1524 
1525  /* do inverse transform */
1526  fftwf_execute(ftPlanInverse);
1527  /* do windowing and add to output accumulator */
1528  for(k=0; k < fftFrameSize; k++) {
1529  gOutputAccum[k] += hanningd[k] * fftw_out[ k][0] ;
1530  }
1531  for (k = 0; k < stepSize; k++) gOutFIFO[k] = gOutputAccum[k];
1532 
1533  /* shift accumulator */
1534  memmove(gOutputAccum, gOutputAccum+stepSize, fftFrameSize*sizeof(float));
1535 
1536  /* move input FIFO */
1537  for (k = 0; k < inFifoLatency; k++) gInFIFO[k] = gInFIFO[k+stepSize];
1538  }
1539  }
1540  resamp.up(fftFrameSize,resampin2,resampout);
1541  aio = 0;
1542  }
1543  if(l) {
1544  for (i = 0; i < count; i++){
1545  outdata[i] = ((fSlow0 * resampout[aio]) + (fSlow1 *indata2[aio]));
1546  aio++;
1547  }
1548  } else {
1549  for (i = 0; i < count; i++){
1550  outdata[i] = ((fSlow0 * resampout[aio]) + (fSlow1 *indata[i]));
1551  aio++;
1552  }
1553  }
1554 }
1555 
1556 int smbPitchShift::register_par(const ParamReg& reg)
1557 {
1558  reg.registerVar("smbPitchShift.semitone", N_("Detune"), "S", "", &semitones, 0.0, -12., 12., 0.1);
1559  static const value_pair octave_values[] = {{"unison"},{"octave up"},{"octave down"},{0}};
1560  reg.registerIEnumVar("smbPitchShift.octave",N_("add harmonics"),"B",N_("add harmonics"),octave_values,&octave, 0);
1561  static const value_pair latency_values[] = {{"latency "},{"compensate"},{0}};
1562  reg.registerEnumVar("smbPitchShift.l",N_("compensate latency"),"S",N_("compensate latency"),latency_values,&l, 0.0f, 0.0f, 1.0f, 1.0f);
1563  static const value_pair latency_set[] = {{"high quality"},{"low quality"},{"realtime"},{0}};
1564  reg.registerIEnumVar("smbPitchShift.latency",N_("latency settings"),"B",N_("latency settings"),latency_set,&latency, 0);
1565  reg.registerVar("smbPitchShift.wet", N_("Wet"), "S", N_("Wet amount"), &wet, 50.0, 0.0, 100.0, 1);
1566  reg.registerVar("smbPitchShift.dry", N_("Dry"), "S", N_("Dry amount"), &dry, 50.0, 0.0, 100.0, 1);
1567  reg.registerVar("smbPitchShift.a", N_("low"), "S", N_("Sub"), &a, 1.0, 0.0, 2.0, 0.01);
1568  reg.registerVar("smbPitchShift.b", N_("middle low"), "S", N_("Low"), &b, 1.0, 0.0, 2.0, 0.01);
1569  reg.registerVar("smbPitchShift.c", N_("middle treble"), "S", N_("Mid"), &c, 1.0, 0.0, 2.0, 0.01);
1570  reg.registerVar("smbPitchShift.d", N_("treble"), "S", N_("Hi"), &d, 1.0, 0.0, 2.0, 0.01);
1571  param["smbPitchShift.latency"].signal_changed_int().connect(
1572  sigc::hide(sigc::mem_fun(this, &smbPitchShift::change_latency)));
1573  return 0;
1574 }
1575 
1576 int smbPitchShift::registerparam(const ParamReg& reg)
1577 {
1578  return static_cast<smbPitchShift*>(reg.plugin)->register_par(reg);
1579 }
1580 
1581 int smbPitchShift::load_ui_f(const UiBuilder& b, int form)
1582 {
1583  if (form & UI_FORM_GLADE) {
1584  b.load_glade_file("gx_detune_ui.glade");
1585  return 0;
1586  }
1587  if (form & UI_FORM_STACK) {
1588  b.openHorizontalhideBox("");
1589  {
1590  b.create_master_slider("smbPitchShift.semitone",N_("Detune"));
1591  }
1592  b.closeBox();
1593  b.openVerticalBox("");
1594  {
1595  b.openHorizontalBox("");
1596  {
1597  b.openVerticalBox("");
1598  {
1599  b.insertSpacer();
1600  b.create_selector_no_caption("smbPitchShift.octave");
1601  b.create_selector_no_caption("smbPitchShift.l");
1602  b.create_selector_no_caption("smbPitchShift.latency");
1603  b.insertSpacer();
1604  }
1605  b.closeBox();
1606  b.create_mid_rackknob("smbPitchShift.semitone",N_("Detune"));
1607  b.create_small_rackknobr("smbPitchShift.dry",N_("Dry"));
1608  b.create_small_rackknobr("smbPitchShift.wet",N_("Wet"));
1609  }
1610  b.closeBox();
1611  b.insertSpacer();
1612  b.openHorizontalBox("");
1613  {
1615  b.create_small_rackknobr("smbPitchShift.a",N_("Lo"));
1617  b.create_small_rackknobr("smbPitchShift.b",N_("LoMid"));
1619  b.create_small_rackknobr("smbPitchShift.c",N_("HiMid"));
1621  b.create_small_rackknobr("smbPitchShift.d",N_("Hi"));
1622  }
1623  b.closeBox();
1624  }
1625  b.closeBox();
1626  return 0;
1627  }
1628  return -1;
1629 }
1630 
1631 int smbPitchShift::activate_static(bool start, PluginDef *p)
1632 {
1633  return static_cast<smbPitchShift*>(p)->activate(start);
1634 }
1635 
1636 int smbPitchShift::load_ui_f_static(const UiBuilder& b, int form)
1637 {
1638  return static_cast<smbPitchShift*>(b.plugin)->load_ui_f(b, form);
1639 }
1640 
1641 void smbPitchShift::del_instance(PluginDef *p)
1642 {
1643  delete static_cast<smbPitchShift*>(p);
1644 }
1645 
1646 
1647 } // namespace gx_engine
#define always_inline
void write_kv(const char *key, float v)
Definition: gx_json.h:81
static void init(unsigned int samplingFreq, PluginDef *p)
CmdConnection::msg_type start
Definition: jsonrpc.cpp:255
void begin_array(bool nl=false)
Definition: gx_json.cpp:184
void get_sched_priority(int &policy, int &priority, int prio_dim=0)
void up(int count, float *input, float *output)
void(* insertSpacer)()
Definition: gx_plugin.h:78
bool set(const GxJConvSettings &val) const
float sqrf(float x)
BasicOptions & get_options()
Definition: gx_system.h:509
ParameterV< GxJConvSettings > JConvParameter
PluginDef * plugin
Definition: gx_plugin.h:64
void end_array(bool nl=false)
Definition: gx_json.cpp:192
static int activate(bool start, PluginDef *pdef)
virtual void overload(OverloadType tp, const char *reason)=0
virtual void writeJSON(gx_system::JsonWriter &jw) const
struct gx_engine::CabEntry cab_table[]
const char * value_id
Definition: gx_plugin.h:118
PluginDef * plugin
Definition: gx_plugin.h:123
void set_pdef(PluginDef *p)
const PrefixConverter & get_IR_prefixmap() const
Definition: gx_system.h:378
#define N_(String)
const char * name
Definition: gx_plugin.h:186
#define __rt_func
Definition: gx_compiler.h:4
#define UI_LABEL_INVERSE
Definition: gx_plugin.h:45
float *(* registerVar)(const char *id, const char *name, const char *tp, const char *tooltip, float *var, float val, float low, float up, float step)
Definition: gx_plugin.h:124
void(* registerEnumVar)(const char *id, const char *name, const char *tp, const char *tooltip, const value_pair *values, float *var, float val, float low, float up, float step)
Definition: gx_plugin.h:132
#define UI_FORM_GLADE
Definition: gx_plugin.h:61
const char * description
Definition: gx_plugin.h:189
ParameterV(const string &id, ConvolverAdapter &conv, GxJConvSettings *v)
void change_buffersize(unsigned int size)
void(* closeBox)()
Definition: gx_plugin.h:77
void change_buffersize(unsigned int)
void write_key(const char *p, bool nl=false)
Definition: gx_json.cpp:200
#define M_PI
void set_on_off(bool v) const
const char ** groups
Definition: gx_plugin.h:187
void(* load_glade_file)(const char *fname)
Definition: gx_plugin.h:66
bool find_dir(std::string *d, const std::string &filename) const
Definition: gx_system.cpp:264
CabDesc * data
const char * category
Definition: gx_plugin.h:190
virtual void readJSON_value(gx_system::JsonParser &jp)
void(* registerIEnumVar)(const char *id, const char *name, const char *tp, const char *tooltip, const value_pair *values, int *var, int val)
Definition: gx_plugin.h:138
deletefunc delete_instance
Definition: gx_plugin.h:204
virtual bool start(bool force=false)=0
void gx_print_error(const char *, const std::string &)
Definition: gx_logging.cpp:166
bool read_kv(const char *key, float &v)
Definition: gx_json.cpp:511
ConvolverMonoAdapter(EngineControl &engine, sigc::slot< void > sync, ParamMap &param)
smbPitchShift(ParamMap &param_, EngineControl &engine, sigc::slot< void > sync)
std::string getFullIRPath() const
const char * value_id
CabinetConvolver(EngineControl &engine, sigc::slot< void > sync, gx_resample::BufferResampler &resamp)
#define PLUGINDEF_VERSION
Definition: gx_plugin.h:179
void(* openHorizontalBox)(const char *label)
Definition: gx_plugin.h:71
registerfunc register_params
Definition: gx_plugin.h:200
PreampConvolver(EngineControl &engine, sigc::slot< void > sync, gx_resample::BufferResampler &resamp)
static PluginDef outputgate
const char * id
Definition: gx_plugin.h:185
virtual void serializeJSON(gx_system::JsonWriter &jw)
const PathList & get_IR_pathlist() const
Definition: gx_system.h:377
const char * value_label
Definition: gx_plugin.h:119
BaseConvolver(EngineControl &engine, sigc::slot< void > sync, gx_resample::BufferResampler &resamp)
void begin_object(bool nl=false)
Definition: gx_json.cpp:168
void(* create_small_rackknobr)(const char *id, const char *label)
Definition: gx_plugin.h:98
void down(int count, float *input, float *output)
std::string replace_symbol(const std::string &dir) const
Definition: gx_system.cpp:287
void(* create_mid_rackknob)(const char *id, const char *label)
Definition: gx_plugin.h:103
int flags
Definition: gx_plugin.h:183
const Gainline & getGainline() const
#define MAX_FRAME_LENGTH
ContrastConvolver(EngineControl &engine, sigc::slot< void > sync, gx_resample::BufferResampler &resamp)
#define UI_FORM_STACK
Definition: gx_plugin.h:60
const char * value_id
PreDesc * data
void gx_print_warning(const char *, const std::string &)
Definition: gx_logging.cpp:161
void(* openHorizontalhideBox)(const char *label)
Definition: gx_plugin.h:72
ConvolverAdapter(EngineControl &engine, sigc::slot< void > sync, ParamMap &param)
activatefunc activate_plugin
Definition: gx_plugin.h:199
const char * value_label
virtual void check_update()=0
process_stereo_audio stereo_audio
Definition: gx_plugin.h:196
void readJSON(gx_system::JsonParser &jp)
void(* set_next_flags)(int flags)
Definition: gx_plugin.h:79
inifunc set_samplerate
Definition: gx_plugin.h:198
process_mono_audio mono_audio
Definition: gx_plugin.h:195
virtual void serializeJSON(gx_system::JsonWriter &jw)
GxJConvSettings & operator=(GxJConvSettings const &jcset)
string current_value() const
Definition: gx_json.h:143
float current_value_float()
Definition: gx_json.h:146
bool operator==(const GxJConvSettings &jcset) const
void writeJSON(gx_system::JsonWriter &w) const
token next(token expect=no_token)
Definition: gx_json.cpp:496
const char * value_label
void write(float v, bool nl=false)
Definition: gx_json.cpp:116
struct gx_engine::PreEntry pre_table[]
bool get_on_off() const
int version
Definition: gx_plugin.h:182
uiloader load_ui
Definition: gx_plugin.h:201
static ParameterV< GxJConvSettings > * insert_param(ParamMap &pmap, const string &id, ConvolverAdapter &conv, GxJConvSettings *v)
void(* create_master_slider)(const char *id, const char *label)
Definition: gx_plugin.h:84
void end_object(bool nl=false)
Definition: gx_json.cpp:176
ConvolverStereoAdapter(EngineControl &engine, sigc::slot< void > sync, ParamMap &param)
void(* create_selector_no_caption)(const char *id)
Definition: gx_plugin.h:88
void(* openVerticalBox)(const char *label)
Definition: gx_plugin.h:68
sigc::signal< void, unsigned int > & signal_buffersize_change()