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 <string> 24 #include <vector> 25 #include <map> 26 #include <set> 27 28 #include <stdint.h> 29 #include <pthread.h> 30 31 #include <ltc.h> 32 33 #include <boost/shared_ptr.hpp> 34 35 #include "pbd/natsort.h" 36 #include "pbd/ringbuffer.h" 37 #include "ardour/types.h" 38 #include "ardour/audio_backend.h" 39 #include "ardour/dsp_load_calculator.h" 40 #include "ardour/port_engine_shared.h" 41 42 namespace ARDOUR { 43 44 class DummyAudioBackend; 45 46 namespace DummyMidiData { 47 typedef struct _MIDISequence { 48 float beat_time; 49 uint8_t size; 50 uint8_t event[3]; 51 } MIDISequence; 52 }; 53 54 55 class DummyMidiEvent { 56 public: 57 DummyMidiEvent (const pframes_t timestamp, const uint8_t* data, size_t size); 58 DummyMidiEvent (const DummyMidiEvent& other); 59 ~DummyMidiEvent (); size()60 size_t size () const { return _size; }; timestamp()61 pframes_t timestamp () const { return _timestamp; }; const_data()62 const unsigned char* const_data () const { return _data; }; data()63 unsigned char* data () { return _data; }; 64 bool operator< (const DummyMidiEvent &other) const { return timestamp () < other.timestamp (); }; 65 private: 66 size_t _size; 67 pframes_t _timestamp; 68 uint8_t *_data; 69 }; 70 71 typedef std::vector<boost::shared_ptr<DummyMidiEvent> > DummyMidiBuffer; 72 73 class DummyPort : public BackendPort { 74 protected: 75 DummyPort (DummyAudioBackend &b, const std::string&, PortFlags); 76 public: 77 virtual ~DummyPort (); 78 next_period()79 void next_period () { _gen_cycle = false; } 80 81 protected: 82 /* random number generator */ 83 void setup_random_number_generator (); 84 inline float randf (); 85 inline uint32_t randi (); 86 uint32_t _rseed; 87 /* engine time */ 88 pframes_t pulse_position () const; 89 90 // signal generator 91 volatile bool _gen_cycle; 92 Glib::Threads::Mutex generator_lock; 93 94 private: 95 AudioBackend& _engine; 96 97 }; // class DummyPort 98 99 class DummyAudioPort : public DummyPort { 100 public: 101 DummyAudioPort (DummyAudioBackend &b, const std::string&, PortFlags); 102 ~DummyAudioPort (); 103 type()104 DataType type () const { return DataType::AUDIO; }; 105 buffer()106 Sample* buffer () { return _buffer; } const_buffer()107 const Sample* const_buffer () const { return _buffer; } 108 void* get_buffer (pframes_t nframes); 109 110 enum GeneratorType { 111 Silence, 112 DC05, 113 Demolition, 114 UniformWhiteNoise, 115 GaussianWhiteNoise, 116 PinkNoise, 117 PonyNoise, 118 SineWave, 119 SineWaveOctaves, 120 SquareWave, 121 KronekerDelta, 122 SineSweep, 123 SineSweepSwell, 124 SquareSweep, 125 SquareSweepSwell, 126 OneHz, 127 LTC, 128 Loopback, 129 }; 130 std::string setup_generator (GeneratorType const, float const, int, int); fill_wavetable(const float * d,size_t n_samples)131 void fill_wavetable (const float* d, size_t n_samples) { assert(_wavetable != 0); memcpy(_wavetable, d, n_samples * sizeof(float)); } 132 void midi_to_wavetable (DummyMidiBuffer const * const src, size_t n_samples); 133 134 private: 135 Sample _buffer[8192]; 136 137 // signal generator ('fake' physical inputs) 138 void generate (const pframes_t n_samples); 139 GeneratorType _gen_type; 140 141 // generator buffers 142 // pink-noise filters 143 float _b0, _b1, _b2, _b3, _b4, _b5, _b6; 144 // generated sinf() samples 145 Sample * _wavetable; 146 uint32_t _gen_period; 147 uint32_t _gen_offset; 148 uint32_t _gen_perio2; 149 uint32_t _gen_count2; 150 151 // gaussian noise generator 152 float grandf (); 153 bool _pass; 154 float _rn1; 155 // LTC generator 156 LTCEncoder* _ltc; 157 PBD::RingBuffer<Sample>* _ltcbuf; 158 float _ltc_spd; 159 float _ltc_rand; 160 161 162 }; // class DummyAudioPort 163 164 class DummyMidiPort : public DummyPort { 165 public: 166 DummyMidiPort (DummyAudioBackend &b, const std::string&, PortFlags); 167 ~DummyMidiPort (); 168 type()169 DataType type () const { return DataType::MIDI; }; 170 171 void* get_buffer (pframes_t nframes); const_buffer()172 const DummyMidiBuffer * const_buffer () const { return &_buffer; } 173 174 std::string setup_generator (int, float const); 175 void set_loopback (DummyMidiBuffer const * const src); 176 177 private: 178 DummyMidiBuffer _buffer; 179 DummyMidiBuffer _loopback; 180 181 // midi event generator ('fake' physical inputs) 182 void midi_generate (const pframes_t n_samples); 183 float _midi_seq_spb; // samples per beat 184 int64_t _midi_seq_time; 185 uint32_t _midi_seq_pos; 186 DummyMidiData::MIDISequence const * _midi_seq_dat; 187 }; // class DummyMidiPort 188 189 class DummyAudioBackend : public AudioBackend, public PortEngineSharedImpl { 190 public: 191 DummyAudioBackend (AudioEngine& e, AudioBackendInfo& info); 192 ~DummyAudioBackend (); 193 is_running()194 bool is_running () const { return _running; } 195 196 /* AUDIOBACKEND API */ 197 198 std::string name () const; 199 bool is_realtime () const; 200 requires_driver_selection()201 bool requires_driver_selection() const { return true; } 202 std::string driver_name () const; 203 std::vector<std::string> enumerate_drivers () const; 204 int set_driver (const std::string&); 205 206 std::vector<DeviceStatus> enumerate_devices () const; 207 std::vector<float> available_sample_rates (const std::string& device) const; 208 std::vector<uint32_t> available_buffer_sizes (const std::string& device) const; 209 uint32_t available_input_channel_count (const std::string& device) const; 210 uint32_t available_output_channel_count (const std::string& device) const; 211 212 bool can_change_sample_rate_when_running () const; 213 bool can_change_buffer_size_when_running () const; can_measure_systemic_latency()214 bool can_measure_systemic_latency () const { return true; } 215 216 int set_device_name (const std::string&); 217 int set_sample_rate (float); 218 int set_buffer_size (uint32_t); 219 int set_interleaved (bool yn); 220 int set_input_channels (uint32_t); 221 int set_output_channels (uint32_t); 222 int set_systemic_input_latency (uint32_t); 223 int set_systemic_output_latency (uint32_t); set_systemic_midi_input_latency(std::string const,uint32_t)224 int set_systemic_midi_input_latency (std::string const, uint32_t) { return 0; } set_systemic_midi_output_latency(std::string const,uint32_t)225 int set_systemic_midi_output_latency (std::string const, uint32_t) { return 0; } 226 reset_device()227 int reset_device () { return 0; }; 228 229 /* Retrieving parameters */ 230 std::string device_name () const; 231 float sample_rate () const; 232 uint32_t buffer_size () const; 233 bool interleaved () const; 234 uint32_t input_channels () const; 235 uint32_t output_channels () const; 236 uint32_t systemic_input_latency () const; 237 uint32_t systemic_output_latency () const; systemic_midi_input_latency(std::string const)238 uint32_t systemic_midi_input_latency (std::string const) const { return 0; } systemic_midi_output_latency(std::string const)239 uint32_t systemic_midi_output_latency (std::string const) const { return 0; } 240 241 /* External control app */ control_app_name()242 std::string control_app_name () const { return std::string (); } launch_control_app()243 void launch_control_app () {} 244 245 /* MIDI */ 246 std::vector<std::string> enumerate_midi_options () const; 247 int set_midi_option (const std::string&); 248 std::string midi_option () const; 249 enumerate_midi_devices()250 std::vector<DeviceStatus> enumerate_midi_devices () const { 251 return std::vector<AudioBackend::DeviceStatus> (); 252 } set_midi_device_enabled(std::string const,bool)253 int set_midi_device_enabled (std::string const, bool) { 254 return 0; 255 } midi_device_enabled(std::string const)256 bool midi_device_enabled (std::string const) const { 257 return true; 258 } can_set_systemic_midi_latencies()259 bool can_set_systemic_midi_latencies () const { 260 return false; 261 } 262 263 /* State Control */ 264 protected: 265 int _start (bool for_latency_measurement); 266 public: 267 int stop (); 268 int freewheel (bool); 269 float dsp_load () const; 270 size_t raw_buffer_size (DataType t); 271 272 /* Process time */ 273 samplepos_t sample_time (); 274 samplepos_t sample_time_at_cycle_start (); 275 pframes_t samples_since_cycle_start (); 276 277 int create_process_thread (boost::function<void()> func); 278 int join_process_threads (); 279 bool in_process_thread (); 280 uint32_t process_thread_count (); 281 282 void update_latencies (); 283 284 /* PORTENGINE API */ 285 286 void* private_handle () const; 287 const std::string& my_name () const; 288 289 /* PortEngine API - forwarded to PortEngineSharedImpl */ 290 port_is_physical(PortEngine::PortHandle ph)291 bool port_is_physical (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::port_is_physical (ph); } get_physical_outputs(DataType type,std::vector<std::string> & results)292 void get_physical_outputs (DataType type, std::vector<std::string>& results) { PortEngineSharedImpl::get_physical_outputs (type, results); } get_physical_inputs(DataType type,std::vector<std::string> & results)293 void get_physical_inputs (DataType type, std::vector<std::string>& results) { PortEngineSharedImpl::get_physical_inputs (type, results); } n_physical_outputs()294 ChanCount n_physical_outputs () const { return PortEngineSharedImpl::n_physical_outputs (); } n_physical_inputs()295 ChanCount n_physical_inputs () const { return PortEngineSharedImpl::n_physical_inputs (); } port_name_size()296 uint32_t port_name_size () const { return PortEngineSharedImpl::port_name_size(); } set_port_name(PortEngine::PortHandle ph,const std::string & name)297 int set_port_name (PortEngine::PortHandle ph, const std::string& name) { return PortEngineSharedImpl::set_port_name (ph, name); } get_port_name(PortEngine::PortHandle ph)298 std::string get_port_name (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_name (ph); } get_port_flags(PortEngine::PortHandle ph)299 PortFlags get_port_flags (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_flags (ph); } get_port_by_name(std::string const & name)300 PortEngine::PortPtr get_port_by_name (std::string const & name) const { return PortEngineSharedImpl::get_port_by_name (name); } get_port_property(PortEngine::PortHandle ph,const std::string & key,std::string & value,std::string & type)301 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); } set_port_property(PortEngine::PortHandle ph,const std::string & key,const std::string & value,const std::string & type)302 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); } get_ports(const std::string & port_name_pattern,DataType type,PortFlags flags,std::vector<std::string> & results)303 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); } port_data_type(PortEngine::PortHandle ph)304 DataType port_data_type (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::port_data_type (ph); } register_port(const std::string & shortname,ARDOUR::DataType type,ARDOUR::PortFlags flags)305 PortEngine::PortPtr register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) { return PortEngineSharedImpl::register_port (shortname, type, flags); } unregister_port(PortHandle ph)306 void unregister_port (PortHandle ph) { if (!_running) return; PortEngineSharedImpl::unregister_port (ph); } connect(const std::string & src,const std::string & dst)307 int connect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::connect (src, dst); } disconnect(const std::string & src,const std::string & dst)308 int disconnect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::disconnect (src, dst); } connect(PortEngine::PortHandle ph,const std::string & other)309 int connect (PortEngine::PortHandle ph, const std::string& other) { return PortEngineSharedImpl::connect (ph, other); } disconnect(PortEngine::PortHandle ph,const std::string & other)310 int disconnect (PortEngine::PortHandle ph, const std::string& other) { return PortEngineSharedImpl::disconnect (ph, other); } disconnect_all(PortEngine::PortHandle ph)311 int disconnect_all (PortEngine::PortHandle ph) { return PortEngineSharedImpl::disconnect_all (ph); } connected(PortEngine::PortHandle ph,bool process_callback_safe)312 bool connected (PortEngine::PortHandle ph, bool process_callback_safe) { return PortEngineSharedImpl::connected (ph, process_callback_safe); } connected_to(PortEngine::PortHandle ph,const std::string & other,bool process_callback_safe)313 bool connected_to (PortEngine::PortHandle ph, const std::string& other, bool process_callback_safe) { return PortEngineSharedImpl::connected_to (ph, other, process_callback_safe); } physically_connected(PortEngine::PortHandle ph,bool process_callback_safe)314 bool physically_connected (PortEngine::PortHandle ph, bool process_callback_safe) { return PortEngineSharedImpl::physically_connected (ph, process_callback_safe); } get_connections(PortEngine::PortHandle ph,std::vector<std::string> & results,bool process_callback_safe)315 int get_connections (PortEngine::PortHandle ph, std::vector<std::string>& results, bool process_callback_safe) { return PortEngineSharedImpl::get_connections (ph, results, process_callback_safe); } 316 317 318 /* MIDI */ 319 int midi_event_get (pframes_t& timestamp, size_t& size, uint8_t const** buf, void* port_buffer, uint32_t event_index); 320 int midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size); 321 uint32_t get_midi_event_count (void* port_buffer); 322 void midi_clear (void* port_buffer); 323 324 /* Monitoring */ 325 326 bool can_monitor_input () const; 327 int request_input_monitoring (PortHandle, bool); 328 int ensure_input_monitoring (PortHandle, bool); 329 bool monitoring_input (PortHandle); 330 331 /* Latency management */ 332 333 void set_latency_range (PortHandle, bool for_playback, LatencyRange); 334 LatencyRange get_latency_range (PortHandle, bool for_playback); 335 336 /* Getting access to the data buffer for a port */ 337 338 void* get_buffer (PortHandle, pframes_t); 339 340 void* main_process_thread (); 341 max_buffer_size()342 static size_t max_buffer_size() {return _max_buffer_size;} 343 344 private: 345 enum MidiPortMode { 346 MidiNoEvents, 347 MidiGenerator, 348 MidiOneHz, 349 MidiLoopback, 350 MidiToAudio, 351 }; 352 353 struct DriverSpeed { 354 std::string name; 355 float speedup; DriverSpeedDriverSpeed356 DriverSpeed (const std::string& n, float s) : name (n), speedup (s) {} 357 }; 358 359 std::string _instance_name; 360 static std::vector<std::string> _midi_options; 361 static std::vector<AudioBackend::DeviceStatus> _device_status; 362 static std::vector<DummyAudioBackend::DriverSpeed> _driver_speed; 363 364 bool _running; 365 bool _freewheel; 366 bool _freewheeling; 367 float _speedup; 368 369 std::string _device; 370 371 float _samplerate; 372 size_t _samples_per_period; 373 float _dsp_load; 374 DSPLoadCalculator _dsp_load_calc; 375 static size_t _max_buffer_size; 376 377 uint32_t _n_inputs; 378 uint32_t _n_outputs; 379 380 uint32_t _n_midi_inputs; 381 uint32_t _n_midi_outputs; 382 MidiPortMode _midi_mode; 383 384 uint32_t _systemic_input_latency; 385 uint32_t _systemic_output_latency; 386 387 samplecnt_t _processed_samples; 388 389 pthread_t _main_thread; 390 391 /* process threads */ 392 static void* dummy_process_thread (void *); 393 std::vector<pthread_t> _threads; 394 395 struct ThreadData { 396 DummyAudioBackend* engine; 397 boost::function<void ()> f; 398 size_t stacksize; 399 ThreadDataThreadData400 ThreadData (DummyAudioBackend* e, boost::function<void ()> fp, size_t stacksz) 401 : engine (e) , f (fp) , stacksize (stacksz) {} 402 }; 403 404 /* port engine */ 405 int register_system_ports (); 406 407 BackendPort* port_factory (std::string const & name, ARDOUR::DataType type, ARDOUR::PortFlags); 408 409 }; // class DummyAudioBackend 410 411 } // namespace 412 413 #endif /* __libbackend_dummy_audiobackend_h__ */ 414