5e9602c1da7f53f30d3bce4c3c99c2daceed7ea5
[ardour.git] / libs / backends / dummy / dummy_audiobackend.cc
1 /*
2  * Copyright (C) 2014 Robin Gareus <robin@gareus.org>
3  * Copyright (C) 2013 Paul Davis
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., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19
20 #include <sys/time.h>
21 #include <regex.h>
22 #include <stdlib.h>
23
24 #include <glibmm.h>
25
26 #include "dummy_audiobackend.h"
27 #include "dummy_midi_seq.h"
28
29 #include "pbd/error.h"
30 #include "ardour/port_manager.h"
31 #include "i18n.h"
32
33 using namespace ARDOUR;
34
35 static std::string s_instance_name;
36 size_t DummyAudioBackend::_max_buffer_size = 8192;
37 std::vector<std::string> DummyAudioBackend::_midi_options;
38 std::vector<AudioBackend::DeviceStatus> DummyAudioBackend::_device_status;
39
40 DummyAudioBackend::DummyAudioBackend (AudioEngine& e, AudioBackendInfo& info)
41         : AudioBackend (e, info)
42         , _running (false)
43         , _freewheeling (false)
44         , _device ("")
45         , _samplerate (48000)
46         , _samples_per_period (1024)
47         , _dsp_load (0)
48         , _n_inputs (0)
49         , _n_outputs (0)
50         , _n_midi_inputs (0)
51         , _n_midi_outputs (0)
52         , _enable_midi_generators (false)
53         , _systemic_input_latency (0)
54         , _systemic_output_latency (0)
55         , _processed_samples (0)
56         , _port_change_flag (false)
57 {
58         _instance_name = s_instance_name;
59         _device = _("Silence");
60         pthread_mutex_init (&_port_callback_mutex, 0);
61 }
62
63 DummyAudioBackend::~DummyAudioBackend ()
64 {
65         pthread_mutex_destroy (&_port_callback_mutex);
66 }
67
68 /* AUDIOBACKEND API */
69
70 std::string
71 DummyAudioBackend::name () const
72 {
73         return X_("Dummy");
74 }
75
76 bool
77 DummyAudioBackend::is_realtime () const
78 {
79         return false;
80 }
81
82 std::vector<AudioBackend::DeviceStatus>
83 DummyAudioBackend::enumerate_devices () const
84 {
85         if (_device_status.empty()) {
86                 _device_status.push_back (DeviceStatus (_("Silence"), true));
87                 _device_status.push_back (DeviceStatus (_("Sine Wave"), true));
88                 _device_status.push_back (DeviceStatus (_("Square Wave"), true));
89                 _device_status.push_back (DeviceStatus (_("Impulses"), true));
90                 _device_status.push_back (DeviceStatus (_("Uniform White Noise"), true));
91                 _device_status.push_back (DeviceStatus (_("Gaussian White Noise"), true));
92                 _device_status.push_back (DeviceStatus (_("Pink Noise"), true));
93                 _device_status.push_back (DeviceStatus (_("Pink Noise (low CPU)"), true));
94                 _device_status.push_back (DeviceStatus (_("Sine Sweep"), true));
95                 _device_status.push_back (DeviceStatus (_("Sine Sweep Swell"), true));
96         }
97         return _device_status;
98 }
99
100 std::vector<float>
101 DummyAudioBackend::available_sample_rates (const std::string&) const
102 {
103         std::vector<float> sr;
104         sr.push_back (8000.0);
105         sr.push_back (22050.0);
106         sr.push_back (24000.0);
107         sr.push_back (44100.0);
108         sr.push_back (48000.0);
109         sr.push_back (88200.0);
110         sr.push_back (96000.0);
111         sr.push_back (176400.0);
112         sr.push_back (192000.0);
113         return sr;
114 }
115
116 std::vector<uint32_t>
117 DummyAudioBackend::available_buffer_sizes (const std::string&) const
118 {
119         std::vector<uint32_t> bs;
120         bs.push_back (4);
121         bs.push_back (8);
122         bs.push_back (16);
123         bs.push_back (32);
124         bs.push_back (64);
125         bs.push_back (128);
126         bs.push_back (256);
127         bs.push_back (512);
128         bs.push_back (1024);
129         bs.push_back (2048);
130         bs.push_back (4096);
131         bs.push_back (8192);
132         return bs;
133 }
134
135 uint32_t
136 DummyAudioBackend::available_input_channel_count (const std::string&) const
137 {
138         return 128;
139 }
140
141 uint32_t
142 DummyAudioBackend::available_output_channel_count (const std::string&) const
143 {
144         return 128;
145 }
146
147 bool
148 DummyAudioBackend::can_change_sample_rate_when_running () const
149 {
150         return true;
151 }
152
153 bool
154 DummyAudioBackend::can_change_buffer_size_when_running () const
155 {
156         return true;
157 }
158
159 int
160 DummyAudioBackend::set_device_name (const std::string& d)
161 {
162         _device = d;
163         return 0;
164 }
165
166 int
167 DummyAudioBackend::set_sample_rate (float sr)
168 {
169         if (sr <= 0) { return -1; }
170         _samplerate = sr;
171         engine.sample_rate_change (sr);
172         return 0;
173 }
174
175 int
176 DummyAudioBackend::set_buffer_size (uint32_t bs)
177 {
178         if (bs <= 0 || bs >= _max_buffer_size) {
179                 return -1;
180         }
181         _samples_per_period = bs;
182         engine.buffer_size_change (bs);
183         return 0;
184 }
185
186 int
187 DummyAudioBackend::set_interleaved (bool yn)
188 {
189         if (!yn) { return 0; }
190         return -1;
191 }
192
193 int
194 DummyAudioBackend::set_input_channels (uint32_t cc)
195 {
196         _n_inputs = cc;
197         return 0;
198 }
199
200 int
201 DummyAudioBackend::set_output_channels (uint32_t cc)
202 {
203         _n_outputs = cc;
204         return 0;
205 }
206
207 int
208 DummyAudioBackend::set_systemic_input_latency (uint32_t sl)
209 {
210         _systemic_input_latency = sl;
211         return 0;
212 }
213
214 int
215 DummyAudioBackend::set_systemic_output_latency (uint32_t sl)
216 {
217         _systemic_output_latency = sl;
218         return 0;
219 }
220
221 /* Retrieving parameters */
222 std::string
223 DummyAudioBackend::device_name () const
224 {
225         return _device;
226 }
227
228 float
229 DummyAudioBackend::sample_rate () const
230 {
231         return _samplerate;
232 }
233
234 uint32_t
235 DummyAudioBackend::buffer_size () const
236 {
237         return _samples_per_period;
238 }
239
240 bool
241 DummyAudioBackend::interleaved () const
242 {
243         return false;
244 }
245
246 uint32_t
247 DummyAudioBackend::input_channels () const
248 {
249         return _n_inputs;
250 }
251
252 uint32_t
253 DummyAudioBackend::output_channels () const
254 {
255         return _n_outputs;
256 }
257
258 uint32_t
259 DummyAudioBackend::systemic_input_latency () const
260 {
261         return _systemic_input_latency;
262 }
263
264 uint32_t
265 DummyAudioBackend::systemic_output_latency () const
266 {
267         return _systemic_output_latency;
268 }
269
270
271 /* MIDI */
272 std::vector<std::string>
273 DummyAudioBackend::enumerate_midi_options () const
274 {
275         if (_midi_options.empty()) {
276                 _midi_options.push_back (_("No MIDI I/O"));
277                 _midi_options.push_back (_("1 in, 1 out, Silence"));
278                 _midi_options.push_back (_("2 in, 2 out, Silence"));
279                 _midi_options.push_back (_("8 in, 8 out, Silence"));
280                 _midi_options.push_back (_("Midi Event Generators"));
281         }
282         return _midi_options;
283 }
284
285 int
286 DummyAudioBackend::set_midi_option (const std::string& opt)
287 {
288         _enable_midi_generators = false;
289         if (opt == _("1 in, 1 out, Silence")) {
290                 _n_midi_inputs = _n_midi_outputs = 1;
291         }
292         else if (opt == _("2 in, 2 out, Silence")) {
293                 _n_midi_inputs = _n_midi_outputs = 2;
294         }
295         else if (opt == _("8 in, 8 out, Silence")) {
296                 _n_midi_inputs = _n_midi_outputs = 8;
297         }
298         else if (opt == _("Midi Event Generators")) {
299                 _n_midi_inputs = _n_midi_outputs = NUM_MIDI_EVENT_GENERATORS;
300                 _enable_midi_generators = true;
301         }
302         else {
303                 _n_midi_inputs = _n_midi_outputs = 0;
304         }
305         return 0;
306 }
307
308 std::string
309 DummyAudioBackend::midi_option () const
310 {
311         return ""; // TODO
312 }
313
314 /* State Control */
315
316 static void * pthread_process (void *arg)
317 {
318         DummyAudioBackend *d = static_cast<DummyAudioBackend *>(arg);
319         d->main_process_thread ();
320         pthread_exit (0);
321         return 0;
322 }
323
324 int
325 DummyAudioBackend::_start (bool /*for_latency_measurement*/)
326 {
327         if (_running) {
328                 PBD::error << _("DummyAudioBackend: already active.") << endmsg;
329                 return -1;
330         }
331
332         if (_ports.size()) {
333                 PBD::warning << _("DummyAudioBackend: recovering from unclean shutdown, port registry is not empty.") << endmsg;
334                 for (std::vector<DummyPort*>::const_iterator it = _ports.begin (); it != _ports.end (); ++it) {
335                         PBD::info << _("DummyAudioBackend: port '") << (*it)->name () << "' exists." << endmsg;
336                 }
337                 _system_inputs.clear();
338                 _system_midi_in.clear();
339                 _ports.clear();
340         }
341
342         if (register_system_ports()) {
343                 PBD::error << _("DummyAudioBackend: failed to register system ports.") << endmsg;
344                 return -1;
345         }
346
347         engine.sample_rate_change (_samplerate);
348         engine.buffer_size_change (_samples_per_period);
349
350         if (engine.reestablish_ports ()) {
351                 PBD::error << _("DummyAudioBackend: Could not re-establish ports.") << endmsg;
352                 stop ();
353                 return -1;
354         }
355
356         engine.reconnect_ports ();
357         _port_change_flag = false;
358
359         if (pthread_create (&_main_thread, NULL, pthread_process, this)) {
360                 PBD::error << _("DummyAudioBackend: cannot start.") << endmsg;
361         }
362
363         int timeout = 5000;
364         while (!_running && --timeout > 0) { Glib::usleep (1000); }
365
366         if (timeout == 0 || !_running) {
367                 PBD::error << _("DummyAudioBackend: failed to start process thread.") << endmsg;
368                 return -1;
369         }
370
371         return 0;
372 }
373
374 int
375 DummyAudioBackend::stop ()
376 {
377         void *status;
378         if (!_running) {
379                 return 0;
380         }
381
382         _running = false;
383         if (pthread_join (_main_thread, &status)) {
384                 PBD::error << _("DummyAudioBackend: failed to terminate.") << endmsg;
385                 return -1;
386         }
387         unregister_ports();
388         return 0;
389 }
390
391 int
392 DummyAudioBackend::freewheel (bool onoff)
393 {
394         if (onoff == _freewheeling) {
395                 return 0;
396         }
397         _freewheeling = onoff;
398         engine.freewheel_callback (onoff);
399         return 0;
400 }
401
402 float
403 DummyAudioBackend::dsp_load () const
404 {
405         return 100.f * _dsp_load;
406 }
407
408 size_t
409 DummyAudioBackend::raw_buffer_size (DataType t)
410 {
411         switch (t) {
412                 case DataType::AUDIO:
413                         return _samples_per_period * sizeof(Sample);
414                 case DataType::MIDI:
415                         return _max_buffer_size; // XXX not really limited
416         }
417         return 0;
418 }
419
420 /* Process time */
421 pframes_t
422 DummyAudioBackend::sample_time ()
423 {
424         return _processed_samples;
425 }
426
427 pframes_t
428 DummyAudioBackend::sample_time_at_cycle_start ()
429 {
430         return _processed_samples;
431 }
432
433 pframes_t
434 DummyAudioBackend::samples_since_cycle_start ()
435 {
436         return 0;
437 }
438
439
440 void *
441 DummyAudioBackend::dummy_process_thread (void *arg)
442 {
443         ThreadData* td = reinterpret_cast<ThreadData*> (arg);
444         boost::function<void ()> f = td->f;
445         delete td;
446         f ();
447         return 0;
448 }
449
450 int
451 DummyAudioBackend::create_process_thread (boost::function<void()> func)
452 {
453         pthread_t thread_id;
454         pthread_attr_t attr;
455         size_t stacksize = 100000;
456
457         pthread_attr_init (&attr);
458         pthread_attr_setstacksize (&attr, stacksize);
459         ThreadData* td = new ThreadData (this, func, stacksize);
460
461         if (pthread_create (&thread_id, &attr, dummy_process_thread, td)) {
462                 PBD::error << _("AudioEngine: cannot create process thread.") << endmsg;
463                 pthread_attr_destroy (&attr);
464                 return -1;
465         }
466         pthread_attr_destroy (&attr);
467
468         _threads.push_back (thread_id);
469         return 0;
470 }
471
472 int
473 DummyAudioBackend::join_process_threads ()
474 {
475         int rv = 0;
476
477         for (std::vector<pthread_t>::const_iterator i = _threads.begin (); i != _threads.end (); ++i)
478         {
479                 void *status;
480                 if (pthread_join (*i, &status)) {
481                         PBD::error << _("AudioEngine: cannot terminate process thread.") << endmsg;
482                         rv -= 1;
483                 }
484         }
485         _threads.clear ();
486         return rv;
487 }
488
489 bool
490 DummyAudioBackend::in_process_thread ()
491 {
492         for (std::vector<pthread_t>::const_iterator i = _threads.begin (); i != _threads.end (); ++i)
493         {
494                 if (pthread_equal (*i, pthread_self ()) != 0) {
495                         return true;
496                 }
497         }
498         return false;
499 }
500
501 uint32_t
502 DummyAudioBackend::process_thread_count ()
503 {
504         return _threads.size ();
505 }
506
507 void
508 DummyAudioBackend::update_latencies ()
509 {
510         // trigger latency callback in RT thread (locked graph)
511         port_connect_add_remove_callback();
512 }
513
514 /* PORTENGINE API */
515
516 void*
517 DummyAudioBackend::private_handle () const
518 {
519         return NULL;
520 }
521
522 const std::string&
523 DummyAudioBackend::my_name () const
524 {
525         return _instance_name;
526 }
527
528 bool
529 DummyAudioBackend::available () const
530 {
531         return true;
532 }
533
534 uint32_t
535 DummyAudioBackend::port_name_size () const
536 {
537         return 256;
538 }
539
540 int
541 DummyAudioBackend::set_port_name (PortEngine::PortHandle port, const std::string& name)
542 {
543         if (!valid_port (port)) {
544                 PBD::error << _("DummyBackend::set_port_name: Invalid Port(s)") << endmsg;
545                 return -1;
546         }
547         return static_cast<DummyPort*>(port)->set_name (_instance_name + ":" + name);
548 }
549
550 std::string
551 DummyAudioBackend::get_port_name (PortEngine::PortHandle port) const
552 {
553         if (!valid_port (port)) {
554                 PBD::error << _("DummyBackend::get_port_name: Invalid Port(s)") << endmsg;
555                 return std::string ();
556         }
557         return static_cast<DummyPort*>(port)->name ();
558 }
559
560 PortEngine::PortHandle
561 DummyAudioBackend::get_port_by_name (const std::string& name) const
562 {
563         PortHandle port = (PortHandle) find_port (name);
564         return port;
565 }
566
567 int
568 DummyAudioBackend::get_ports (
569                 const std::string& port_name_pattern,
570                 DataType type, PortFlags flags,
571                 std::vector<std::string>& port_names) const
572 {
573         int rv = 0;
574         regex_t port_regex;
575         bool use_regexp = false;
576         if (port_name_pattern.size () > 0) {
577                 if (!regcomp (&port_regex, port_name_pattern.c_str (), REG_EXTENDED|REG_NOSUB)) {
578                         use_regexp = true;
579                 }
580         }
581         for (size_t i = 0; i < _ports.size (); ++i) {
582                 DummyPort* port = _ports[i];
583                 if ((port->type () == type) && (port->flags () & flags)) {
584                         if (!use_regexp || !regexec (&port_regex, port->name ().c_str (), 0, NULL, 0)) {
585                                 port_names.push_back (port->name ());
586                                 ++rv;
587                         }
588                 }
589         }
590         if (use_regexp) {
591                 regfree (&port_regex);
592         }
593         return rv;
594 }
595
596 DataType
597 DummyAudioBackend::port_data_type (PortEngine::PortHandle port) const
598 {
599         if (!valid_port (port)) {
600                 return DataType::NIL;
601         }
602         return static_cast<DummyPort*>(port)->type ();
603 }
604
605 PortEngine::PortHandle
606 DummyAudioBackend::register_port (
607                 const std::string& name,
608                 ARDOUR::DataType type,
609                 ARDOUR::PortFlags flags)
610 {
611         if (name.size () == 0) { return 0; }
612         if (flags & IsPhysical) { return 0; }
613         if (!_running) {
614                 PBD::info << _("DummyBackend::register_port: Engine is not running.") << endmsg;
615         }
616         return add_port (_instance_name + ":" + name, type, flags);
617 }
618
619 PortEngine::PortHandle
620 DummyAudioBackend::add_port (
621                 const std::string& name,
622                 ARDOUR::DataType type,
623                 ARDOUR::PortFlags flags)
624 {
625         assert(name.size ());
626         if (find_port (name)) {
627                 PBD::error << _("DummyBackend::register_port: Port already exists:")
628                                 << " (" << name << ")" << endmsg;
629                 return 0;
630         }
631         DummyPort* port = NULL;
632         switch (type) {
633                 case DataType::AUDIO:
634                         port = new DummyAudioPort (*this, name, flags);
635                         break;
636                 case DataType::MIDI:
637                         port = new DummyMidiPort (*this, name, flags);
638                         break;
639                 default:
640                         PBD::error << _("DummyBackend::register_port: Invalid Data Type.") << endmsg;
641                         return 0;
642         }
643
644         _ports.push_back (port);
645
646         return port;
647 }
648
649 void
650 DummyAudioBackend::unregister_port (PortEngine::PortHandle port_handle)
651 {
652         if (!_running) {
653                 PBD::info << _("DummyBackend::unregister_port: Engine is not running.") << endmsg;
654                 assert (!valid_port (port_handle));
655                 return;
656         }
657         DummyPort* port = static_cast<DummyPort*>(port_handle);
658         std::vector<DummyPort*>::iterator i = std::find (_ports.begin (), _ports.end (), static_cast<DummyPort*>(port_handle));
659         if (i == _ports.end ()) {
660                 PBD::error << _("DummyBackend::unregister_port: Failed to find port") << endmsg;
661                 return;
662         }
663         disconnect_all(port_handle);
664         _ports.erase (i);
665         delete port;
666 }
667
668 int
669 DummyAudioBackend::register_system_ports()
670 {
671         LatencyRange lr;
672         enum DummyAudioPort::GeneratorType gt;
673         if (_device == _("Uniform White Noise")) {
674                 gt = DummyAudioPort::UniformWhiteNoise;
675         } else if (_device == _("Gaussian White Noise")) {
676                 gt = DummyAudioPort::GaussianWhiteNoise;
677         } else if (_device == _("Pink Noise")) {
678                 gt = DummyAudioPort::PinkNoise;
679         } else if (_device == _("Pink Noise (low CPU)")) {
680                 gt = DummyAudioPort::PonyNoise;
681         } else if (_device == _("Sine Wave")) {
682                 gt = DummyAudioPort::SineWave;
683         } else if (_device == _("Square Wave")) {
684                 gt = DummyAudioPort::SquareWave;
685         } else if (_device == _("Impulses")) {
686                 gt = DummyAudioPort::KronekerDelta;
687         } else if (_device == _("Sine Sweep")) {
688                 gt = DummyAudioPort::SineSweep;
689         } else if (_device == _("Sine Sweep Swell")) {
690                 gt = DummyAudioPort::SineSweepSwell;
691         } else {
692                 gt = DummyAudioPort::Silence;
693         }
694
695         const int a_ins = _n_inputs > 0 ? _n_inputs : 8;
696         const int a_out = _n_outputs > 0 ? _n_outputs : 8;
697         const int m_ins = _n_midi_inputs;
698         const int m_out = _n_midi_outputs;
699
700         /* audio ports */
701         lr.min = lr.max = _samples_per_period + _systemic_input_latency;
702         for (int i = 1; i <= a_ins; ++i) {
703                 char tmp[64];
704                 snprintf(tmp, sizeof(tmp), "system:capture_%d", i);
705                 PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
706                 if (!p) return -1;
707                 set_latency_range (p, false, lr);
708                 _system_inputs.push_back (static_cast<DummyAudioPort*>(p));
709                 static_cast<DummyAudioPort*>(p)->setup_generator (gt, _samplerate);
710         }
711
712         lr.min = lr.max = _samples_per_period + _systemic_output_latency;
713         for (int i = 1; i <= a_out; ++i) {
714                 char tmp[64];
715                 snprintf(tmp, sizeof(tmp), "system:playback_%d", i);
716                 PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
717                 if (!p) return -1;
718                 set_latency_range (p, true, lr);
719         }
720
721         /* midi ports */
722         lr.min = lr.max = _samples_per_period + _systemic_input_latency;
723         for (int i = 1; i <= m_ins; ++i) {
724                 char tmp[64];
725                 snprintf(tmp, sizeof(tmp), "system:midi_capture_%d", i);
726                 PortHandle p = add_port(std::string(tmp), DataType::MIDI, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
727                 if (!p) return -1;
728                 set_latency_range (p, false, lr);
729                 _system_midi_in.push_back (static_cast<DummyMidiPort*>(p));
730                 if (_enable_midi_generators) {
731                         static_cast<DummyMidiPort*>(p)->setup_generator (i % NUM_MIDI_EVENT_GENERATORS, _samplerate);
732                 }
733         }
734
735         lr.min = lr.max = _samples_per_period + _systemic_output_latency;
736         for (int i = 1; i <= m_out; ++i) {
737                 char tmp[64];
738                 snprintf(tmp, sizeof(tmp), "system:midi_playback_%d", i);
739                 PortHandle p = add_port(std::string(tmp), DataType::MIDI, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
740                 if (!p) return -1;
741                 set_latency_range (p, true, lr);
742         }
743         return 0;
744 }
745
746 void
747 DummyAudioBackend::unregister_ports (bool system_only)
748 {
749         size_t i = 0;
750         _system_inputs.clear();
751         _system_midi_in.clear();
752         while (i <  _ports.size ()) {
753                 DummyPort* port = _ports[i];
754                 if (! system_only || (port->is_physical () && port->is_terminal ())) {
755                         port->disconnect_all ();
756                         delete port;
757                         _ports.erase (_ports.begin() + i);
758                 } else {
759                         ++i;
760                 }
761         }
762 }
763
764 int
765 DummyAudioBackend::connect (const std::string& src, const std::string& dst)
766 {
767         DummyPort* src_port = find_port (src);
768         DummyPort* dst_port = find_port (dst);
769
770         if (!src_port) {
771                 PBD::error << _("DummyBackend::connect: Invalid Source port:")
772                                 << " (" << src <<")" << endmsg;
773                 return -1;
774         }
775         if (!dst_port) {
776                 PBD::error << _("DummyBackend::connect: Invalid Destination port:")
777                         << " (" << dst <<")" << endmsg;
778                 return -1;
779         }
780         return src_port->connect (dst_port);
781 }
782
783 int
784 DummyAudioBackend::disconnect (const std::string& src, const std::string& dst)
785 {
786         DummyPort* src_port = find_port (src);
787         DummyPort* dst_port = find_port (dst);
788
789         if (!src_port || !dst_port) {
790                 PBD::error << _("DummyBackend::disconnect: Invalid Port(s)") << endmsg;
791                 return -1;
792         }
793         return src_port->disconnect (dst_port);
794 }
795
796 int
797 DummyAudioBackend::connect (PortEngine::PortHandle src, const std::string& dst)
798 {
799         DummyPort* dst_port = find_port (dst);
800         if (!valid_port (src)) {
801                 PBD::error << _("DummyBackend::connect: Invalid Source Port Handle") << endmsg;
802                 return -1;
803         }
804         if (!dst_port) {
805                 PBD::error << _("DummyBackend::connect: Invalid Destination Port")
806                         << " (" << dst << ")" << endmsg;
807                 return -1;
808         }
809         return static_cast<DummyPort*>(src)->connect (dst_port);
810 }
811
812 int
813 DummyAudioBackend::disconnect (PortEngine::PortHandle src, const std::string& dst)
814 {
815         DummyPort* dst_port = find_port (dst);
816         if (!valid_port (src) || !dst_port) {
817                 PBD::error << _("DummyBackend::disconnect: Invalid Port(s)") << endmsg;
818                 return -1;
819         }
820         return static_cast<DummyPort*>(src)->disconnect (dst_port);
821 }
822
823 int
824 DummyAudioBackend::disconnect_all (PortEngine::PortHandle port)
825 {
826         if (!valid_port (port)) {
827                 PBD::error << _("DummyBackend::disconnect_all: Invalid Port") << endmsg;
828                 return -1;
829         }
830         static_cast<DummyPort*>(port)->disconnect_all ();
831         return 0;
832 }
833
834 bool
835 DummyAudioBackend::connected (PortEngine::PortHandle port, bool /* process_callback_safe*/)
836 {
837         if (!valid_port (port)) {
838                 PBD::error << _("DummyBackend::disconnect_all: Invalid Port") << endmsg;
839                 return false;
840         }
841         return static_cast<DummyPort*>(port)->is_connected ();
842 }
843
844 bool
845 DummyAudioBackend::connected_to (PortEngine::PortHandle src, const std::string& dst, bool /*process_callback_safe*/)
846 {
847         DummyPort* dst_port = find_port (dst);
848         if (!valid_port (src) || !dst_port) {
849                 PBD::error << _("DummyBackend::connected_to: Invalid Port") << endmsg;
850                 return false;
851         }
852         return static_cast<DummyPort*>(src)->is_connected (dst_port);
853 }
854
855 bool
856 DummyAudioBackend::physically_connected (PortEngine::PortHandle port, bool /*process_callback_safe*/)
857 {
858         if (!valid_port (port)) {
859                 PBD::error << _("DummyBackend::physically_connected: Invalid Port") << endmsg;
860                 return false;
861         }
862         return static_cast<DummyPort*>(port)->is_physically_connected ();
863 }
864
865 int
866 DummyAudioBackend::get_connections (PortEngine::PortHandle port, std::vector<std::string>& names, bool /*process_callback_safe*/)
867 {
868         if (!valid_port (port)) {
869                 PBD::error << _("DummyBackend::get_connections: Invalid Port") << endmsg;
870                 return -1;
871         }
872
873         assert (0 == names.size ());
874
875         const std::vector<DummyPort*>& connected_ports = static_cast<DummyPort*>(port)->get_connections ();
876
877         for (std::vector<DummyPort*>::const_iterator i = connected_ports.begin (); i != connected_ports.end (); ++i) {
878                 names.push_back ((*i)->name ());
879         }
880
881         return (int)names.size ();
882 }
883
884 /* MIDI */
885 int
886 DummyAudioBackend::midi_event_get (
887                 pframes_t& timestamp,
888                 size_t& size, uint8_t** buf, void* port_buffer,
889                 uint32_t event_index)
890 {
891         assert (buf && port_buffer);
892         DummyMidiBuffer& source = * static_cast<DummyMidiBuffer*>(port_buffer);
893         if (event_index >= source.size ()) {
894                 return -1;
895         }
896         DummyMidiEvent * const event = source[event_index].get ();
897
898         timestamp = event->timestamp ();
899         size = event->size ();
900         *buf = event->data ();
901         return 0;
902 }
903
904 int
905 DummyAudioBackend::midi_event_put (
906                 void* port_buffer,
907                 pframes_t timestamp,
908                 const uint8_t* buffer, size_t size)
909 {
910         assert (buffer && port_buffer);
911         DummyMidiBuffer& dst = * static_cast<DummyMidiBuffer*>(port_buffer);
912         if (dst.size () && (pframes_t)dst.back ()->timestamp () > timestamp) {
913                 fprintf (stderr, "DummyMidiBuffer: it's too late for this event.\n");
914                 return -1;
915         }
916         dst.push_back (boost::shared_ptr<DummyMidiEvent>(new DummyMidiEvent (timestamp, buffer, size)));
917         return 0;
918 }
919
920 uint32_t
921 DummyAudioBackend::get_midi_event_count (void* port_buffer)
922 {
923         assert (port_buffer);
924         return static_cast<DummyMidiBuffer*>(port_buffer)->size ();
925 }
926
927 void
928 DummyAudioBackend::midi_clear (void* port_buffer)
929 {
930         assert (port_buffer);
931         DummyMidiBuffer * buf = static_cast<DummyMidiBuffer*>(port_buffer);
932         assert (buf);
933         buf->clear ();
934 }
935
936 /* Monitoring */
937
938 bool
939 DummyAudioBackend::can_monitor_input () const
940 {
941         return false;
942 }
943
944 int
945 DummyAudioBackend::request_input_monitoring (PortEngine::PortHandle, bool)
946 {
947         return -1;
948 }
949
950 int
951 DummyAudioBackend::ensure_input_monitoring (PortEngine::PortHandle, bool)
952 {
953         return -1;
954 }
955
956 bool
957 DummyAudioBackend::monitoring_input (PortEngine::PortHandle)
958 {
959         return false;
960 }
961
962 /* Latency management */
963
964 void
965 DummyAudioBackend::set_latency_range (PortEngine::PortHandle port, bool for_playback, LatencyRange latency_range)
966 {
967         if (!valid_port (port)) {
968                 PBD::error << _("DummyPort::set_latency_range (): invalid port.") << endmsg;
969         }
970         static_cast<DummyPort*>(port)->set_latency_range (latency_range, for_playback);
971 }
972
973 LatencyRange
974 DummyAudioBackend::get_latency_range (PortEngine::PortHandle port, bool for_playback)
975 {
976         if (!valid_port (port)) {
977                 PBD::error << _("DummyPort::get_latency_range (): invalid port.") << endmsg;
978                 LatencyRange r;
979                 r.min = 0;
980                 r.max = 0;
981                 return r;
982         }
983         return static_cast<DummyPort*>(port)->latency_range (for_playback);
984 }
985
986 /* Discovering physical ports */
987
988 bool
989 DummyAudioBackend::port_is_physical (PortEngine::PortHandle port) const
990 {
991         if (!valid_port (port)) {
992                 PBD::error << _("DummyPort::port_is_physical (): invalid port.") << endmsg;
993                 return false;
994         }
995         return static_cast<DummyPort*>(port)->is_physical ();
996 }
997
998 void
999 DummyAudioBackend::get_physical_outputs (DataType type, std::vector<std::string>& port_names)
1000 {
1001         for (size_t i = 0; i < _ports.size (); ++i) {
1002                 DummyPort* port = _ports[i];
1003                 if ((port->type () == type) && port->is_input () && port->is_physical ()) {
1004                         port_names.push_back (port->name ());
1005                 }
1006         }
1007 }
1008
1009 void
1010 DummyAudioBackend::get_physical_inputs (DataType type, std::vector<std::string>& port_names)
1011 {
1012         for (size_t i = 0; i < _ports.size (); ++i) {
1013                 DummyPort* port = _ports[i];
1014                 if ((port->type () == type) && port->is_output () && port->is_physical ()) {
1015                         port_names.push_back (port->name ());
1016                 }
1017         }
1018 }
1019
1020 ChanCount
1021 DummyAudioBackend::n_physical_outputs () const
1022 {
1023         int n_midi = 0;
1024         int n_audio = 0;
1025         for (size_t i = 0; i < _ports.size (); ++i) {
1026                 DummyPort* port = _ports[i];
1027                 if (port->is_output () && port->is_physical ()) {
1028                         switch (port->type ()) {
1029                                 case DataType::AUDIO: ++n_audio; break;
1030                                 case DataType::MIDI: ++n_midi; break;
1031                                 default: break;
1032                         }
1033                 }
1034         }
1035         ChanCount cc;
1036         cc.set (DataType::AUDIO, n_audio);
1037         cc.set (DataType::MIDI, n_midi);
1038         return cc;
1039 }
1040
1041 ChanCount
1042 DummyAudioBackend::n_physical_inputs () const
1043 {
1044         int n_midi = 0;
1045         int n_audio = 0;
1046         for (size_t i = 0; i < _ports.size (); ++i) {
1047                 DummyPort* port = _ports[i];
1048                 if (port->is_input () && port->is_physical ()) {
1049                         switch (port->type ()) {
1050                                 case DataType::AUDIO: ++n_audio; break;
1051                                 case DataType::MIDI: ++n_midi; break;
1052                                 default: break;
1053                         }
1054                 }
1055         }
1056         ChanCount cc;
1057         cc.set (DataType::AUDIO, n_audio);
1058         cc.set (DataType::MIDI, n_midi);
1059         return cc;
1060 }
1061
1062 /* Getting access to the data buffer for a port */
1063
1064 void*
1065 DummyAudioBackend::get_buffer (PortEngine::PortHandle port, pframes_t nframes)
1066 {
1067         assert (port);
1068         assert (valid_port (port));
1069         return static_cast<DummyPort*>(port)->get_buffer (nframes);
1070 }
1071
1072 /* Engine Process */
1073 void *
1074 DummyAudioBackend::main_process_thread ()
1075 {
1076         AudioEngine::thread_init_callback (this);
1077         _running = true;
1078         _processed_samples = 0;
1079
1080         manager.registration_callback();
1081         manager.graph_order_callback();
1082
1083         uint64_t clock1, clock2;
1084         clock1 = g_get_monotonic_time();
1085         while (_running) {
1086
1087                 // re-set input buffers, generate on demand.
1088                 for (std::vector<DummyAudioPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
1089                         (*it)->next_period();
1090                 }
1091                 for (std::vector<DummyMidiPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it) {
1092                         (*it)->next_period();
1093                 }
1094
1095                 if (engine.process_callback (_samples_per_period)) {
1096                         return 0;
1097                 }
1098                 _processed_samples += _samples_per_period;
1099                 if (!_freewheeling) {
1100                         clock2 = g_get_monotonic_time();
1101                         const int64_t elapsed_time = clock2 - clock1;
1102                         const int64_t nomial_time = 1e6 * _samples_per_period / _samplerate;
1103                         _dsp_load = elapsed_time / (float) nomial_time;
1104                         if (elapsed_time < nomial_time) {
1105                                 Glib::usleep (nomial_time - elapsed_time);
1106                         } else {
1107                                 Glib::usleep (100); // don't hog cpu
1108                         }
1109                 } else {
1110                         _dsp_load = 1.0f;
1111                         Glib::usleep (100); // don't hog cpu
1112                 }
1113                 clock1 = g_get_monotonic_time();
1114
1115                 bool connections_changed = false;
1116                 bool ports_changed = false;
1117                 if (!pthread_mutex_trylock (&_port_callback_mutex)) {
1118                         if (_port_change_flag) {
1119                                 ports_changed = true;
1120                                 _port_change_flag = false;
1121                         }
1122                         if (!_port_connection_queue.empty ()) {
1123                                 connections_changed = true;
1124                         }
1125                         while (!_port_connection_queue.empty ()) {
1126                                 PortConnectData *c = _port_connection_queue.back ();
1127                                 manager.connect_callback (c->a, c->b, c->c);
1128                                 _port_connection_queue.pop_back ();
1129                                 delete c;
1130                         }
1131                         pthread_mutex_unlock (&_port_callback_mutex);
1132                 }
1133                 if (ports_changed) {
1134                         manager.registration_callback();
1135                 }
1136                 if (connections_changed) {
1137                         manager.graph_order_callback();
1138                 }
1139                 if (connections_changed || ports_changed) {
1140                         engine.latency_callback(false);
1141                         engine.latency_callback(true);
1142                 }
1143
1144         }
1145         _running = false;
1146         return 0;
1147 }
1148
1149
1150 /******************************************************************************/
1151
1152 static boost::shared_ptr<DummyAudioBackend> _instance;
1153
1154 static boost::shared_ptr<AudioBackend> backend_factory (AudioEngine& e);
1155 static int instantiate (const std::string& arg1, const std::string& /* arg2 */);
1156 static int deinstantiate ();
1157 static bool already_configured ();
1158
1159 static ARDOUR::AudioBackendInfo _descriptor = {
1160         "Dummy",
1161         instantiate,
1162         deinstantiate,
1163         backend_factory,
1164         already_configured,
1165 };
1166
1167 static boost::shared_ptr<AudioBackend>
1168 backend_factory (AudioEngine& e)
1169 {
1170         if (!_instance) {
1171                 _instance.reset (new DummyAudioBackend (e, _descriptor));
1172         }
1173         return _instance;
1174 }
1175
1176 static int
1177 instantiate (const std::string& arg1, const std::string& /* arg2 */)
1178 {
1179         s_instance_name = arg1;
1180         return 0;
1181 }
1182
1183 static int
1184 deinstantiate ()
1185 {
1186         _instance.reset ();
1187         return 0;
1188 }
1189
1190 static bool
1191 already_configured ()
1192 {
1193         return false;
1194 }
1195
1196 extern "C" ARDOURBACKEND_API ARDOUR::AudioBackendInfo* descriptor ()
1197 {
1198         return &_descriptor;
1199 }
1200
1201
1202 /******************************************************************************/
1203 DummyPort::DummyPort (DummyAudioBackend &b, const std::string& name, PortFlags flags)
1204         : _dummy_backend (b)
1205         , _name  (name)
1206         , _flags (flags)
1207         , _rseed (0)
1208         , _gen_cycle (false)
1209 {
1210         _capture_latency_range.min = 0;
1211         _capture_latency_range.max = 0;
1212         _playback_latency_range.min = 0;
1213         _playback_latency_range.max = 0;
1214         _dummy_backend.port_connect_add_remove_callback();
1215 }
1216
1217 DummyPort::~DummyPort () {
1218         disconnect_all ();
1219         _dummy_backend.port_connect_add_remove_callback();
1220 }
1221
1222
1223 int DummyPort::connect (DummyPort *port)
1224 {
1225         if (!port) {
1226                 PBD::error << _("DummyPort::connect (): invalid (null) port") << endmsg;
1227                 return -1;
1228         }
1229
1230         if (type () != port->type ()) {
1231                 PBD::error << _("DummyPort::connect (): wrong port-type") << endmsg;
1232                 return -1;
1233         }
1234
1235         if (is_output () && port->is_output ()) {
1236                 PBD::error << _("DummyPort::connect (): cannot inter-connect output ports.") << endmsg;
1237                 return -1;
1238         }
1239
1240         if (is_input () && port->is_input ()) {
1241                 PBD::error << _("DummyPort::connect (): cannot inter-connect input ports.") << endmsg;
1242                 return -1;
1243         }
1244
1245         if (this == port) {
1246                 PBD::error << _("DummyPort::connect (): cannot self-connect ports.") << endmsg;
1247                 return -1;
1248         }
1249
1250         if (is_connected (port)) {
1251 #if 0 // don't bother to warn about this for now. just ignore it
1252                 PBD::error << _("DummyPort::connect (): ports are already connected:")
1253                         << " (" << name () << ") -> (" << port->name () << ")"
1254                         << endmsg;
1255 #endif
1256                 return -1;
1257         }
1258
1259         _connect (port, true);
1260         return 0;
1261 }
1262
1263
1264 void DummyPort::_connect (DummyPort *port, bool callback)
1265 {
1266         _connections.push_back (port);
1267         if (callback) {
1268                 port->_connect (this, false);
1269                 _dummy_backend.port_connect_callback (name(),  port->name(), true);
1270         }
1271 }
1272
1273 int DummyPort::disconnect (DummyPort *port)
1274 {
1275         if (!port) {
1276                 PBD::error << _("DummyPort::disconnect (): invalid (null) port") << endmsg;
1277                 return -1;
1278         }
1279
1280         if (!is_connected (port)) {
1281                 PBD::error << _("DummyPort::disconnect (): ports are not connected:")
1282                         << " (" << name () << ") -> (" << port->name () << ")"
1283                         << endmsg;
1284                 return -1;
1285         }
1286         _disconnect (port, true);
1287         return 0;
1288 }
1289
1290 void DummyPort::_disconnect (DummyPort *port, bool callback)
1291 {
1292         std::vector<DummyPort*>::iterator it = std::find (_connections.begin (), _connections.end (), port);
1293
1294         assert (it != _connections.end ());
1295
1296         _connections.erase (it);
1297
1298         if (callback) {
1299                 port->_disconnect (this, false);
1300                 _dummy_backend.port_connect_callback (name(),  port->name(), false);
1301         }
1302 }
1303
1304
1305 void DummyPort::disconnect_all ()
1306 {
1307         while (!_connections.empty ()) {
1308                 _connections.back ()->_disconnect (this, false);
1309                 _dummy_backend.port_connect_callback (name(),  _connections.back ()->name(), false);
1310                 _connections.pop_back ();
1311         }
1312 }
1313
1314 bool
1315 DummyPort::is_connected (const DummyPort *port) const
1316 {
1317         return std::find (_connections.begin (), _connections.end (), port) != _connections.end ();
1318 }
1319
1320 bool DummyPort::is_physically_connected () const
1321 {
1322         for (std::vector<DummyPort*>::const_iterator it = _connections.begin (); it != _connections.end (); ++it) {
1323                 if ((*it)->is_physical ()) {
1324                         return true;
1325                 }
1326         }
1327         return false;
1328 }
1329
1330 void DummyPort::setup_random_number_generator ()
1331 {
1332         _rseed = g_get_monotonic_time() % UINT_MAX;
1333 }
1334
1335 inline uint32_t
1336 DummyPort::randi ()
1337 {
1338         // 31bit Park-Miller-Carta Pseudo-Random Number Generator
1339         // http://www.firstpr.com.au/dsp/rand31/
1340         uint32_t hi, lo;
1341         lo = 16807 * (_rseed & 0xffff);
1342         hi = 16807 * (_rseed >> 16);
1343
1344         lo += (hi & 0x7fff) << 16;
1345         lo += hi >> 15;
1346 #if 1
1347         lo = (lo & 0x7fffffff) + (lo >> 31);
1348 #else
1349         if (lo > 0x7fffffff) { lo -= 0x7fffffff; }
1350 #endif
1351         return (_rseed = lo);
1352 }
1353
1354 inline float
1355 DummyPort::randf ()
1356 {
1357         return (randi() / 1073741824.f) - 1.f;
1358 }
1359
1360 /******************************************************************************/
1361
1362 DummyAudioPort::DummyAudioPort (DummyAudioBackend &b, const std::string& name, PortFlags flags)
1363         : DummyPort (b, name, flags)
1364         , _gen_type (Silence)
1365         , _b0 (0)
1366         , _b1 (0)
1367         , _b2 (0)
1368         , _b3 (0)
1369         , _b4 (0)
1370         , _b5 (0)
1371         , _b6 (0)
1372         , _wavetable (0)
1373         , _gen_period (0)
1374         , _gen_offset (0)
1375         , _gen_perio2 (0)
1376         , _gen_count2 (0)
1377         , _pass (false)
1378         , _rn1 (0)
1379 {
1380         memset (_buffer, 0, sizeof (_buffer));
1381 }
1382
1383 DummyAudioPort::~DummyAudioPort () {
1384         free(_wavetable);
1385         _wavetable = 0;
1386 }
1387
1388 void DummyAudioPort::setup_generator (GeneratorType const g, float const samplerate)
1389 {
1390         DummyPort::setup_random_number_generator();
1391         _gen_type = g;
1392
1393         switch (_gen_type) {
1394                 case PinkNoise:
1395                 case PonyNoise:
1396                 case UniformWhiteNoise:
1397                 case GaussianWhiteNoise:
1398                 case Silence:
1399                         break;
1400                 case KronekerDelta:
1401                         _gen_period = (5 + randi() % (int)(samplerate / 20.f));
1402                         break;
1403                 case SquareWave:
1404                         _gen_period = (5 + randi() % (int)(samplerate / 20.f)) & ~1;
1405                         break;
1406                 case SineWave:
1407                         _gen_period = 5 + randi() % (int)(samplerate / 20.f);
1408                         _wavetable = (Sample*) malloc (_gen_period * sizeof(Sample));
1409                         for (uint32_t i = 0 ; i < _gen_period; ++i) {
1410                                 _wavetable[i] = .12589f * sinf(2.0f * M_PI * (float)i / (float)_gen_period); // -18dBFS
1411                         }
1412                         break;
1413                 case SineSweep:
1414                 case SineSweepSwell:
1415                         {
1416                                 _gen_period = 5 * samplerate + randi() % (int)(samplerate * 10.f);
1417                                 _wavetable = (Sample*) malloc (_gen_period * sizeof(Sample));
1418                                 _gen_perio2 = 1 | (int)ceilf (_gen_period * .89f); // Volume Swell period
1419                                 const double f_min = 20.;
1420                                 const double f_max = samplerate * .5;
1421 #ifdef LINEAR_SWEEP
1422                                 const double b = (f_max - f_min) / (2. * samplerate * _gen_period);
1423                                 const double a = f_min / samplerate;
1424 #else
1425                                 const double b = log (f_max / f_min) / _gen_period;
1426                                 const double a = f_min / (b * samplerate);
1427 #endif
1428                                 for (uint32_t i = 0 ; i < _gen_period; ++i) {
1429 #ifdef LINEAR_SWEEP
1430                                         const double phase = i * (a + b * i);
1431 #else
1432                                         const double phase = a * exp (b * i) - a;
1433 #endif
1434                                         _wavetable[i] = (float)sin (2. * M_PI * (phase - floor (phase)));
1435                                 }
1436                         }
1437                         break;
1438         }
1439 }
1440
1441 float DummyAudioPort::grandf ()
1442 {
1443         // Gaussian White Noise
1444         // http://www.musicdsp.org/archive.php?classid=0#109
1445         float x1, x2, r;
1446
1447         if (_pass) {
1448                 _pass = false;
1449                 return _rn1;
1450         }
1451
1452         do {
1453                 x1 = randf ();
1454                 x2 = randf ();
1455                 r = x1 * x1 + x2 * x2;
1456         } while ((r >= 1.0f) || (r < 1e-22f));
1457
1458         r = sqrtf (-2.f * logf (r) / r);
1459
1460         _pass = true;
1461         _rn1 = r * x2;
1462         return r * x1;
1463 }
1464
1465 void DummyAudioPort::generate (const pframes_t n_samples)
1466 {
1467         Glib::Threads::Mutex::Lock lm (generator_lock);
1468         if (_gen_cycle) {
1469                 return;
1470         }
1471
1472         switch (_gen_type) {
1473                 case Silence:
1474                         memset (_buffer, 0, n_samples * sizeof (Sample));
1475                         break;
1476                 case SquareWave:
1477                         assert(_gen_period > 0);
1478                         for (pframes_t i = 0 ; i < n_samples; ++i) {
1479                                 if (_gen_offset < _gen_period * .5f) {
1480                                         _buffer[i] =  .40709f; // -6dBFS
1481                                 } else {
1482                                         _buffer[i] = -.40709f;
1483                                 }
1484                                 _gen_offset = (_gen_offset + 1) % _gen_period;
1485                         }
1486                         break;
1487                 case KronekerDelta:
1488                         assert(_gen_period > 0);
1489                         memset (_buffer, 0, n_samples * sizeof (Sample));
1490                         for (pframes_t i = 0; i < n_samples; ++i) {
1491                                 if (_gen_offset == 0) {
1492                                         _buffer[i] = 1.0f;
1493                                 }
1494                                 _gen_offset = (_gen_offset + 1) % _gen_period;
1495                         }
1496                         break;
1497                 case SineSweepSwell:
1498                         assert(_wavetable && _gen_period > 0);
1499                         {
1500                                 const float vols = 2.f / (float)_gen_perio2;
1501                                 for (pframes_t i = 0; i < n_samples; ++i) {
1502                                         const float g = fabsf (_gen_count2 * vols - 1.0);
1503                                         _buffer[i] = g * _wavetable[_gen_offset];
1504                                         _gen_offset = (_gen_offset + 1) % _gen_period;
1505                                         _gen_count2 = (_gen_count2 + 1) % _gen_perio2;
1506                                 }
1507                         }
1508                         break;
1509                 case SineWave:
1510                 case SineSweep:
1511                         assert(_wavetable && _gen_period > 0);
1512                         {
1513                                 pframes_t written = 0;
1514                                 while (written < n_samples) {
1515                                         const uint32_t remain = n_samples - written;
1516                                         const uint32_t to_copy = std::min(remain, _gen_period - _gen_offset);
1517                                         memcpy((void*)&_buffer[written],
1518                                                         (void*)&_wavetable[_gen_offset],
1519                                                         to_copy * sizeof(Sample));
1520                                         written += to_copy;
1521                                         _gen_offset = (_gen_offset + to_copy) % _gen_period;
1522                                 }
1523                         }
1524                         break;
1525                 case UniformWhiteNoise:
1526                         for (pframes_t i = 0 ; i < n_samples; ++i) {
1527                                 _buffer[i] = .158489f * randf();
1528                         }
1529                         break;
1530                 case GaussianWhiteNoise:
1531                         for (pframes_t i = 0 ; i < n_samples; ++i) {
1532                                 _buffer[i] = .089125f * grandf();
1533                         }
1534                         break;
1535                 case PinkNoise:
1536                         for (pframes_t i = 0 ; i < n_samples; ++i) {
1537                                 // Paul Kellet's refined method
1538                                 // http://www.musicdsp.org/files/pink.txt
1539                                 // NB. If 'white' consists of uniform random numbers,
1540                                 // the pink noise will have an almost gaussian distribution.
1541                                 const float white = .0498f * randf ();
1542                                 _b0 = .99886f * _b0 + white * .0555179f;
1543                                 _b1 = .99332f * _b1 + white * .0750759f;
1544                                 _b2 = .96900f * _b2 + white * .1538520f;
1545                                 _b3 = .86650f * _b3 + white * .3104856f;
1546                                 _b4 = .55000f * _b4 + white * .5329522f;
1547                                 _b5 = -.7616f * _b5 - white * .0168980f;
1548                                 _buffer[i] = _b0 + _b1 + _b2 + _b3 + _b4 + _b5 + _b6 + white * 0.5362f;
1549                                 _b6 = white * 0.115926f;
1550                         }
1551                         break;
1552                 case PonyNoise:
1553                         for (pframes_t i = 0 ; i < n_samples; ++i) {
1554                                 const float white = 0.0498f * randf ();
1555                                 // Paul Kellet's economy method
1556                                 // http://www.musicdsp.org/files/pink.txt
1557                                 _b0 = 0.99765f * _b0 + white * 0.0990460f;
1558                                 _b1 = 0.96300f * _b1 + white * 0.2965164f;
1559                                 _b2 = 0.57000f * _b2 + white * 1.0526913f;
1560                                 _buffer[i] = _b0 + _b1 + _b2 + white * 0.1848f;
1561                         }
1562                         break;
1563         }
1564         _gen_cycle = true;
1565 }
1566
1567 void* DummyAudioPort::get_buffer (pframes_t n_samples)
1568 {
1569         if (is_input ()) {
1570                 std::vector<DummyPort*>::const_iterator it = get_connections ().begin ();
1571                 if (it == get_connections ().end ()) {
1572                         memset (_buffer, 0, n_samples * sizeof (Sample));
1573                 } else {
1574                         DummyAudioPort * source = static_cast<DummyAudioPort*>(*it);
1575                         assert (source && source->is_output ());
1576                         if (source->is_physical() && source->is_terminal()) {
1577                                 source->get_buffer(n_samples); // generate signal.
1578                         }
1579                         memcpy (_buffer, source->const_buffer (), n_samples * sizeof (Sample));
1580                         while (++it != get_connections ().end ()) {
1581                                 source = static_cast<DummyAudioPort*>(*it);
1582                                 assert (source && source->is_output ());
1583                                 Sample* dst = buffer ();
1584                                 if (source->is_physical() && source->is_terminal()) {
1585                                         source->get_buffer(n_samples); // generate signal.
1586                                 }
1587                                 const Sample* src = source->const_buffer ();
1588                                 for (uint32_t s = 0; s < n_samples; ++s, ++dst, ++src) {
1589                                         *dst += *src;
1590                                 }
1591                         }
1592                 }
1593         } else if (is_output () && is_physical () && is_terminal()) {
1594                 if (!_gen_cycle) {
1595                         generate(n_samples);
1596                 }
1597         }
1598         return _buffer;
1599 }
1600
1601
1602 DummyMidiPort::DummyMidiPort (DummyAudioBackend &b, const std::string& name, PortFlags flags)
1603         : DummyPort (b, name, flags)
1604         , _midi_seq_spb (0)
1605         , _midi_seq_time (0)
1606         , _midi_seq_pos (0)
1607 {
1608         _buffer.clear ();
1609 }
1610
1611 DummyMidiPort::~DummyMidiPort () { }
1612
1613 struct MidiEventSorter {
1614         bool operator() (const boost::shared_ptr<DummyMidiEvent>& a, const boost::shared_ptr<DummyMidiEvent>& b) {
1615                 return *a < *b;
1616         }
1617 };
1618
1619 void DummyMidiPort::setup_generator (int seq_id, const float sr)
1620 {
1621         DummyPort::setup_random_number_generator();
1622         switch (seq_id) {
1623                 case 1:
1624                         _midi_seq_dat = DummyMidiData::s1;
1625                         break;
1626                 case 2:
1627                         _midi_seq_dat = DummyMidiData::s2;
1628                         break;
1629                 case 3:
1630                         _midi_seq_dat = DummyMidiData::s3;
1631                         break;
1632                 default:
1633                         _midi_seq_dat = DummyMidiData::s0;
1634                         break;
1635         }
1636         _midi_seq_spb = sr * .5f; // 120 BPM, beat_time 1.0 per beat.
1637         _midi_seq_pos = 0;
1638         _midi_seq_time = 0;
1639 }
1640
1641 void DummyMidiPort::midi_generate (const pframes_t n_samples)
1642 {
1643         Glib::Threads::Mutex::Lock lm (generator_lock);
1644         if (_gen_cycle) {
1645                 return;
1646         }
1647
1648         _buffer.clear ();
1649         _gen_cycle = true;
1650
1651         if (_midi_seq_spb == 0 || !_midi_seq_dat) {
1652                 return;
1653         }
1654
1655         while (1) {
1656                 const int32_t ev_beat_time = _midi_seq_dat[_midi_seq_pos].beat_time * _midi_seq_spb - _midi_seq_time;
1657                 if (ev_beat_time < 0) {
1658                         break;
1659                 }
1660                 if ((pframes_t) ev_beat_time >= n_samples) {
1661                         break;
1662                 }
1663                 _buffer.push_back (boost::shared_ptr<DummyMidiEvent>(new DummyMidiEvent (
1664                                                 ev_beat_time, _midi_seq_dat[_midi_seq_pos].event, 3
1665                                                 )));
1666                 ++_midi_seq_pos;
1667
1668                 if (_midi_seq_dat[_midi_seq_pos].event[0] == 0xff && _midi_seq_dat[_midi_seq_pos].event[1] == 0xff) {
1669                         _midi_seq_time -= _midi_seq_dat[_midi_seq_pos].beat_time * _midi_seq_spb;
1670                         _midi_seq_pos = 0;
1671                 }
1672         }
1673         _midi_seq_time += n_samples;
1674 }
1675
1676
1677 void* DummyMidiPort::get_buffer (pframes_t n_samples)
1678 {
1679         if (is_input ()) {
1680                 _buffer.clear ();
1681                 for (std::vector<DummyPort*>::const_iterator i = get_connections ().begin ();
1682                                 i != get_connections ().end ();
1683                                 ++i) {
1684                         DummyMidiPort * source = static_cast<DummyMidiPort*>(*i);
1685                         if (source->is_physical() && source->is_terminal()) {
1686                                 source->get_buffer(n_samples); // generate signal.
1687                         }
1688                         const DummyMidiBuffer src = static_cast<const DummyMidiPort*>(*i)->const_buffer ();
1689                         for (DummyMidiBuffer::const_iterator it = src.begin (); it != src.end (); ++it) {
1690                                 _buffer.push_back (boost::shared_ptr<DummyMidiEvent>(new DummyMidiEvent (**it)));
1691                         }
1692                 }
1693                 std::sort (_buffer.begin (), _buffer.end (), MidiEventSorter());
1694         } else if (is_output () && is_physical () && is_terminal()) {
1695                 if (!_gen_cycle) {
1696                         midi_generate(n_samples);
1697                 }
1698         }
1699         return &_buffer;
1700 }
1701
1702 DummyMidiEvent::DummyMidiEvent (const pframes_t timestamp, const uint8_t* data, size_t size)
1703         : _size (size)
1704         , _timestamp (timestamp)
1705         , _data (0)
1706 {
1707         if (size > 0) {
1708                 _data = (uint8_t*) malloc (size);
1709          memcpy (_data, data, size);
1710         }
1711 }
1712
1713 DummyMidiEvent::DummyMidiEvent (const DummyMidiEvent& other)
1714         : _size (other.size ())
1715         , _timestamp (other.timestamp ())
1716         , _data (0)
1717 {
1718         if (other.size () && other.const_data ()) {
1719                 _data = (uint8_t*) malloc (other.size ());
1720                 memcpy (_data, other.const_data (), other.size ());
1721         }
1722 };
1723
1724 DummyMidiEvent::~DummyMidiEvent () {
1725         free (_data);
1726 };