add an Amp to Delivery, remove it from Send, make use of this in various ::run() methods

Delivery::_amp now will handle monitor-related delicks assuming the Session::config.get_use_monitor_fades() is
true.
This commit is contained in:
Paul Davis 2015-09-15 16:34:53 -04:00
parent fdcc209354
commit 601a34521c
6 changed files with 86 additions and 46 deletions

View file

@ -133,9 +133,19 @@ Amp::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end_frame*/,
_current_gain = Amp::apply_gain (bufs, _session.nominal_frame_rate(), nframes, _current_gain, dg, _midi_amp);
} else if (_current_gain == GAIN_COEFF_ZERO) {
/* gain has not changed, and is zero. small
* optimization here.
*/
bufs.silence (nframes, 0);
} else if (_current_gain != GAIN_COEFF_UNITY) {
/* gain has not changed, but its non-unity */
/* gain has not changed, but its non-unity and
* isn't zero, so we have to do something
*/
if (_midi_amp) {
/* don't Trim midi velocity -- only relevant for Midi on Audio tracks */

View file

@ -34,6 +34,7 @@ class MuteMaster;
class PannerShell;
class Panner;
class Pannable;
class Amp;
class LIBARDOUR_API Delivery : public IOProcessor
{
@ -67,6 +68,8 @@ public:
bool set_name (const std::string& name);
std::string display_name() const;
boost::shared_ptr<Amp> amp() const { return _amp; }
Role role() const { return _role; }
bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
bool configure_io (ChanCount in, ChanCount out);
@ -106,8 +109,8 @@ public:
protected:
Role _role;
BufferSet* _output_buffers;
gain_t _current_gain;
boost::shared_ptr<PannerShell> _panshell;
boost::shared_ptr<Amp> _amp;
gain_t target_gain ();

View file

@ -43,7 +43,6 @@ class LIBARDOUR_API Send : public Delivery
bool display_to_user() const;
boost::shared_ptr<Amp> amp() const { return _amp; }
boost::shared_ptr<PeakMeter> meter() const { return _meter; }
bool metering() const { return _metering; }
@ -78,7 +77,6 @@ class LIBARDOUR_API Send : public Delivery
protected:
bool _metering;
boost::shared_ptr<Amp> _amp;
boost::shared_ptr<PeakMeter> _meter;
boost::shared_ptr<DelayLine> _delayline;

View file

@ -52,7 +52,7 @@ Delivery::Delivery (Session& s, boost::shared_ptr<IO> io, boost::shared_ptr<Pann
: IOProcessor(s, boost::shared_ptr<IO>(), (role_requires_output_ports (r) ? io : boost::shared_ptr<IO>()), name)
, _role (r)
, _output_buffers (new BufferSet())
, _current_gain (GAIN_COEFF_UNITY)
, _amp (new Amp (s))
, _no_outs_cuz_we_no_monitor (false)
, _mute_master (mm)
, _no_panner_reset (false)
@ -68,6 +68,8 @@ Delivery::Delivery (Session& s, boost::shared_ptr<IO> io, boost::shared_ptr<Pann
if (_output) {
_output->changed.connect_same_thread (*this, boost::bind (&Delivery::output_changed, this, _1, _2));
}
_amp->activate ();
}
/* deliver to a new IO object */
@ -76,7 +78,7 @@ Delivery::Delivery (Session& s, boost::shared_ptr<Pannable> pannable, boost::sha
: IOProcessor(s, false, (role_requires_output_ports (r) ? true : false), name, "", DataType::AUDIO, (r == Send))
, _role (r)
, _output_buffers (new BufferSet())
, _current_gain (GAIN_COEFF_UNITY)
, _amp (new Amp (s))
, _no_outs_cuz_we_no_monitor (false)
, _mute_master (mm)
, _no_panner_reset (false)
@ -92,16 +94,17 @@ Delivery::Delivery (Session& s, boost::shared_ptr<Pannable> pannable, boost::sha
if (_output) {
_output->changed.connect_same_thread (*this, boost::bind (&Delivery::output_changed, this, _1, _2));
}
}
_amp->activate ();
}
Delivery::~Delivery()
{
DEBUG_TRACE (DEBUG::Destruction, string_compose ("delivery %1 destructor\n", _name));
DEBUG_TRACE (DEBUG::Destruction, string_compose ("delivery %1 destructor\n", _name));
/* this object should vanish from any signal callback lists
that it is on before we get any further. The full qualification
of the method name is not necessary, but is here to make it
of the method name is not necessary, but is here to make it
clear that this call is about signals, not data flow connections.
*/
@ -235,6 +238,7 @@ Delivery::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pf
PortSet& ports (_output->ports());
gain_t tgain;
bool need_amp = true;
if (_output->n_ports ().get (_output->default_type()) == 0) {
goto out;
@ -259,28 +263,59 @@ Delivery::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pf
tgain = target_gain ();
if (tgain != _current_gain) {
/* target gain has changed */
if (tgain < GAIN_COEFF_SMALL && _amp->gain() < GAIN_COEFF_SMALL) {
_current_gain = Amp::apply_gain (bufs, _session.nominal_frame_rate(), nframes, _current_gain, tgain);
} else if (tgain < GAIN_COEFF_SMALL) {
/* we were quiet last time, and we're still supposed to be quiet.
Silence the outputs, and make sure the buffers are quiet too,
*/
/* special case (but very common) fast path:
*
* if we are supposed to be silent, and we were already silent,
* then short-circuit the computation in Amp and just put silence into
* our output(s)
*/
_output->silence (nframes);
if (result_required) {
bufs.set_count (output_buffers().count ());
Amp::apply_simple_gain (bufs, nframes, GAIN_COEFF_ZERO);
if (!result_required) {
/* if !result_required, then the buffers won't actually
* be used. This means we don't actually need to silence
* them, because we've already filled the output ports
* with silence.
*
* but we just noted that result_required is true,
* and so we do need to run the amp to ensure
* that the buffers are silenced.
*/
need_amp = false;
}
}
if (need_amp) {
bufs.set_count (output_buffers().count ());
if (_role != Main) {
/* inserts, external and internal sends have
* automatable gain and the Amp::run() method has
* already been executed by the time we get here.
*
* XXX we do not expose the automatable gain for
* Inserts as of September 2015.
*/
} else {
/* main outs have no automatable gain, the amp is just
* used for ramping gain changes caused by monitoring
* state changes.
*/
_amp->set_gain (tgain, this);
_amp->run (bufs, 0, 0, nframes, false);
}
} else {
goto out;
} else if (tgain != GAIN_COEFF_UNITY) {
/* target gain has not changed, but is not unity */
Amp::apply_simple_gain (bufs, nframes, tgain);
}
if (_panshell && !_panshell->bypassed() && _panshell->panner()) {
@ -386,7 +421,7 @@ Delivery::pan_outs () const
{
if (_output) {
return _output->n_ports().n_audio();
}
}
return _configured_output.n_audio();
}
@ -454,7 +489,7 @@ Delivery::flush_buffers (framecnt_t nframes)
if (!_output) {
return;
}
PortSet& ports (_output->ports());
for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
@ -505,7 +540,7 @@ Delivery::target_gain ()
we're not monitoring, then be quiet.
*/
if (_no_outs_cuz_we_no_monitor) {
if (_role == Main && _session.config.get_use_monitor_fades() && _no_outs_cuz_we_no_monitor) {
return GAIN_COEFF_ZERO;
}

View file

@ -148,10 +148,10 @@ InternalSend::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame
} else {
if (role() == Listen) {
/* We're going to the monitor 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);
/* monitor-section has same number of channels as master-bus (on creation).
*
* There is no clear answer what should happen when trying to PFL or AFL
@ -190,27 +190,22 @@ InternalSend::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame
gain_t tgain = target_gain ();
if (tgain != _current_gain) {
/* target gain has changed */
_current_gain = Amp::apply_gain (mixbufs, _session.nominal_frame_rate(), nframes, _current_gain, tgain);
} else if (tgain == GAIN_COEFF_ZERO) {
_amp->set_gain (tgain, this);
if (tgain == GAIN_COEFF_ZERO && _amp->gain() == GAIN_COEFF_ZERO) {
/* we were quiet last time, and we're still supposed to be quiet.
*/
*/
_meter->reset ();
Amp::apply_simple_gain (mixbufs, nframes, GAIN_COEFF_ZERO);
goto out;
} else if (tgain != GAIN_COEFF_UNITY) {
/* target gain has not changed, but is not zero or unity */
Amp::apply_simple_gain (mixbufs, nframes, tgain);
}
/* These two calls will either set up gain automation or mark
the amp as ready to use a simple scalar gain.
*/
_amp->set_gain_automation_buffer (_session.send_gain_automation_buffer ());
_amp->setup_gain_automation (start_frame, end_frame, nframes);
_amp->run (mixbufs, start_frame, end_frame, nframes, true);
@ -400,4 +395,4 @@ InternalSend::cycle_start (pframes_t /*nframes*/)
for (BufferSet::audio_iterator b = mixbufs.audio_begin(); b != mixbufs.audio_end(); ++b) {
b->prepare ();
}
}
}

View file

@ -86,7 +86,6 @@ Send::Send (Session& s, boost::shared_ptr<Pannable> p, boost::shared_ptr<MuteMas
//boost_debug_shared_ptr_mark_interesting (this, "send");
_amp.reset (new Amp (_session));
_meter.reset (new PeakMeter (_session, name()));
_delayline.reset (new DelayLine (_session, name()));
@ -174,7 +173,7 @@ Send::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframe
sendbufs.read_from (bufs, nframes);
assert(sendbufs.count() == bufs.count());
/* gain control */
/* automatable gain control */
_amp->set_gain_automation_buffer (_session.send_gain_automation_buffer ());
_amp->setup_gain_automation (start_frame, end_frame, nframes);