Consistent Automation evaluation:
Rule #89: The *owner* of each automation-control is responsible to evaluate automation of automated automation-controls (and emit Changed() signals to notify the GUI and slaved controls). This can happen during run(), when the Processor evaluates automation (eg. PluginInsert does that), but needs to regardless, every cycle. Emit Changed signal for GainControl This follow the same concept as PluginInsert: The Changed signal is called on demand when evaluating automation.
This commit is contained in:
parent
06ca52d5a5
commit
dee990103a
|
@ -90,6 +90,9 @@ Amp::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end_frame*/,
|
|||
gain_t* gab = _gain_automation_buffer;
|
||||
assert (gab);
|
||||
|
||||
/* see note in PluginInsert::connect_and_run -- emit Changed signal */
|
||||
_gain_control->set_value_unchecked (gab[0]);
|
||||
|
||||
if (_midi_amp) {
|
||||
for (BufferSet::midi_iterator i = bufs.midi_begin(); i != bufs.midi_end(); ++i) {
|
||||
MidiBuffer& mb (*i);
|
||||
|
@ -130,6 +133,12 @@ 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);
|
||||
|
||||
/* see note in PluginInsert::connect_and_run ()
|
||||
* set_value_unchecked() won't emit a signal since the value is effectively unchanged
|
||||
*/
|
||||
|
||||
_gain_control->Changed (false, PBD::Controllable::NoGroup);
|
||||
|
||||
} else if (_current_gain != GAIN_COEFF_UNITY) {
|
||||
|
||||
/* gain has not changed, but its non-unity */
|
||||
|
|
|
@ -86,6 +86,8 @@ public:
|
|||
virtual void transport_located (framepos_t now);
|
||||
virtual void transport_stopped (framepos_t now);
|
||||
|
||||
virtual void automation_run (framepos_t, pframes_t);
|
||||
|
||||
virtual std::string describe_parameter(Evoral::Parameter param);
|
||||
|
||||
AutoState get_parameter_automation_state (Evoral::Parameter param);
|
||||
|
|
|
@ -77,7 +77,7 @@ class LIBARDOUR_API Processor : public SessionObject, public Automatable, public
|
|||
* if false, the method need not bother writing to @a bufs if it doesn't want to.
|
||||
*/
|
||||
virtual void run (BufferSet& /*bufs*/, framepos_t /*start_frame*/, framepos_t /*end_frame*/, double speed, pframes_t /*nframes*/, bool /*result_required*/) {}
|
||||
virtual void silence (framecnt_t /*nframes*/, framepos_t /*start_frame*/) {}
|
||||
virtual void silence (framecnt_t nframes, framepos_t start_frame) { automation_run (start_frame, nframes); }
|
||||
|
||||
virtual void activate () { _pending_active = true; ActiveChanged(); }
|
||||
virtual void deactivate () { _pending_active = false; ActiveChanged(); }
|
||||
|
|
|
@ -395,6 +395,19 @@ Automatable::transport_stopped (framepos_t now)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Automatable::automation_run (framepos_t start, pframes_t nframes)
|
||||
{
|
||||
for (Controls::iterator li = controls().begin(); li != controls().end(); ++li) {
|
||||
boost::shared_ptr<AutomationControl> c =
|
||||
boost::dynamic_pointer_cast<AutomationControl>(li->second);
|
||||
if (!c) {
|
||||
continue;
|
||||
}
|
||||
c->automation_run (start, nframes);
|
||||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr<Evoral::Control>
|
||||
Automatable::control_factory(const Evoral::Parameter& param)
|
||||
{
|
||||
|
|
|
@ -260,6 +260,7 @@ AutomationControl::set_automation_state (AutoState as)
|
|||
}
|
||||
} else {
|
||||
AutomationWatch::instance().remove_automation_watch (shared_from_this());
|
||||
Changed (false, Controllable::NoGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1170,6 +1170,7 @@ PluginInsert::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame
|
|||
|
||||
} else {
|
||||
bypass (bufs, nframes);
|
||||
automation_run (start_frame, nframes);
|
||||
_delaybuffers.flush ();
|
||||
}
|
||||
|
||||
|
|
|
@ -322,7 +322,7 @@ Route::process_output_buffers (BufferSet& bufs,
|
|||
return;
|
||||
}
|
||||
|
||||
_mute_control->automation_run (start_frame, nframes);
|
||||
automation_run (start_frame, nframes);
|
||||
|
||||
/* figure out if we're going to use gain automation */
|
||||
if (gain_automation_ok) {
|
||||
|
@ -2980,11 +2980,16 @@ Route::silence_unlocked (framecnt_t nframes)
|
|||
|
||||
_output->silence (nframes);
|
||||
|
||||
// update owned automated controllables
|
||||
automation_run (now, nframes);
|
||||
|
||||
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
||||
boost::shared_ptr<PluginInsert> pi;
|
||||
|
||||
if (!_active && (pi = boost::dynamic_pointer_cast<PluginInsert> (*i)) != 0) {
|
||||
// skip plugins, they don't need anything when we're not active
|
||||
/* evaluate automated automation controls */
|
||||
pi->automation_run (now, nframes);
|
||||
/* skip plugins, they don't need anything when we're not active */
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
#include "ardour/slave.h"
|
||||
#include "ardour/ticker.h"
|
||||
#include "ardour/types.h"
|
||||
#include "ardour/vca.h"
|
||||
#include "ardour/vca_manager.h"
|
||||
|
||||
#include "midi++/mmc.h"
|
||||
|
||||
|
@ -142,6 +144,11 @@ Session::no_roll (pframes_t nframes)
|
|||
|
||||
ltc_tx_send_time_code_for_cycle (_transport_frame, end_frame, _target_transport_speed, _transport_speed, nframes);
|
||||
|
||||
VCAList v = _vca_manager->vcas ();
|
||||
for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
|
||||
(*i)->automation_run (_transport_frame, nframes);
|
||||
}
|
||||
|
||||
if (_process_graph) {
|
||||
DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/no-roll\n");
|
||||
_process_graph->routes_no_roll( nframes, _transport_frame, end_frame, non_realtime_work_pending(), declick);
|
||||
|
@ -180,6 +187,11 @@ Session::process_routes (pframes_t nframes, bool& need_butler)
|
|||
const framepos_t start_frame = _transport_frame;
|
||||
const framepos_t end_frame = _transport_frame + floor (nframes * _transport_speed);
|
||||
|
||||
VCAList v = _vca_manager->vcas ();
|
||||
for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
|
||||
(*i)->automation_run (start_frame, nframes);
|
||||
}
|
||||
|
||||
if (_process_graph) {
|
||||
DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/process-routes\n");
|
||||
if (_process_graph->process_routes (nframes, start_frame, end_frame, declick, need_butler) < 0) {
|
||||
|
@ -225,6 +237,11 @@ Session::silent_process_routes (pframes_t nframes, bool& need_butler)
|
|||
const framepos_t start_frame = _transport_frame;
|
||||
const framepos_t end_frame = _transport_frame + lrintf(nframes * _transport_speed);
|
||||
|
||||
VCAList v = _vca_manager->vcas ();
|
||||
for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
|
||||
(*i)->automation_run (start_frame, nframes);
|
||||
}
|
||||
|
||||
if (_process_graph) {
|
||||
_process_graph->silent_process_routes (nframes, start_frame, end_frame, need_butler);
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue
Block a user