From cd4fff863a63ff78afe5ed26f8ccb092c40b4f72 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Tue, 20 Jun 2023 00:36:14 +0200 Subject: [PATCH] Dummy backend: add realtime option On windows this is still limited by the timer resolution, but it's a start. This is mainly intended to be used with NDI or other external sources without actual audio hardware. --- libs/backends/dummy/dummy_audiobackend.cc | 20 +++++++++++++++----- libs/backends/dummy/dummy_audiobackend.h | 9 ++++++--- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/libs/backends/dummy/dummy_audiobackend.cc b/libs/backends/dummy/dummy_audiobackend.cc index aed0a30921..8f9d175eef 100644 --- a/libs/backends/dummy/dummy_audiobackend.cc +++ b/libs/backends/dummy/dummy_audiobackend.cc @@ -65,6 +65,7 @@ DummyAudioBackend::DummyAudioBackend (AudioEngine& e, AudioBackendInfo& info) , _running (false) , _freewheel (false) , _freewheeling (false) + , _realtime (false) , _speedup (1.0) , _device ("") , _samplerate (48000) @@ -85,6 +86,7 @@ DummyAudioBackend::DummyAudioBackend (AudioEngine& e, AudioBackendInfo& info) if (_driver_speed.empty()) { _driver_speed.push_back (DriverSpeed (_("Half Speed"), 2.0f)); _driver_speed.push_back (DriverSpeed (_("Normal Speed"), 1.0f)); + _driver_speed.push_back (DriverSpeed (_("Realtime"), 1.0f, true)); _driver_speed.push_back (DriverSpeed (_("Double Speed"), 0.5f)); _driver_speed.push_back (DriverSpeed (_("5x Speed"), 0.2f)); _driver_speed.push_back (DriverSpeed (_("10x Speed"), 0.1f)); @@ -227,6 +229,7 @@ DummyAudioBackend::set_driver (const std::string& d) for (std::vector::const_iterator it = _driver_speed.begin () ; it != _driver_speed.end (); ++it) { if (d == it->name) { _speedup = it->speedup; + _realtime = it->realtime; return 0; } } @@ -463,7 +466,13 @@ DummyAudioBackend::_start (bool /*for_latency_measurement*/) engine.reconnect_ports (); _port_change_flag.store (0); - if (pbd_pthread_create (PBD_RT_STACKSIZE_PROC, &_main_thread, pthread_process, this)) { + bool ok = _realtime; + if (_realtime && pbd_realtime_pthread_create (PBD_SCHED_FIFO, PBD_RT_PRI_MAIN, PBD_RT_STACKSIZE_PROC, &_main_thread, pthread_process, this)) { + PBD::warning << _("DummyAudioBackend: failed to acquire realtime permissions.") << endmsg; + ok = false; + } + + if (!ok && pbd_pthread_create (PBD_RT_STACKSIZE_PROC, &_main_thread, pthread_process, this)) { PBD::error << _("DummyAudioBackend: cannot start.") << endmsg; } @@ -556,7 +565,8 @@ DummyAudioBackend::create_process_thread (boost::function func) pthread_t thread_id; ThreadData* td = new ThreadData (this, func, PBD_RT_STACKSIZE_PROC); - if (pbd_pthread_create (PBD_RT_STACKSIZE_PROC, &thread_id, dummy_process_thread, td)) { + bool ok = _realtime && 0 == pbd_realtime_pthread_create (PBD_SCHED_FIFO, PBD_RT_PRI_PROC, PBD_RT_STACKSIZE_PROC, &thread_id, dummy_process_thread, td); + if (!ok && pbd_pthread_create (PBD_RT_STACKSIZE_PROC, &thread_id, dummy_process_thread, td)) { PBD::error << _("AudioEngine: cannot create process thread.") << endmsg; return -1; } @@ -997,13 +1007,13 @@ DummyAudioBackend::main_process_thread () const int64_t nominal_time = _dsp_load_calc.get_max_time_us (); if (elapsed_time < nominal_time) { const int64_t sleepy = _speedup * (nominal_time - elapsed_time); - Glib::usleep (std::max ((int64_t) 100, sleepy)); + Glib::usleep (std::max ((int64_t) 10, sleepy)); } else { - Glib::usleep (100); // don't hog cpu + Glib::usleep (10); // don't hog cpu } } else { _dsp_load = 1.0f; - Glib::usleep (100); // don't hog cpu + Glib::usleep (10); // don't hog cpu } /* beginning of next cycle */ diff --git a/libs/backends/dummy/dummy_audiobackend.h b/libs/backends/dummy/dummy_audiobackend.h index 4256e581b5..6631890fa4 100644 --- a/libs/backends/dummy/dummy_audiobackend.h +++ b/libs/backends/dummy/dummy_audiobackend.h @@ -183,9 +183,10 @@ class DummyMidiPort : public DummyPort { DummyMidiData::MIDISequence const * _midi_seq_dat; }; // class DummyMidiPort -class DummyAudioBackend : public AudioBackend, public PortEngineSharedImpl { +class DummyAudioBackend : public AudioBackend, public PortEngineSharedImpl +{ public: - DummyAudioBackend (AudioEngine& e, AudioBackendInfo& info); + DummyAudioBackend (AudioEngine& e, AudioBackendInfo& info); ~DummyAudioBackend (); bool is_running () const { return _running; } @@ -350,7 +351,8 @@ class DummyAudioBackend : public AudioBackend, public PortEngineSharedImpl { struct DriverSpeed { std::string name; float speedup; - DriverSpeed (const std::string& n, float s) : name (n), speedup (s) {} + bool realtime; + DriverSpeed (const std::string& n, float s, bool r = false) : name (n), speedup (s), realtime (r) {} }; std::string _instance_name; @@ -361,6 +363,7 @@ class DummyAudioBackend : public AudioBackend, public PortEngineSharedImpl { bool _running; bool _freewheel; bool _freewheeling; + bool _realtime; float _speedup; std::string _device;