X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Faudioengine.cc;h=91f58d44adfd0ee299b49df7de5338456d9821d2;hb=32b73439275dbe2cccaa2a71026a951ea46d24b9;hp=1a09a7f0eb3ded9f632dc65b5e96fb9e960e5c0e;hpb=c25640f3364478e91c135936644f264f143f1f43;p=ardour.git diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 1a09a7f0eb..91f58d44ad 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -55,6 +55,7 @@ #include "ardour/process_thread.h" #include "ardour/rc_configuration.h" #include "ardour/session.h" +#include "ardour/transport_master_manager.h" #include "pbd/i18n.h" @@ -77,7 +78,7 @@ AudioEngine::AudioEngine () , _freewheeling (false) , monitor_check_interval (INT32_MAX) , last_monitor_check (0) - , _processed_frames (0) + , _processed_samples (-1) , m_meter_thread (0) , _main_thread (0) , _mtdm (0) @@ -85,18 +86,18 @@ AudioEngine::AudioEngine () , _measuring_latency (MeasureNone) , _latency_input_port (0) , _latency_output_port (0) - , _latency_flush_frames (0) + , _latency_flush_samples (0) , _latency_signal_latency (0) , _stopped_for_latency (false) , _started_for_latency (false) , _in_destructor (false) , _last_backend_error_string(AudioBackend::get_error_string((AudioBackend::ErrorCode)-1)) - , _hw_reset_event_thread(0) - , _hw_reset_request_count(0) - , _stop_hw_reset_processing(0) - , _hw_devicelist_update_thread(0) - , _hw_devicelist_update_count(0) - , _stop_hw_devicelist_processing(0) + , _hw_reset_event_thread(0) + , _hw_reset_request_count(0) + , _stop_hw_reset_processing(0) + , _hw_devicelist_update_thread(0) + , _hw_devicelist_update_count(0) + , _stop_hw_devicelist_processing(0) #ifdef SILENCE_AFTER_SECONDS , _silence_countdown (0) , _silence_hit_cnt (0) @@ -155,7 +156,7 @@ AudioEngine::sample_rate_change (pframes_t nframes) last_monitor_check = 0; if (_session) { - _session->set_frame_rate (nframes); + _session->set_sample_rate (nframes); } SampleRateChanged (nframes); /* EMIT SIGNAL */ @@ -181,7 +182,7 @@ AudioEngine::buffer_size_change (pframes_t bufsiz) } /** Method called by our ::process_thread when there is work to be done. - * @param nframes Number of frames to process. + * @param nframes Number of samples to process. */ #ifdef __clang__ __attribute__((annotate("realtime"))) @@ -190,19 +191,25 @@ int AudioEngine::process_callback (pframes_t nframes) { Glib::Threads::Mutex::Lock tm (_process_lock, Glib::Threads::TRY_LOCK); + Port::set_speed_ratio (1.0); PT_TIMING_REF; PT_TIMING_CHECK (1); - /// The number of frames that will have been processed when we've finished - pframes_t next_processed_frames; + /// The number of samples that will have been processed when we've finished + pframes_t next_processed_samples; - /* handle wrap around of total frames counter */ + if (_processed_samples < 0) { + _processed_samples = sample_time(); + cerr << "IIIIINIT PS to " << _processed_samples << endl; + } + + /* handle wrap around of total samples counter */ - if (max_framepos - _processed_frames < nframes) { - next_processed_frames = nframes - (max_framepos - _processed_frames); + if (max_samplepos - _processed_samples < nframes) { + next_processed_samples = nframes - (max_samplepos - _processed_samples); } else { - next_processed_frames = _processed_frames + nframes; + next_processed_samples = _processed_samples + nframes; } if (!tm.locked()) { @@ -286,7 +293,7 @@ AudioEngine::process_callback (pframes_t nframes) PortManager::cycle_end (nframes); return_after_remove_check = true; - } else if (_latency_flush_frames) { + } else if (_latency_flush_samples) { /* wait for the appropriate duration for the MTDM signal to * drain from the ports before we revert to normal behaviour. @@ -296,11 +303,11 @@ AudioEngine::process_callback (pframes_t nframes) PortManager::silence (nframes); PortManager::cycle_end (nframes); - if (_latency_flush_frames > nframes) { - _latency_flush_frames -= nframes; - } else { - _latency_flush_frames = 0; - } + if (_latency_flush_samples > nframes) { + _latency_flush_samples -= nframes; + } else { + _latency_flush_samples = 0; + } return_after_remove_check = true; } @@ -345,51 +352,76 @@ AudioEngine::process_callback (pframes_t nframes) return 0; } + TransportMasterManager& tmm (TransportMasterManager::instance()); + + /* make sure the TMM is up to date about the current session */ + + if (_session != tmm.session()) { + tmm.set_session (_session); + } + if (_session == 0) { if (!_freewheeling) { - PortManager::cycle_start (nframes); - PortManager::cycle_end (nframes); + PortManager::silence_outputs (nframes); } - _processed_frames = next_processed_frames; + _processed_samples = next_processed_samples; return 0; } + if (!_freewheeling || Freewheel.empty()) { + const double engine_speed = tmm.pre_process_transport_masters (nframes, sample_time_at_cycle_start()); + Port::set_speed_ratio (engine_speed); + DEBUG_TRACE (DEBUG::Slave, string_compose ("transport master (current=%1) gives speed %2 (ports using %3)\n", tmm.current() ? tmm.current()->name() : string("[]"), engine_speed, Port::speed_ratio())); + } + /* tell all relevant objects that we're starting a new cycle */ InternalSend::CycleStart (nframes); /* tell all Ports that we're starting a new cycle */ - PortManager::cycle_start (nframes); + PortManager::cycle_start (nframes, _session); /* test if we are freewheeling and there are freewheel signals connected. - ardour should act normally even when freewheeling unless /it/ is - exporting (which is what Freewheel.empty() tests for). - */ + * ardour should act normally even when freewheeling unless /it/ is + * exporting (which is what Freewheel.empty() tests for). + */ if (_freewheeling && !Freewheel.empty()) { Freewheel (nframes); } else { - _session->process (nframes); + if (Port::cycle_nframes () <= nframes) { + _session->process (Port::cycle_nframes ()); + } else { + pframes_t remain = Port::cycle_nframes (); + while (remain > 0) { + pframes_t nf = std::min (remain, nframes); + _session->process (nf); + remain -= nf; + if (remain > 0) { + split_cycle (nf); + } + } + } } if (_freewheeling) { - PortManager::cycle_end (nframes); + PortManager::cycle_end (nframes, _session); return 0; } if (!_running) { - _processed_frames = next_processed_frames; + _processed_samples = next_processed_samples; return 0; } - if (last_monitor_check + monitor_check_interval < next_processed_frames) { + if (last_monitor_check + monitor_check_interval < next_processed_samples) { PortManager::check_monitoring (); - last_monitor_check = next_processed_frames; + last_monitor_check = next_processed_samples; } #ifdef SILENCE_AFTER_SECONDS @@ -419,7 +451,7 @@ AudioEngine::process_callback (pframes_t nframes) if (session_remove_pending && session_removal_countdown) { - PortManager::fade_out (session_removal_gain, session_removal_gain_step, nframes); + PortManager::cycle_end_fade_out (session_removal_gain, session_removal_gain_step, nframes, _session); if (session_removal_countdown > nframes) { session_removal_countdown -= nframes; @@ -428,11 +460,11 @@ AudioEngine::process_callback (pframes_t nframes) } session_removal_gain -= (nframes * session_removal_gain_step); + } else { + PortManager::cycle_end (nframes, _session); } - PortManager::cycle_end (nframes); - - _processed_frames = next_processed_frames; + _processed_samples = next_processed_samples; PT_TIMING_CHECK (2); @@ -466,9 +498,9 @@ AudioEngine::launch_device_control_app() void AudioEngine::request_backend_reset() { - Glib::Threads::Mutex::Lock guard (_reset_request_lock); - g_atomic_int_inc (&_hw_reset_request_count); - _hw_reset_condition.signal (); + Glib::Threads::Mutex::Lock guard (_reset_request_lock); + g_atomic_int_inc (&_hw_reset_request_count); + _hw_reset_condition.signal (); } int @@ -493,28 +525,28 @@ AudioEngine::do_reset_backend() Glib::Threads::RecMutex::Lock pl (_state_lock); g_atomic_int_dec_and_test (&_hw_reset_request_count); - std::cout << "AudioEngine::RESET::Reset request processing. Requests left: " << _hw_reset_request_count << std::endl; - DeviceResetStarted(); // notify about device reset to be started + std::cout << "AudioEngine::RESET::Reset request processing. Requests left: " << _hw_reset_request_count << std::endl; + DeviceResetStarted(); // notify about device reset to be started - // backup the device name - std::string name = _backend->device_name (); + // backup the device name + std::string name = _backend->device_name (); - std::cout << "AudioEngine::RESET::Reseting device..." << std::endl; + std::cout << "AudioEngine::RESET::Reseting device..." << std::endl; if ( ( 0 == stop () ) && - ( 0 == _backend->reset_device () ) && - ( 0 == start () ) ) { + ( 0 == _backend->reset_device () ) && + ( 0 == start () ) ) { std::cout << "AudioEngine::RESET::Engine started..." << std::endl; // inform about possible changes BufferSizeChanged (_backend->buffer_size() ); - DeviceResetFinished(); // notify about device reset finish + DeviceResetFinished(); // notify about device reset finish - } else { + } else { - DeviceResetFinished(); // notify about device reset finish + DeviceResetFinished(); // notify about device reset finish // we've got an error - DeviceError(); + DeviceError(); } std::cout << "AudioEngine::RESET::Done." << std::endl; @@ -528,81 +560,79 @@ AudioEngine::do_reset_backend() } } } + void AudioEngine::request_device_list_update() { - Glib::Threads::Mutex::Lock guard (_devicelist_update_lock); - g_atomic_int_inc (&_hw_devicelist_update_count); - _hw_devicelist_update_condition.signal (); + Glib::Threads::Mutex::Lock guard (_devicelist_update_lock); + g_atomic_int_inc (&_hw_devicelist_update_count); + _hw_devicelist_update_condition.signal (); } - void AudioEngine::do_devicelist_update() { - SessionEvent::create_per_thread_pool (X_("Device list update processing thread"), 512); + SessionEvent::create_per_thread_pool (X_("Device list update processing thread"), 512); - Glib::Threads::Mutex::Lock guard (_devicelist_update_lock); + Glib::Threads::Mutex::Lock guard (_devicelist_update_lock); - while (!_stop_hw_devicelist_processing) { + while (!_stop_hw_devicelist_processing) { - if (_hw_devicelist_update_count) { + if (_hw_devicelist_update_count) { - _devicelist_update_lock.unlock(); + _devicelist_update_lock.unlock(); - Glib::Threads::RecMutex::Lock pl (_state_lock); + Glib::Threads::RecMutex::Lock pl (_state_lock); - g_atomic_int_dec_and_test (&_hw_devicelist_update_count); - DeviceListChanged (); /* EMIT SIGNAL */ + g_atomic_int_dec_and_test (&_hw_devicelist_update_count); + DeviceListChanged (); /* EMIT SIGNAL */ - _devicelist_update_lock.lock(); + _devicelist_update_lock.lock(); - } else { - _hw_devicelist_update_condition.wait (_devicelist_update_lock); - } - } + } else { + _hw_devicelist_update_condition.wait (_devicelist_update_lock); + } + } } void AudioEngine::start_hw_event_processing() { - if (_hw_reset_event_thread == 0) { - g_atomic_int_set(&_hw_reset_request_count, 0); - g_atomic_int_set(&_stop_hw_reset_processing, 0); - _hw_reset_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this)); - } + if (_hw_reset_event_thread == 0) { + g_atomic_int_set(&_hw_reset_request_count, 0); + g_atomic_int_set(&_stop_hw_reset_processing, 0); + _hw_reset_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this)); + } - if (_hw_devicelist_update_thread == 0) { - g_atomic_int_set(&_hw_devicelist_update_count, 0); - g_atomic_int_set(&_stop_hw_devicelist_processing, 0); - _hw_devicelist_update_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_devicelist_update, this)); - } + if (_hw_devicelist_update_thread == 0) { + g_atomic_int_set(&_hw_devicelist_update_count, 0); + g_atomic_int_set(&_stop_hw_devicelist_processing, 0); + _hw_devicelist_update_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_devicelist_update, this)); + } } void AudioEngine::stop_hw_event_processing() { - if (_hw_reset_event_thread) { - g_atomic_int_set(&_stop_hw_reset_processing, 1); - g_atomic_int_set(&_hw_reset_request_count, 0); - _hw_reset_condition.signal (); - _hw_reset_event_thread->join (); - _hw_reset_event_thread = 0; - } - - if (_hw_devicelist_update_thread) { - g_atomic_int_set(&_stop_hw_devicelist_processing, 1); - g_atomic_int_set(&_hw_devicelist_update_count, 0); - _hw_devicelist_update_condition.signal (); - _hw_devicelist_update_thread->join (); - _hw_devicelist_update_thread = 0; - } + if (_hw_reset_event_thread) { + g_atomic_int_set(&_stop_hw_reset_processing, 1); + g_atomic_int_set(&_hw_reset_request_count, 0); + _hw_reset_condition.signal (); + _hw_reset_event_thread->join (); + _hw_reset_event_thread = 0; + } + if (_hw_devicelist_update_thread) { + g_atomic_int_set(&_stop_hw_devicelist_processing, 1); + g_atomic_int_set(&_hw_devicelist_update_count, 0); + _hw_devicelist_update_condition.signal (); + _hw_devicelist_update_thread->join (); + _hw_devicelist_update_thread = 0; + } } - void AudioEngine::set_session (Session *s) { @@ -873,7 +903,7 @@ AudioEngine::start (bool for_latency) return 0; } - _processed_frames = 0; + _processed_samples = 0; last_monitor_check = 0; int error_code = _backend->start (for_latency); @@ -886,7 +916,7 @@ AudioEngine::start (bool for_latency) _running = true; if (_session) { - _session->set_frame_rate (_backend->sample_rate()); + _session->set_sample_rate (_backend->sample_rate()); if (_session->config.get_jack_time_master()) { _backend->set_time_master (true); @@ -922,11 +952,14 @@ AudioEngine::stop (bool for_latency) if (for_latency && _backend->can_change_systemic_latency_when_running()) { stop_engine = false; + if (_running) { + _backend->start (false); // keep running, reload latencies + } } else { if (_backend->stop ()) { if (pl.locked ()) { - pl.release (); - } + pl.release (); + } return -1; } } @@ -943,14 +976,18 @@ AudioEngine::stop (bool for_latency) _session->engine_halted (); } - if (stop_engine) { + if (stop_engine && _running) { _running = false; + if (!for_latency) { + _started_for_latency = false; + } else if (!_started_for_latency) { + _stopped_for_latency = true; + } } - _processed_frames = 0; + _processed_samples = 0; _measuring_latency = MeasureNone; _latency_output_port = 0; _latency_input_port = 0; - _started_for_latency = false; if (stop_engine) { Port::PortDrop (); @@ -1032,7 +1069,7 @@ AudioEngine::transport_state () } void -AudioEngine::transport_locate (framepos_t pos) +AudioEngine::transport_locate (samplepos_t pos) { if (!_backend) { return; @@ -1040,16 +1077,16 @@ AudioEngine::transport_locate (framepos_t pos) return _backend->transport_locate (pos); } -framepos_t -AudioEngine::transport_frame() +samplepos_t +AudioEngine::transport_sample() { if (!_backend) { return 0; } - return _backend->transport_frame (); + return _backend->transport_sample (); } -framecnt_t +samplecnt_t AudioEngine::sample_rate () const { if (!_backend) { @@ -1085,7 +1122,7 @@ AudioEngine::raw_buffer_size (DataType t) return _backend->raw_buffer_size (t); } -framepos_t +samplepos_t AudioEngine::sample_time () { if (!_backend) { @@ -1094,7 +1131,7 @@ AudioEngine::sample_time () return _backend->sample_time (); } -framepos_t +samplepos_t AudioEngine::sample_time_at_cycle_start () { if (!_backend) { @@ -1233,7 +1270,7 @@ AudioEngine::set_systemic_output_latency (uint32_t ol) bool AudioEngine::thread_initialised_for_audio_processing () { - return SessionEvent::has_per_thread_pool () && AsyncMIDIPort::is_process_thread(); + return SessionEvent::has_per_thread_pool () && AsyncMIDIPort::is_process_thread(); } /* END OF BACKEND PROXY API */ @@ -1262,7 +1299,7 @@ AudioEngine::thread_init_callback (void* arg) } int -AudioEngine::sync_callback (TransportState state, framepos_t position) +AudioEngine::sync_callback (TransportState state, samplepos_t position) { if (_session) { return _session->backend_sync_callback (state, position); @@ -1279,9 +1316,9 @@ AudioEngine::freewheel_callback (bool onoff) void AudioEngine::latency_callback (bool for_playback) { - if (_session) { - _session->update_latency (for_playback); - } + if (_session) { + _session->update_latency (for_playback); + } } void @@ -1336,16 +1373,16 @@ AudioEngine::prepare_for_latency_measurement () } if (_backend->can_change_systemic_latency_when_running()) { - if (start()) { + if (_running) { + _backend->start (true); // zero latency reporting of running backend + } else if (start (true)) { return -1; } - _backend->set_systemic_input_latency (0); - _backend->set_systemic_output_latency (0); + _started_for_latency = true; return 0; } if (running()) { - _stopped_for_latency = true; stop (true); } @@ -1353,7 +1390,6 @@ AudioEngine::prepare_for_latency_measurement () return -1; } _started_for_latency = true; - return 0; } @@ -1448,7 +1484,7 @@ AudioEngine::start_latency_detection (bool for_midi) _latency_signal_latency += lr.max; /* all created and connected, lets go */ - _latency_flush_frames = samples_per_cycle(); + _latency_flush_samples = samples_per_cycle(); _measuring_latency = for_midi ? MeasureMIDI : MeasureAudio; return 0; @@ -1468,6 +1504,18 @@ AudioEngine::stop_latency_detection () _latency_input_port = 0; } + if (_running && _backend->can_change_systemic_latency_when_running()) { + if (_started_for_latency) { + _running = false; // force reload: reset latencies and emit Running() + start (); + } + } + + if (_running && !_started_for_latency) { + assert (!_stopped_for_latency); + return; + } + if (!_backend->can_change_systemic_latency_when_running()) { stop (true); }