Ardour  9.0-pre0-582-g084a23a80d
dummy_audiobackend.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014-2018 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2014-2018 Robin Gareus <robin@gareus.org>
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 along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #ifndef __libbackend_dummy_audiobackend_h__
21 #define __libbackend_dummy_audiobackend_h__
22 
23 #include <cstdint>
24 #include <string>
25 #include <vector>
26 #include <map>
27 #include <memory>
28 #include <set>
29 
30 #include <pthread.h>
31 
32 #include <ltc.h>
33 
34 #include "pbd/natsort.h"
35 #include "pbd/ringbuffer.h"
36 #include "ardour/types.h"
37 #include "ardour/audio_backend.h"
40 
41 namespace ARDOUR {
42 
43 class DummyAudioBackend;
44 
45 namespace DummyMidiData {
46  typedef struct _MIDISequence {
47  float beat_time;
48  uint8_t size;
49  uint8_t event[3];
51 };
52 
53 
55  public:
56  DummyMidiEvent (const pframes_t timestamp, const uint8_t* data, size_t size);
59  size_t size () const { return _size; };
60  pframes_t timestamp () const { return _timestamp; };
61  const uint8_t* data () const { return _data; };
62  private:
63  size_t _size;
65  uint8_t *_data;
66 };
67 
68 typedef std::vector<std::shared_ptr<DummyMidiEvent> > DummyMidiBuffer;
69 
70 class DummyPort : public BackendPort {
71  protected:
72  DummyPort (DummyAudioBackend &b, const std::string&, PortFlags);
73  public:
74  virtual ~DummyPort ();
75 
76  void next_period () { _gen_cycle = false; }
77 
78  protected:
79  /* random number generator */
81  inline float randf ();
82  inline uint32_t randi ();
83  uint32_t _rseed;
84  /* engine time */
86 
87  // signal generator
88  volatile bool _gen_cycle;
89  Glib::Threads::Mutex generator_lock;
90 
91  private:
93 
94 }; // class DummyPort
95 
96 class DummyAudioPort : public DummyPort {
97  public:
98  DummyAudioPort (DummyAudioBackend &b, const std::string&, PortFlags);
100 
101  DataType type () const { return DataType::AUDIO; };
102 
103  Sample* buffer () { return _buffer; }
104  const Sample* const_buffer () const { return _buffer; }
105  void* get_buffer (pframes_t nframes);
106 
126  };
127  std::string setup_generator (GeneratorType const, float const, int, int);
128  void fill_wavetable (const float* d, size_t n_samples) { assert(_wavetable != 0); memcpy(_wavetable, d, n_samples * sizeof(float)); }
129  void midi_to_wavetable (DummyMidiBuffer const * const src, size_t n_samples);
130 
131  private:
133 
134  // signal generator ('fake' physical inputs)
135  void generate (const pframes_t n_samples);
137 
138  // generator buffers
139  // pink-noise filters
140  float _b0, _b1, _b2, _b3, _b4, _b5, _b6;
141  // generated sinf() samples
143  uint32_t _gen_period;
144  uint32_t _gen_offset;
145  uint32_t _gen_perio2;
146  uint32_t _gen_count2;
147 
148  // gaussian noise generator
149  float grandf ();
150  bool _pass;
151  float _rn1;
152  // LTC generator
155  float _ltc_spd;
156  float _ltc_rand;
157 
158 
159 }; // class DummyAudioPort
160 
161 class DummyMidiPort : public DummyPort {
162  public:
163  DummyMidiPort (DummyAudioBackend &b, const std::string&, PortFlags);
165 
166  DataType type () const { return DataType::MIDI; };
167 
168  void* get_buffer (pframes_t nframes);
169  const DummyMidiBuffer * const_buffer () const { return &_buffer; }
170 
171  std::string setup_generator (int, float const);
172  void set_loopback (DummyMidiBuffer const * const src);
173 
174  private:
177 
178  // midi event generator ('fake' physical inputs)
179  void midi_generate (const pframes_t n_samples);
180  float _midi_seq_spb; // samples per beat
181  int64_t _midi_seq_time;
182  uint32_t _midi_seq_pos;
184 }; // class DummyMidiPort
185 
187 {
188  public:
191 
192  bool is_running () const { return _running; }
193 
194  /* AUDIOBACKEND API */
195 
196  std::string name () const;
197  bool is_realtime () const;
198 
199  bool requires_driver_selection() const { return true; }
200  std::string driver_name () const;
201  std::vector<std::string> enumerate_drivers () const;
202  int set_driver (const std::string&);
203 
204  std::vector<DeviceStatus> enumerate_devices () const;
205  std::vector<float> available_sample_rates (const std::string& device) const;
206  std::vector<uint32_t> available_buffer_sizes (const std::string& device) const;
207 
210  bool can_measure_systemic_latency () const { return true; }
211 
212  int set_device_name (const std::string&);
213  int set_sample_rate (float);
214  int set_buffer_size (uint32_t);
215  int set_interleaved (bool yn);
218  int set_systemic_midi_input_latency (std::string const, uint32_t) { return 0; }
219  int set_systemic_midi_output_latency (std::string const, uint32_t) { return 0; }
220 
221  int reset_device () { return 0; };
222 
223  /* Retrieving parameters */
224  std::string device_name () const;
225  float sample_rate () const;
226  uint32_t buffer_size () const;
227  bool interleaved () const;
228  uint32_t systemic_input_latency () const;
229  uint32_t systemic_output_latency () const;
230  uint32_t systemic_midi_input_latency (std::string const) const { return 0; }
231  uint32_t systemic_midi_output_latency (std::string const) const { return 0; }
232 
233  /* External control app */
234  std::string control_app_name () const { return std::string (); }
236 
237  /* MIDI */
238  std::vector<std::string> enumerate_midi_options () const;
239  int set_midi_option (const std::string&);
240  std::string midi_option () const;
241 
242  std::vector<DeviceStatus> enumerate_midi_devices () const {
243  return std::vector<AudioBackend::DeviceStatus> ();
244  }
245  int set_midi_device_enabled (std::string const, bool) {
246  return 0;
247  }
248  bool midi_device_enabled (std::string const) const {
249  return true;
250  }
252  return false;
253  }
254 
255  /* State Control */
256  protected:
257  int _start (bool for_latency_measurement);
258  public:
259  int stop ();
260  int freewheel (bool);
261  float dsp_load () const;
263 
264  /* Process time */
268 
269  int create_process_thread (std::function<void()> func);
272  uint32_t process_thread_count ();
273 
275 
276  /* PORTENGINE API */
277 
278  void* private_handle () const;
279  const std::string& my_name () const;
280 
281  /* PortEngine API - forwarded to PortEngineSharedImpl */
282 
284  void get_physical_outputs (DataType type, std::vector<std::string>& results) { PortEngineSharedImpl::get_physical_outputs (type, results); }
285  void get_physical_inputs (DataType type, std::vector<std::string>& results) { PortEngineSharedImpl::get_physical_inputs (type, results); }
288  uint32_t port_name_size () const { return PortEngineSharedImpl::port_name_size(); }
293  int get_port_property (PortEngine::PortHandle ph, const std::string& key, std::string& value, std::string& type) const { return PortEngineSharedImpl::get_port_property (ph, key, value, type); }
294  int set_port_property (PortEngine::PortHandle ph, const std::string& key, const std::string& value, const std::string& type) { return PortEngineSharedImpl::set_port_property (ph, key, value, type); }
295  int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>& results) const { return PortEngineSharedImpl::get_ports (port_name_pattern, type, flags, results); }
297  PortEngine::PortPtr register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) { return PortEngineSharedImpl::register_port (shortname, type, flags); }
299  int connect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::connect (src, dst); }
300  int disconnect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::disconnect (src, dst); }
301  int connect (PortEngine::PortHandle ph, const std::string& other) { return PortEngineSharedImpl::connect (ph, other); }
302  int disconnect (PortEngine::PortHandle ph, const std::string& other) { return PortEngineSharedImpl::disconnect (ph, other); }
304  bool connected (PortEngine::PortHandle ph, bool process_callback_safe) { return PortEngineSharedImpl::connected (ph, process_callback_safe); }
305  bool connected_to (PortEngine::PortHandle ph, const std::string& other, bool process_callback_safe) { return PortEngineSharedImpl::connected_to (ph, other, process_callback_safe); }
306  bool physically_connected (PortEngine::PortHandle ph, bool process_callback_safe) { return PortEngineSharedImpl::physically_connected (ph, process_callback_safe); }
307  int get_connections (PortEngine::PortHandle ph, std::vector<std::string>& results, bool process_callback_safe) { return PortEngineSharedImpl::get_connections (ph, results, process_callback_safe); }
308 
309 
310  /* MIDI */
311  int midi_event_get (pframes_t& timestamp, size_t& size, uint8_t const** buf, void* port_buffer, uint32_t event_index);
312  int midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size);
313  uint32_t get_midi_event_count (void* port_buffer);
314  void midi_clear (void* port_buffer);
315 
316  /* Monitoring */
317 
318  bool can_monitor_input () const;
322 
323  /* Latency management */
324 
325  void set_latency_range (PortHandle, bool for_playback, LatencyRange);
327 
328  /* Getting access to the data buffer for a port */
329 
331 
333 
334  static size_t max_buffer_size() {return _max_buffer_size;}
335 
336  private:
343  };
344 
345  struct DriverSpeed {
346  std::string name;
347  float speedup;
348  bool realtime;
349  DriverSpeed (const std::string& n, float s, bool r = false) : name (n), speedup (s), realtime (r) {}
350  };
351 
352  std::string _instance_name;
353  static std::vector<std::string> _midi_options;
354  static std::vector<AudioBackend::DeviceStatus> _device_status;
355  static std::vector<DummyAudioBackend::DriverSpeed> _driver_speed;
356 
357  bool _running;
360  bool _realtime;
361  float _speedup;
362 
363  std::string _device;
364 
365  float _samplerate;
367  float _dsp_load;
369  static size_t _max_buffer_size;
370 
371  uint32_t _n_inputs;
372  uint32_t _n_outputs;
373 
374  uint32_t _n_midi_inputs;
375  uint32_t _n_midi_outputs;
377 
380 
382 
383  pthread_t _main_thread;
384 
385  /* process threads */
386  static void* dummy_process_thread (void *);
387  std::vector<pthread_t> _threads;
388 
389  struct ThreadData {
391  std::function<void ()> f;
392  size_t stacksize;
393 
394  ThreadData (DummyAudioBackend* e, std::function<void ()> fp, size_t stacksz)
395  : engine (e) , f (fp) , stacksize (stacksz) {}
396  };
397 
398  /* port engine */
400 
402 
403 }; // class DummyAudioBackend
404 
405 } // namespace
406 
407 #endif /* __libbackend_dummy_audiobackend_h__ */
AudioBackendInfo & info() const
const std::string & my_name() const
static void * dummy_process_thread(void *)
int create_process_thread(std::function< void()> func)
int disconnect(const std::string &src, const std::string &dst)
int get_connections(PortEngine::PortHandle ph, std::vector< std::string > &results, bool process_callback_safe)
static std::vector< std::string > _midi_options
bool physically_connected(PortEngine::PortHandle ph, bool process_callback_safe)
void set_latency_range(PortHandle, bool for_playback, LatencyRange)
int set_midi_device_enabled(std::string const, bool)
pframes_t samples_since_cycle_start()
bool can_change_sample_rate_when_running() const
int set_systemic_midi_output_latency(std::string const, uint32_t)
std::vector< DeviceStatus > enumerate_midi_devices() const
void get_physical_inputs(DataType type, std::vector< std::string > &results)
std::string control_app_name() const
bool can_set_systemic_midi_latencies() const
bool can_monitor_input() const
DSPLoadCalculator _dsp_load_calc
DataType port_data_type(PortEngine::PortHandle ph) const
std::string driver_name() const
std::vector< pthread_t > _threads
static std::vector< AudioBackend::DeviceStatus > _device_status
int set_interleaved(bool yn)
int connect(const std::string &src, const std::string &dst)
int _start(bool for_latency_measurement)
int disconnect(PortEngine::PortHandle ph, const std::string &other)
uint32_t systemic_midi_output_latency(std::string const) const
PortEngine::PortPtr register_port(const std::string &shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags)
std::string get_port_name(PortEngine::PortHandle ph) const
std::string midi_option() const
bool midi_device_enabled(std::string const) const
void unregister_port(PortHandle ph)
std::vector< float > available_sample_rates(const std::string &device) const
int set_systemic_input_latency(uint32_t)
int disconnect_all(PortEngine::PortHandle ph)
ChanCount n_physical_inputs() const
bool can_change_buffer_size_when_running() const
int set_device_name(const std::string &)
DummyAudioBackend(AudioEngine &e, AudioBackendInfo &info)
PortFlags get_port_flags(PortEngine::PortHandle ph) const
ChanCount n_physical_outputs() const
std::string device_name() const
int ensure_input_monitoring(PortHandle, bool)
BackendPort * port_factory(std::string const &name, ARDOUR::DataType type, ARDOUR::PortFlags)
int set_midi_option(const std::string &)
bool connected(PortEngine::PortHandle ph, bool process_callback_safe)
bool connected_to(PortEngine::PortHandle ph, const std::string &other, bool process_callback_safe)
int set_buffer_size(uint32_t)
std::vector< uint32_t > available_buffer_sizes(const std::string &device) const
std::vector< std::string > enumerate_midi_options() const
bool can_measure_systemic_latency() const
bool monitoring_input(PortHandle)
uint32_t systemic_input_latency() const
int midi_event_put(void *port_buffer, pframes_t timestamp, const uint8_t *buffer, size_t size)
int request_input_monitoring(PortHandle, bool)
uint32_t buffer_size() const
std::vector< std::string > enumerate_drivers() const
static std::vector< DummyAudioBackend::DriverSpeed > _driver_speed
int midi_event_get(pframes_t &timestamp, size_t &size, uint8_t const **buf, void *port_buffer, uint32_t event_index)
bool port_is_physical(PortEngine::PortHandle ph) const
int get_port_property(PortEngine::PortHandle ph, const std::string &key, std::string &value, std::string &type) const
int get_ports(const std::string &port_name_pattern, DataType type, PortFlags flags, std::vector< std::string > &results) const
std::vector< DeviceStatus > enumerate_devices() const
int set_port_name(PortEngine::PortHandle ph, const std::string &name)
uint32_t systemic_output_latency() const
PortEngine::PortPtr get_port_by_name(std::string const &name) const
void * private_handle() const
void midi_clear(void *port_buffer)
int set_port_property(PortEngine::PortHandle ph, const std::string &key, const std::string &value, const std::string &type)
std::string name() const
void get_physical_outputs(DataType type, std::vector< std::string > &results)
int connect(PortEngine::PortHandle ph, const std::string &other)
samplepos_t sample_time_at_cycle_start()
int set_systemic_output_latency(uint32_t)
LatencyRange get_latency_range(PortHandle, bool for_playback)
void * get_buffer(PortHandle, pframes_t)
int set_systemic_midi_input_latency(std::string const, uint32_t)
int set_driver(const std::string &)
uint32_t get_midi_event_count(void *port_buffer)
size_t raw_buffer_size(DataType t)
uint32_t systemic_midi_input_latency(std::string const) const
const Sample * const_buffer() const
PBD::RingBuffer< Sample > * _ltcbuf
void * get_buffer(pframes_t nframes)
void midi_to_wavetable(DummyMidiBuffer const *const src, size_t n_samples)
void fill_wavetable(const float *d, size_t n_samples)
DummyAudioPort(DummyAudioBackend &b, const std::string &, PortFlags)
void generate(const pframes_t n_samples)
std::string setup_generator(GeneratorType const, float const, int, int)
DummyMidiEvent(const DummyMidiEvent &other)
const uint8_t * data() const
pframes_t timestamp() const
DummyMidiEvent(const pframes_t timestamp, const uint8_t *data, size_t size)
std::string setup_generator(int, float const)
const DummyMidiBuffer * const_buffer() const
DummyMidiData::MIDISequence const * _midi_seq_dat
void * get_buffer(pframes_t nframes)
void midi_generate(const pframes_t n_samples)
DummyMidiPort(DummyAudioBackend &b, const std::string &, PortFlags)
void set_loopback(DummyMidiBuffer const *const src)
void setup_random_number_generator()
Glib::Threads::Mutex generator_lock
AudioBackend & _engine
volatile bool _gen_cycle
DummyPort(DummyAudioBackend &b, const std::string &, PortFlags)
virtual ~DummyPort()
uint32_t randi()
pframes_t pulse_position() const
int set_port_name(PortEngine::PortHandle, const std::string &)
uint32_t port_name_size() const
virtual void unregister_port(PortEngine::PortHandle)
bool physically_connected(PortEngine::PortHandle, bool process_callback_safe)
int disconnect(const std::string &src, const std::string &dst)
PortEngine::PortPtr get_port_by_name(const std::string &) const
int get_ports(const std::string &port_name_pattern, DataType type, PortFlags flags, std::vector< std::string > &) const
int connect(const std::string &src, const std::string &dst)
ChanCount n_physical_outputs() const
PortFlags get_port_flags(PortEngine::PortHandle) const
bool connected_to(PortEngine::PortHandle, const std::string &, bool process_callback_safe)
bool connected(PortEngine::PortHandle, bool process_callback_safe)
int get_connections(PortEngine::PortHandle, std::vector< std::string > &, bool process_callback_safe)
std::string get_port_name(PortEngine::PortHandle) const
ChanCount n_physical_inputs() const
void get_physical_outputs(DataType type, std::vector< std::string > &)
void get_physical_inputs(DataType type, std::vector< std::string > &)
DataType port_data_type(PortEngine::PortHandle) const
int disconnect_all(PortEngine::PortHandle)
bool port_is_physical(PortEngine::PortHandle) const
int get_port_property(PortEngine::PortHandle, const std::string &key, std::string &value, std::string &type) const
int set_port_property(PortEngine::PortHandle, const std::string &key, const std::string &value, const std::string &type)
PortEngine::PortPtr register_port(const std::string &shortname, ARDOUR::DataType, ARDOUR::PortFlags)
PortPtr const & PortHandle
Definition: port_engine.h:113
std::shared_ptr< ProtoPort > PortPtr
Definition: port_engine.h:107
libltc - en+decode linear timecode
struct ARDOUR::DummyMidiData::_MIDISequence MIDISequence
std::vector< std::shared_ptr< DummyMidiEvent > > DummyMidiBuffer
uint32_t pframes_t
Temporal::samplecnt_t samplecnt_t
Temporal::samplepos_t samplepos_t
DriverSpeed(const std::string &n, float s, bool r=false)
ThreadData(DummyAudioBackend *e, std::function< void()> fp, size_t stacksz)