Guitarix
gx_modulesequencer.h
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 #pragma once
22 
23 namespace gx_engine {
24 
25 /****************************************************************
26  ** class ModuleSelector
27  */
28 
29 class ModuleSelector {
30 protected:
32 public:
34  : seq(seq_) {}
35  virtual ~ModuleSelector() {}
36  virtual void set_module() = 0;
37 };
38 
39 
40 /****************************************************************
41  ** class ProcessingChainBase
42  ** members and methods accessed by the rt thread are marked RT
43  */
44 
45 class ProcessingChainBase {
46 public:
48 private:
49  sem_t sync_sem; // RT
50  list<Plugin*> to_release;
51  int ramp_value; // RT
52  int ramp_mode; // RT should be RampMode, but gcc 4.5 doesn't accept it for g_atomic_int_compare_and_exchange
53  volatile bool stopped;
54 protected:
55  int steps_up; // RT; >= 1
56  int steps_up_dead; // RT; >= 0
57  int steps_down; // RT; >= 1
58  list<Plugin*> modules;
59  inline void set_ramp_value(int n) { gx_system::atomic_set(&ramp_value, n); } // RT
60  inline void set_ramp_mode(RampMode n) { gx_system::atomic_set(&ramp_mode, n); } // RT
61  void try_set_ramp_mode(RampMode oldmode, RampMode newmode, int oldrv, int newrv); // RT
62 public:
66  return static_cast<RampMode>(gx_system::atomic_get(ramp_mode)); // RT
67  }
68  inline int get_ramp_value() { return gx_system::atomic_get(ramp_value); } // RT
69  void set_samplerate(int samplerate);
70  bool set_plugin_list(const list<Plugin*> &p);
71  void clear_module_states();
72  inline void post_rt_finished() { // RT
73  int val;
74  sem_getvalue(&sync_sem, &val);
75  if (val == 0) {
76  sem_post(&sync_sem);
77  }
78  }
79  bool wait_rt_finished();
80  void set_latch();
82  void sync() { set_latch(); wait_latch(); }
83  inline bool check_release() { return !to_release.empty(); }
84  void release();
86  void start_ramp_up();
87  void start_ramp_down();
89  inline bool is_down_dead() { return get_ramp_mode() == ramp_mode_down_dead; }
90  void set_stopped(bool v);
91  bool is_stopped() { return stopped; }
92 #ifndef NDEBUG
93  void print_chain_state(const char *title);
94 #endif
95 };
96 
97 
98 /****************************************************************
99  ** template class ThreadSafeChainPointer
100  ** members and methods accessed by the rt thread are marked RT
101  */
102 
103 template <class F>
105 private:
106  F *rack_order_ptr[2]; // RT
107  int size[2];
108  int current_index;
109  F *current_pointer;
110  void setsize(int n);
111  inline F get_audio(PluginDef *p);
112 protected:
114  inline F* get_rt_chain() { return gx_system::atomic_get(processing_pointer); } // RT
115 public:
118  inline void empty_chain(ParamMap& pmap) {
119  list<Plugin*> p;
120  if (set_plugin_list(p)) {
121  commit(true, pmap);
122  }
123  }
124  void commit(bool clear, ParamMap& pmap);
125 };
126 
127 typedef void (*monochainorder)(int count, float *output, float *output1,
128  PluginDef *plugin);
129 typedef void (*stereochainorder)(int count, float* input, float* input1,
130  float *output, float *output1, PluginDef *plugin);
131 
134  PluginDef *plugin;
135  monochain_data(monochainorder func_, PluginDef *plugin_): func(func_), plugin(plugin_) {}
137 };
138 
141  PluginDef *plugin;
142  stereochain_data(stereochainorder func_, PluginDef *plugin_): func(func_), plugin(plugin_) {}
143  stereochain_data(): func(), plugin() {}
144 };
145 
146 template <>
147 inline monochain_data ThreadSafeChainPointer<monochain_data>::get_audio(PluginDef *p)
148 {
149  return monochain_data(p->mono_audio, p);
150 }
151 
152 template <>
153 inline stereochain_data ThreadSafeChainPointer<stereochain_data>::get_audio(PluginDef *p)
154 {
155  return stereochain_data(p->stereo_audio, p);
156 }
157 
158 template <class F>
160  rack_order_ptr(),
161  size(),
162  current_index(0),
163  current_pointer(),
164  processing_pointer() {
165  setsize(1);
166  current_pointer[0].func = 0;
167  processing_pointer = current_pointer;
168  current_index = 1;
169  current_pointer = rack_order_ptr[1];
170 }
171 
172 template <class F>
174  delete[] rack_order_ptr[0];
175  delete[] rack_order_ptr[1];
176 }
177 
178 template <class F>
179 void ThreadSafeChainPointer<F>::setsize(int n)
180 {
181  if (n <= size[current_index]) {
182  return;
183  }
184  delete[] rack_order_ptr[current_index];
185  rack_order_ptr[current_index] = new F[n];
186  size[current_index] = n;
187  current_pointer = rack_order_ptr[current_index];
188 }
189 
190 template <class F>
191 void ThreadSafeChainPointer<F>::commit(bool clear, ParamMap& pmap) {
192  setsize(modules.size()+1); // leave one slot for 0 marker
193  int active_counter = 0;
194  for (list<Plugin*>::const_iterator p = modules.begin(); p != modules.end(); p++) {
195  PluginDef* pd = (*p)->get_pdef();
196  if (pd->activate_plugin) {
197  if (pd->activate_plugin(true, pd) != 0) {
198  (*p)->set_on_off(false);
199  continue;
200  }
201  } else if (pd->clear_state && clear) {
202  pd->clear_state(pd);
203  }
204  F f = get_audio(pd);
205  assert(f.func);
206  current_pointer[active_counter++] = f;
207  }
208  current_pointer[active_counter].func = 0;
209  gx_system::atomic_set(&processing_pointer, current_pointer);
210  set_latch();
211  current_index = (current_index+1) % 2;
212  current_pointer = rack_order_ptr[current_index];
213 }
214 
215 /****************************************************************
216  ** class MonoModuleChain, class StereoModuleChain
217  */
218 
219 class MonoModuleChain: public ThreadSafeChainPointer<monochain_data> {
220 public:
222  void process(int count, float *input, float *output);
223  inline void print() { printlist("Mono", modules); }
224 };
225 
226 class StereoModuleChain: public ThreadSafeChainPointer<stereochain_data> {
227 public:
229  void process(int count, float *input1, float *input2, float *output1, float *output2);
230  inline void print() { printlist("Stereo", modules); }
231 };
232 
233 
234 /****************************************************************
235  ** class EngineControl
236  */
237 
239 protected:
240  list<ModuleSelector*> selectors; // selectors that modify the on/off state of
241  // modules at start of reconfiguration
242  sigc::connection rack_changed; // idle signal for reconfiguration of module chains
243  ParamMap pmap;
244  int policy; // jack realtime policy,
245  int priority; // and priority, for internal modules
246  // signal anyone who needs to be synchronously notified
247  // BE CAREFUL: executed by RT thread (though not concurrent with audio
248  // modules, and timing requirements are relaxed)
249  sigc::signal<void, unsigned int> buffersize_change;
250  sigc::signal<void, unsigned int> samplerate_change;
251  unsigned int buffersize;
252  unsigned int samplerate;
253 public:
254  enum OverloadType { // type of overload condition
255  ov_User = 0x1, // idle thread probe starved
256  ov_Convolver = 0x2, // convolver overload
257  ov_XRun = 0x4 // jack audio loop overload
258  };
259  PluginList pluginlist;
260  EngineControl();
261  ~EngineControl();
262  void init(unsigned int samplerate, unsigned int buffersize,
263  int policy, int priority);
264  virtual void wait_ramp_down_finished() = 0;
265  virtual bool update_module_lists() = 0;
266  virtual void start_ramp_up() = 0;
267  virtual void start_ramp_down() = 0;
268  virtual void overload(OverloadType tp, const char *reason) = 0; // RT
269  void set_samplerate(unsigned int samplerate_);
270  unsigned int get_samplerate() { return samplerate; }
271  void set_buffersize(unsigned int buffersize_);
272  unsigned int get_buffersize() { return buffersize; }
273  virtual void set_rack_changed() = 0;
274  void clear_rack_changed();
275  bool get_rack_changed();
276  sigc::signal<void, unsigned int>& signal_buffersize_change() { return buffersize_change; }
277  sigc::signal<void, unsigned int>& signal_samplerate_change() { return samplerate_change; }
278  void add_selector(ModuleSelector& sel);
279  void registerParameter(ParameterGroups& groups);
280  void get_sched_priority(int &policy, int &priority, int prio_dim = 0);
281  ParamMap& get_param() { return pmap; }
282 };
283 
284 
285 /****************************************************************
286  ** class ModuleSequencer
287  */
288 
289 enum GxEngineState { // engine states set by user (ModuleSequencer set_state/get_state)
290  kEngineOff = 0, // mute, no output (but tuner or something might run)
291  kEngineOn = 1, // normal operation
292  kEngineBypass = 2 // just some balance or level control
293 };
294 
295 
297 protected:
298  int audio_mode; // GxEngineState coded as PGN_MODE_XX flags
299  boost::mutex stateflags_mutex;
300  int stateflags;
301  sigc::signal<void, GxEngineState> state_change;
302  Glib::Dispatcher overload_detected;
303  const char *overload_reason; // name of unit which detected overload
304  int ov_disabled; // bitmask of OverloadType
305  static int sporadic_interval; // seconds; overload if at least 2 events in the timespan
306 protected:
307  void check_overload();
308 public:
309  MonoModuleChain mono_chain; // active modules (amp chain, input to insert output)
310  StereoModuleChain stereo_chain; // active stereo modules (effect chain, after insert input)
311  enum StateFlag { // engine is off if one of these flags is set
312  SF_NO_CONNECTION = 0x01, // no jack connection at amp input
313  SF_JACK_RECONFIG = 0x02, // jack buffersize reconfiguration in progress
314  SF_INITIALIZING = 0x04, // jack or engine not ready
315  SF_OVERLOAD = 0x08, // engine overload
316  };
317 public:
318  ModuleSequencer();
319  ~ModuleSequencer();
320  void clear_module_states() {
321  mono_chain.clear_module_states();
322  stereo_chain.clear_module_states();
323  }
324  virtual void set_samplerate(unsigned int samplerate);
325  virtual void start_ramp_up();
326  virtual void start_ramp_down();
327  virtual void wait_ramp_down_finished();
328  void ramp_down() {
329  start_ramp_down();
330  wait_ramp_down_finished();
331  }
332  void set_down_dead() {
333  mono_chain.set_down_dead();
334  stereo_chain.set_down_dead();
335  }
336  bool prepare_module_lists();
337  void commit_module_lists();
338  virtual void set_rack_changed();
339  virtual bool update_module_lists();
340  bool check_module_lists();
341  virtual void overload(OverloadType tp, const char *reason); // RT
342  void set_stateflag(StateFlag flag); // RT
343  void clear_stateflag(StateFlag flag); // RT
344  void set_state(GxEngineState state);
345  GxEngineState get_state();
346  sigc::signal<void, GxEngineState>& signal_state_change() { return state_change; }
347  static void set_overload_interval(int i) { sporadic_interval = i; }
348 #ifndef NDEBUG
349  void print_engine_state();
350 #endif
351 };
352 
353 } /* end of gx_engine namespace */
gx_engine::stereochain_data::func
stereochainorder func
Definition: gx_modulesequencer.h:137
gx_engine::ProcessingChainBase::wait_latch
void wait_latch()
Definition: gx_modulesequencer.h:81
gx_engine::ProcessingChainBase::ramp_mode_off
Definition: gx_modulesequencer.h:49
cabinet_impulse_former::init
void init(int samplingFreq)
Definition: cabinet_impulse_former.cc:37
PluginDef::mono_audio
process_mono_audio mono_audio
Definition: gx_plugin.h:197
gx_engine::EngineControl::OverloadType
OverloadType
Definition: gx_modulesequencer.h:250
gx_engine::ProcessingChainBase::set_plugin_list
bool set_plugin_list(const list< Plugin * > &p)
Definition: gx_engine_audio.cpp:204
gx_engine::ProcessingChainBase::steps_up_dead
int steps_up_dead
Definition: gx_modulesequencer.h:56
gx_system::atomic_set
void atomic_set(volatile int *p, int v)
Definition: gx_system.h:89
gx_engine::ProcessingChainBase::start_ramp_down
void start_ramp_down()
Definition: gx_engine_audio.cpp:129
gx_engine::ProcessingChainBase::RampMode
RampMode
Definition: gx_modulesequencer.h:47
gx_engine::ProcessingChainBase::next_commit_needs_ramp
bool next_commit_needs_ramp
Definition: gx_modulesequencer.h:63
gx_engine::ProcessingChainBase::get_ramp_mode
RampMode get_ramp_mode()
Definition: gx_modulesequencer.h:65
gx_engine::monochain_data::func
monochainorder func
Definition: gx_modulesequencer.h:130
gx_engine::ProcessingChainBase::clear_module_states
void clear_module_states()
Definition: gx_engine_audio.cpp:230
gx_engine::ProcessingChainBase::try_set_ramp_mode
void try_set_ramp_mode(RampMode oldmode, RampMode newmode, int oldrv, int newrv)
Definition: gx_engine_audio.cpp:143
gx_engine::ThreadSafeChainPointer::ThreadSafeChainPointer
ThreadSafeChainPointer()
Definition: gx_modulesequencer.h:156
gx_engine::ProcessingChainBase::ramp_mode_up
Definition: gx_modulesequencer.h:49
gx_engine::ModuleSequencer::StateFlag
StateFlag
Definition: gx_modulesequencer.h:305
PluginDef::stereo_audio
process_stereo_audio stereo_audio
Definition: gx_plugin.h:198
gx_engine::ProcessingChainBase::ramp_mode_down_dead
Definition: gx_modulesequencer.h:49
ladspa::flag
int flag
Definition: ladspaback.cpp:56
gx_engine::ProcessingChainBase::wait_ramp_down_finished
void wait_ramp_down_finished()
Definition: gx_engine_audio.cpp:107
gx_engine::ProcessingChainBase::ProcessingChainBase
ProcessingChainBase()
Definition: gx_engine_audio.cpp:34
gx_engine::GxEngineState
GxEngineState
Definition: gx_modulesequencer.h:283
gx_engine::stereochain_data
Definition: gx_modulesequencer.h:136
gx_engine::ModuleSelector::ModuleSelector
ModuleSelector(EngineControl &seq_)
Definition: gx_modulesequencer.h:33
gx_engine::stereochain_data::plugin
PluginDef * plugin
Definition: gx_modulesequencer.h:138
gx_engine::ThreadSafeChainPointer::commit
void commit(bool clear, ParamMap &pmap)
Definition: gx_modulesequencer.h:188
gx_engine::ThreadSafeChainPointer::get_rt_chain
F * get_rt_chain()
Definition: gx_modulesequencer.h:113
PluginDef
Definition: gx_plugin.h:183
gx_engine::ModuleSelector::seq
EngineControl & seq
Definition: gx_modulesequencer.h:31
gx_engine::stereochain_data::stereochain_data
stereochain_data()
Definition: gx_modulesequencer.h:140
gx_engine::ThreadSafeChainPointer::~ThreadSafeChainPointer
~ThreadSafeChainPointer()
Definition: gx_modulesequencer.h:170
gx_engine::ProcessingChainBase::print_chain_state
void print_chain_state(const char *title)
Definition: gx_engine_audio.cpp:250
gx_engine::ProcessingChainBase::wait_rt_finished
bool wait_rt_finished()
Definition: gx_engine_audio.cpp:65
gx_engine::kEngineOff
Definition: gx_modulesequencer.h:285
gx_engine::monochainorder
void(* monochainorder)(int count, float *output, float *output1, PluginDef *plugin)
Definition: gx_modulesequencer.h:124
gx_engine::ProcessingChainBase::set_samplerate
void set_samplerate(int samplerate)
Definition: gx_engine_audio.cpp:50
gx_engine::ProcessingChainBase::set_ramp_value
void set_ramp_value(int n)
Definition: gx_modulesequencer.h:59
gx_engine::ProcessingChainBase::post_rt_finished
void post_rt_finished()
Definition: gx_modulesequencer.h:72
gx_engine::ProcessingChainBase::release
void release()
Definition: gx_engine_audio.cpp:241
gx_engine
Definition: gx_convolver.h:33
gx_engine::ModuleSelector::set_module
virtual void set_module()=0
PluginDef::clear_state
clearstatefunc clear_state
Definition: gx_plugin.h:204
gx_engine::ProcessingChainBase
Definition: gx_modulesequencer.h:43
gx_engine::ProcessingChainBase::start_ramp_up
void start_ramp_up()
Definition: gx_engine_audio.cpp:118
gx_engine::ModuleSelector
Definition: gx_modulesequencer.h:28
gx_engine::PluginList
Definition: gx_pluginloader.h:158
gx_engine::ProcessingChainBase::is_down_dead
bool is_down_dead()
Definition: gx_modulesequencer.h:89
gx_engine::ProcessingChainBase::set_ramp_mode
void set_ramp_mode(RampMode n)
Definition: gx_modulesequencer.h:60
gx_engine::kEngineOn
Definition: gx_modulesequencer.h:286
gx_engine::kEngineBypass
Definition: gx_modulesequencer.h:287
gx_engine::ThreadSafeChainPointer::processing_pointer
F * processing_pointer
Definition: gx_modulesequencer.h:112
gx_engine::ProcessingChainBase::set_stopped
void set_stopped(bool v)
Definition: gx_engine_audio.cpp:58
gx_engine::EngineControl
Definition: gx_modulesequencer.h:233
gx_engine::monochain_data
Definition: gx_modulesequencer.h:129
gx_engine::ParameterGroups
Definition: gx_parameter.h:46
gx_engine::ProcessingChainBase::steps_down
int steps_down
Definition: gx_modulesequencer.h:57
gx_engine::ParamMap
Definition: gx_parameter.h:512
gx_system::atomic_get
int atomic_get(volatile int &p)
Definition: gx_system.h:97
gx_engine::ProcessingChainBase::set_down_dead
void set_down_dead()
Definition: gx_modulesequencer.h:88
gx_engine::StereoModuleChain
Definition: gx_modulesequencer.h:222
gx_engine::ModuleSelector::~ModuleSelector
virtual ~ModuleSelector()
Definition: gx_modulesequencer.h:35
gx_engine::printlist
void printlist(const char *title, const list< Plugin * > &modules, bool header=true)
gx_engine::ModuleSequencer
Definition: gx_modulesequencer.h:290
gx_engine::ProcessingChainBase::get_ramp_value
int get_ramp_value()
Definition: gx_modulesequencer.h:68
gx_engine::ProcessingChainBase::is_stopped
bool is_stopped()
Definition: gx_modulesequencer.h:91
PluginDef::activate_plugin
activatefunc activate_plugin
Definition: gx_plugin.h:201
gx_engine::ProcessingChainBase::set_latch
void set_latch()
Definition: gx_engine_audio.cpp:98
gx_engine::ThreadSafeChainPointer::empty_chain
void empty_chain(ParamMap &pmap)
Definition: gx_modulesequencer.h:117
gx_engine::monochain_data::monochain_data
monochain_data()
Definition: gx_modulesequencer.h:133
gx_engine::ProcessingChainBase::modules
list< Plugin * > modules
Definition: gx_modulesequencer.h:58
gx_engine::ProcessingChainBase::steps_up
int steps_up
Definition: gx_modulesequencer.h:55
gx_engine::ProcessingChainBase::ramp_mode_up_dead
Definition: gx_modulesequencer.h:49
gx_engine::monochain_data::plugin
PluginDef * plugin
Definition: gx_modulesequencer.h:131
gx_engine::MonoModuleChain
Definition: gx_modulesequencer.h:215
gx_engine::ProcessingChainBase::ramp_mode_down
Definition: gx_modulesequencer.h:49
gx_engine::ProcessingChainBase::check_release
bool check_release()
Definition: gx_modulesequencer.h:83
gx_engine::stereochainorder
void(* stereochainorder)(int count, float *input, float *input1, float *output, float *output1, PluginDef *plugin)
Definition: gx_modulesequencer.h:126
gx_engine::ThreadSafeChainPointer
Definition: gx_modulesequencer.h:101
gx_engine::ProcessingChainBase::sync
void sync()
Definition: gx_modulesequencer.h:82