13
0

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.
This commit is contained in:
Paul Davis 2024-05-10 08:30:14 -06:00
parent 21f4dce2d9
commit f9a76829f3

View File

@ -240,6 +240,10 @@ InternalSend::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa
_panshell->run (bufs, mixbufs, start_sample + latency, end_sample + latency, nframes); _panshell->run (bufs, mixbufs, start_sample + latency, end_sample + latency, nframes);
} }
/* No need to handle non-audio if this is the MasterSend */
if (role() != MasterSend) {
/* non-audio data will not have been copied by the panner, do it now /* 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 more buffers available than send buffers, ignore them,
* if there are less, copy the last as IO::copy_to_output does. */ * if there are less, copy the last as IO::copy_to_output does. */
@ -260,9 +264,10 @@ InternalSend::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa
} }
} }
} }
}
} else if (role () == Listen) { } else if (role () == Listen || role() == MasterSend) {
/* We're going to the monitor bus, so discard MIDI data */ /* 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 bufs_audio = bufs.count ().get (DataType::AUDIO);
uint32_t const mixbufs_audio = mixbufs.count ().get (DataType::AUDIO); uint32_t const mixbufs_audio = mixbufs.count ().get (DataType::AUDIO);
@ -320,15 +325,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 (); gain_t tgain = target_gain ();
if (tgain != _current_gain) { if (tgain != _current_gain) {
/* target gain has changed, fade in/out */ /* target gain has changed, fade in/out */
_current_gain = Amp::apply_gain (mixbufs, _session.nominal_sample_rate (), nframes, _current_gain, tgain); _current_gain = Amp::apply_gain (mixbufs, _session.nominal_sample_rate (), nframes, _current_gain, tgain);
} else if (tgain == GAIN_COEFF_ZERO) { } else if (tgain == GAIN_COEFF_ZERO) {
/* we were quiet last time, and we're still supposed to be quiet. */ /* 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 (); _meter->reset ();
}
Amp::apply_simple_gain (mixbufs, nframes, GAIN_COEFF_ZERO); Amp::apply_simple_gain (mixbufs, nframes, GAIN_COEFF_ZERO);
return; return;
} else if (tgain != GAIN_COEFF_UNITY) { } else if (tgain != GAIN_COEFF_UNITY) {
@ -336,15 +377,17 @@ InternalSend::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sa
Amp::apply_simple_gain (mixbufs, nframes, tgain); Amp::apply_simple_gain (mixbufs, nframes, tgain);
} }
if (role() != MasterSend) {
/* apply fader gain automation */ /* apply fader gain automation */
_amp->set_gain_automation_buffer (_session.send_gain_automation_buffer ()); _amp->set_gain_automation_buffer (_session.send_gain_automation_buffer ());
_amp->setup_gain_automation (start_sample + latency, end_sample + latency, nframes); _amp->setup_gain_automation (start_sample + latency, end_sample + latency, nframes);
_amp->run (mixbufs, start_sample + latency, end_sample + latency, speed, nframes, true); _amp->run (mixbufs, start_sample + latency, end_sample + latency, speed, nframes, true);
}
_send_delay->run (mixbufs, start_sample, end_sample, speed, nframes, true); _send_delay->run (mixbufs, start_sample, end_sample, speed, nframes, true);
/* consider metering */ /* consider metering */
if (_metering) { if (_metering && role() != MasterSend) {
if (gain_control ()->get_value () == GAIN_COEFF_ZERO) { if (gain_control ()->get_value () == GAIN_COEFF_ZERO) {
_meter->reset (); _meter->reset ();
} else { } else {