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