From 2e55f4452fa50fab9549c04797a4e962c11e8273 Mon Sep 17 00:00:00 2001 From: John Emmas Date: Fri, 10 May 2024 15:01:43 +0100 Subject: [PATCH 1/6] As we've yet to implement user options, let's prefer AAF filenames rather than extracting an internal Comp name This helps to avoid situations where 2 x unrelated AAF imports use the same name internally - and/or they give us meaningless session names like "Untitled.ardour" --- gtk2_ardour/ardour_ui_aaf.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtk2_ardour/ardour_ui_aaf.cc b/gtk2_ardour/ardour_ui_aaf.cc index 0adf492317..964b8d1aff 100644 --- a/gtk2_ardour/ardour_ui_aaf.cc +++ b/gtk2_ardour/ardour_ui_aaf.cc @@ -466,7 +466,7 @@ ARDOUR_UI::new_session_from_aaf (string const& aaf, string const& target_dir, st } /* extract or set session name */ - if (aafi->compositionName && aafi->compositionName[0] != 0x00) { + if (/* Temporary - in the absence of user-options, don't rely on extracted session names which can be meaningless... aafi->compositionName && aafi->compositionName[0] != */ 0x00) { string compositionName = string (aafi->compositionName); snapshot = laaf_util_clean_filename (&compositionName[0]); } else { From edc03002eb20bb152d1927a19fc26a29bdeea89f Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 10 May 2024 08:25:50 -0600 Subject: [PATCH 2/6] for DEBUG::Processors, use display_name() not name() This allows us to differentiate between different instances of the same type of processor (e.g. Trim vs Fader, which are both of type Amp) --- gtk2_ardour/mixer_strip.cc | 2 +- libs/ardour/route.cc | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc index 6c4c1464aa..8d635402ed 100644 --- a/gtk2_ardour/mixer_strip.cc +++ b/gtk2_ardour/mixer_strip.cc @@ -1667,7 +1667,7 @@ MixerStrip::show_send (std::shared_ptr send) send->set_metering (true); _current_delivery->DropReferences.connect (send_gone_connection, invalidator (*this), boost::bind (&MixerStrip::revert_to_default_display, this), gui_context()); - gain_meter().set_controls (_route, send->meter(), send->amp(), send->gain_control()); + gain_meter().set_controls (_route, _route->shared_peak_meter() /*send->meter()*/, send->amp(), send->gain_control()); gain_meter().setup_meters (); uint32_t const in = _current_delivery->pans_required(); diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index afe660c5ed..78b087502f 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -914,7 +914,7 @@ Route::add_processor (std::shared_ptr processor, std::shared_ptrname())); + "%1 adding processor %2\n", name(), processor->display_name())); ProcessorList pl; @@ -1876,7 +1876,7 @@ Route::try_configure_processors_unlocked (ChanCount in, ProcessorStreams* err) } } - DEBUG_TRACE (DEBUG::Processors, string_compose ("\t%1 ID=%2 in=%3 out=%4\n",(*p)->name(), (*p)->id(), in, out)); + DEBUG_TRACE (DEBUG::Processors, string_compose ("\t%1 ID=%2 in=%3 out=%4\n",(*p)->display_name(), (*p)->id(), in, out)); configuration.push_back(make_pair(in, out)); if (is_monitor()) { @@ -5532,7 +5532,7 @@ Route::setup_invisible_processors () DEBUG_TRACE (DEBUG::Processors, string_compose ("%1: setup_invisible_processors\n", _name)); for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { - DEBUG_TRACE (DEBUG::Processors, string_compose ("\t%1\n", (*i)->name ())); + DEBUG_TRACE (DEBUG::Processors, string_compose ("\t%1\n", (*i)->display_name ())); } } From de1a425704960175a6458a6da9ef65f5ef0d4f59 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 10 May 2024 08:30:14 -0600 Subject: [PATCH 3/6] fix for metering of a MasterSend (internal send) Metering for these sends should be effectively PostFader not Output, and should not reflect the impact of solo & mute. --- libs/ardour/internal_send.cc | 93 ++++++++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 25 deletions(-) diff --git a/libs/ardour/internal_send.cc b/libs/ardour/internal_send.cc index 1e1511c5fc..94a1e4f755 100644 --- a/libs/ardour/internal_send.cc +++ b/libs/ardour/internal_send.cc @@ -229,29 +229,34 @@ InternalSend::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa _panshell->run (bufs, mixbufs, start_sample + latency, end_sample + latency, nframes); } - /* non-audio data will not have been copied by the panner, do it now - * if there are more buffers available than send buffers, ignore them, - * if there are less, copy the last as IO::copy_to_output does. */ + /* No need to handle non-audio if this is the MasterSend */ - for (DataType::iterator t = DataType::begin (); t != DataType::end (); ++t) { - if (*t != DataType::AUDIO) { - BufferSet::iterator o = mixbufs.begin (*t); - BufferSet::iterator i = bufs.begin (*t); + if (role() != MasterSend) { - while (i != bufs.end (*t) && o != mixbufs.end (*t)) { - o->read_from (*i, nframes); - ++i; - ++o; - } - while (o != mixbufs.end (*t)) { - o->silence (nframes, 0); - ++o; + /* non-audio data will not have been copied by the panner, do it now + * if there are more buffers available than send buffers, ignore them, + * if there are less, copy the last as IO::copy_to_output does. */ + + for (DataType::iterator t = DataType::begin (); t != DataType::end (); ++t) { + if (*t != DataType::AUDIO) { + BufferSet::iterator o = mixbufs.begin (*t); + BufferSet::iterator i = bufs.begin (*t); + + while (i != bufs.end (*t) && o != mixbufs.end (*t)) { + o->read_from (*i, nframes); + ++i; + ++o; + } + while (o != mixbufs.end (*t)) { + o->silence (nframes, 0); + ++o; + } } } } - } else if (role () == Listen) { - /* We're going to the monitor bus, so discard MIDI data */ + } else if (role () == Listen || role() == MasterSend) { + /* We're going to the monitor or master bus, so discard MIDI data */ uint32_t const bufs_audio = bufs.count ().get (DataType::AUDIO); uint32_t const mixbufs_audio = mixbufs.count ().get (DataType::AUDIO); @@ -309,15 +314,51 @@ InternalSend::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa } } - /* main gain control: * mute & bypass/enable */ + /* For a master send, we want the meter to be effectively MeterPostFader + * rather than MeterOutput. But below, we compute a target gain that + * will take mute and solo into account, and apply to mixbufs *before* + * metering, which would make metering equivalent to MeterOutput. + * + * So, for a master send, run our own gain control first (so we see the + * effect in the meters), then meter, then apply any mute/solo-driven gain. + * + * For other internal sends, apply mute/solo-controlled gain, then our + * own gain control, then meter. + */ + + if (role() == MasterSend) { + + /* apply fader gain automation before running meter */ + + _amp->set_gain_automation_buffer (_session.send_gain_automation_buffer ()); + _amp->setup_gain_automation (start_sample + latency, end_sample + latency, nframes); + _amp->run (mixbufs, start_sample + latency, end_sample + latency, speed, nframes, true); + + if (_metering) { + if (gain_control ()->get_value () == GAIN_COEFF_ZERO) { + _meter->reset (); + } else { + _meter->run (mixbufs, start_sample, end_sample, speed, nframes, true); + } + } + } + + /* tgain reflects muting and soling */ + gain_t tgain = target_gain (); if (tgain != _current_gain) { /* target gain has changed, fade in/out */ _current_gain = Amp::apply_gain (mixbufs, _session.nominal_sample_rate (), nframes, _current_gain, tgain); } else if (tgain == GAIN_COEFF_ZERO) { - /* we were quiet last time, and we're still supposed to be quiet. */ - _meter->reset (); + /* we were quiet last time, and we're still supposed to be + * quiet. Don't do this for a MasterSend, because its meter is + * effectively MeterPostFader, not MeterOutput, so we don't + * want it to reflect mute/solo-controlled levels. + */ + if (role() != MasterSend || (gain_control()->get_value() == GAIN_COEFF_ZERO)) { + _meter->reset (); + } Amp::apply_simple_gain (mixbufs, nframes, GAIN_COEFF_ZERO); return; } else if (tgain != GAIN_COEFF_UNITY) { @@ -325,15 +366,17 @@ InternalSend::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa Amp::apply_simple_gain (mixbufs, nframes, tgain); } - /* apply fader gain automation */ - _amp->set_gain_automation_buffer (_session.send_gain_automation_buffer ()); - _amp->setup_gain_automation (start_sample + latency, end_sample + latency, nframes); - _amp->run (mixbufs, start_sample + latency, end_sample + latency, speed, nframes, true); + if (role() != MasterSend) { + /* apply fader gain automation */ + _amp->set_gain_automation_buffer (_session.send_gain_automation_buffer ()); + _amp->setup_gain_automation (start_sample + latency, end_sample + latency, nframes); + _amp->run (mixbufs, start_sample + latency, end_sample + latency, speed, nframes, true); + } _send_delay->run (mixbufs, start_sample, end_sample, speed, nframes, true); /* consider metering */ - if (_metering) { + if (_metering && role() != MasterSend) { if (gain_control ()->get_value () == GAIN_COEFF_ZERO) { _meter->reset (); } else { From b929e8a4e2cd5e6c8c6806d4db96e6a6eafa8a48 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 10 May 2024 08:30:57 -0600 Subject: [PATCH 4/6] revert inadvertently committed change made for debugging. --- gtk2_ardour/mixer_strip.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc index 8d635402ed..6c4c1464aa 100644 --- a/gtk2_ardour/mixer_strip.cc +++ b/gtk2_ardour/mixer_strip.cc @@ -1667,7 +1667,7 @@ MixerStrip::show_send (std::shared_ptr send) send->set_metering (true); _current_delivery->DropReferences.connect (send_gone_connection, invalidator (*this), boost::bind (&MixerStrip::revert_to_default_display, this), gui_context()); - gain_meter().set_controls (_route, _route->shared_peak_meter() /*send->meter()*/, send->amp(), send->gain_control()); + gain_meter().set_controls (_route, send->meter(), send->amp(), send->gain_control()); gain_meter().setup_meters (); uint32_t const in = _current_delivery->pans_required(); From dcdcaf4b475e4efb4d62812c52415ba9ea6c6f2c Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 10 May 2024 08:31:38 -0600 Subject: [PATCH 5/6] ensure that the master send is directly before the main outs. --- libs/ardour/route.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 78b087502f..e4bf429c96 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -5306,6 +5306,12 @@ Route::setup_invisible_processors () new_processors.insert (meter_point, _meter); } + + if (Profile->get_livetrax() && _master_send) { + assert (!_master_send->display_to_user()); + new_processors.insert (main, _master_send); + } + /* Foldback Sends */ for (ProcessorList::iterator i = foldback_sends.begin(); i != foldback_sends.end(); ++i) { From fce1f15a870c5b04828f0ee0e33bbb05dfa14d5f Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 9 May 2024 17:56:19 -0600 Subject: [PATCH 6/6] avoid timecnt_t exception when loading a region with an excessively long length This is not a fix for whatever underlying problem causes this, but it does allow sessions to load when the faulty region(s) are not in use --- libs/ardour/region.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index f9e931195d..eba4486513 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -1535,7 +1535,9 @@ Region::_set_state (const XMLNode& node, int version, PropertyChange& what_chang match. */ if ((length().time_domain() == Temporal::AudioTime) && (_sources.front()->length().time_domain() == Temporal::AudioTime) && (length().distance() > _sources.front()->length())) { - _length = timecnt_t (start().distance (_sources.front()->length()), _length.val().position()); + std::cerr << "Region " << _name << " has length " << _length.val().str() << " which is longer than its (first?) source's length of " << _sources.front()->length().str() << std::endl; + throw failed_constructor(); + // _length = timecnt_t (start().distance (_sources.front()->length()), _length.val().position()); } }