Prepare to allow to disable latency-compensation
Previously "zero custom/user latency" meant "default plugin latency". This is now saved in a separate boolean allowing a user to reduce a processor's latency to zero. This also prepares for a global switch to use zero latency throughout the whole session.
This commit is contained in:
parent
26f37a4753
commit
3cffaeac74
|
@ -26,27 +26,61 @@
|
|||
namespace ARDOUR {
|
||||
|
||||
class LIBARDOUR_API Latent {
|
||||
public:
|
||||
public:
|
||||
Latent() : _user_latency (0) {}
|
||||
virtual ~Latent() {}
|
||||
|
||||
virtual samplecnt_t signal_latency() const = 0;
|
||||
samplecnt_t user_latency () const { return _user_latency; }
|
||||
|
||||
/* effective latency to be used while processing */
|
||||
samplecnt_t effective_latency() const {
|
||||
if (_user_latency) {
|
||||
if (_zero_latency) {
|
||||
return 0;
|
||||
} else if (_use_user_latency) {
|
||||
return _user_latency;
|
||||
} else {
|
||||
return signal_latency ();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void set_user_latency (samplecnt_t val) { _user_latency = val; }
|
||||
/* custom user-set latency, if any */
|
||||
samplecnt_t user_latency () const {
|
||||
if (_use_user_latency) {
|
||||
return _user_latency;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
samplecnt_t _user_latency;
|
||||
void unset_user_latency () {
|
||||
_use_user_latency = false;
|
||||
_user_latency = 0;
|
||||
}
|
||||
|
||||
virtual void set_user_latency (samplecnt_t val) {
|
||||
_use_user_latency = true;
|
||||
_user_latency = val;
|
||||
}
|
||||
|
||||
static void force_zero_latency (bool en) {
|
||||
_zero_latency = en;
|
||||
}
|
||||
|
||||
static bool zero_latency () {
|
||||
return _zero_latency;
|
||||
}
|
||||
|
||||
protected:
|
||||
int set_state (const XMLNode& node, int version);
|
||||
void add_state (XMLNode*) const;
|
||||
|
||||
private:
|
||||
samplecnt_t _use_user_latency;
|
||||
samplecnt_t _user_latency;
|
||||
static bool _zero_latency;
|
||||
};
|
||||
|
||||
}
|
||||
} /* namespace */
|
||||
|
||||
|
||||
#endif /* __ardour_latent_h__*/
|
||||
|
|
|
@ -536,7 +536,7 @@ IO::state ()
|
|||
node->add_child_nocopy (*pnode);
|
||||
}
|
||||
|
||||
node->set_property (X_("user-latency"), _user_latency);
|
||||
Latent::add_state (node);
|
||||
|
||||
return *node;
|
||||
}
|
||||
|
@ -597,7 +597,7 @@ IO::set_state (const XMLNode& node, int version)
|
|||
ConnectingLegal.connect_same_thread (connection_legal_c, boost::bind (&IO::connecting_became_legal, this));
|
||||
}
|
||||
|
||||
node.get_property ("user-latency", _user_latency);
|
||||
Latent::set_state (node, version);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -528,10 +528,6 @@ LadspaPlugin::describe_parameter (Evoral::Parameter which)
|
|||
ARDOUR::samplecnt_t
|
||||
LadspaPlugin::signal_latency () const
|
||||
{
|
||||
if (_user_latency) {
|
||||
return _user_latency;
|
||||
}
|
||||
|
||||
if (_latency_control_port) {
|
||||
return (samplecnt_t) floor (*_latency_control_port);
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (C) 2018 Robin Gareus <robin@gareus.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "pbd/xml++.h"
|
||||
|
||||
#include "ardour/latent.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
|
||||
bool ARDOUR::Latent::_zero_latency = false;
|
||||
|
||||
int
|
||||
Latent::set_state (const XMLNode& node, int version)
|
||||
{
|
||||
node.get_property ("user-latency", _user_latency);
|
||||
if (!node.get_property ("use-user-latency", _use_user_latency)) {
|
||||
_use_user_latency = _user_latency > 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Latent::add_state (XMLNode* node) const
|
||||
{
|
||||
node->set_property ("user-latency", _user_latency);
|
||||
node->set_property ("use-user-latency", _use_user_latency);
|
||||
}
|
|
@ -651,8 +651,10 @@ PluginInsert::activate ()
|
|||
if (!owner ()) {
|
||||
return;
|
||||
}
|
||||
if (_plugin_signal_latency != signal_latency ()) {
|
||||
_plugin_signal_latency = signal_latency ();
|
||||
|
||||
const samplecnt_t l = effective_latency ();
|
||||
if (_plugin_signal_latency != l) {
|
||||
_plugin_signal_latency = l;
|
||||
latency_changed ();
|
||||
}
|
||||
}
|
||||
|
@ -671,8 +673,10 @@ PluginInsert::deactivate ()
|
|||
for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
|
||||
(*i)->deactivate ();
|
||||
}
|
||||
if (_plugin_signal_latency != signal_latency ()) {
|
||||
_plugin_signal_latency = signal_latency ();
|
||||
|
||||
const samplecnt_t l = effective_latency ();
|
||||
if (_plugin_signal_latency != l) {
|
||||
_plugin_signal_latency = l;
|
||||
latency_changed ();
|
||||
}
|
||||
}
|
||||
|
@ -1063,8 +1067,9 @@ PluginInsert::connect_and_run (BufferSet& bufs, samplepos_t start, samplepos_t e
|
|||
}
|
||||
}
|
||||
|
||||
if (_plugin_signal_latency != signal_latency ()) {
|
||||
_plugin_signal_latency = signal_latency ();
|
||||
const samplecnt_t l = effective_latency ();
|
||||
if (_plugin_signal_latency != l) {
|
||||
_plugin_signal_latency = l;
|
||||
latency_changed ();
|
||||
}
|
||||
}
|
||||
|
@ -2906,11 +2911,7 @@ PluginInsert::signal_latency() const
|
|||
if (!_pending_active) {
|
||||
return 0;
|
||||
}
|
||||
if (_user_latency) {
|
||||
return _user_latency;
|
||||
}
|
||||
|
||||
return _plugins[0]->signal_latency ();
|
||||
return plugin_latency ();
|
||||
}
|
||||
|
||||
ARDOUR::PluginType
|
||||
|
|
|
@ -79,8 +79,8 @@ PortInsert::start_latency_detection ()
|
|||
void
|
||||
PortInsert::stop_latency_detection ()
|
||||
{
|
||||
_latency_flush_samples = signal_latency() + _session.engine().samples_per_cycle();
|
||||
_latency_detect = false;
|
||||
_latency_flush_samples = effective_latency() + _session.engine().samples_per_cycle();
|
||||
_latency_detect = false;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -232,11 +232,11 @@ PortInsert::signal_latency() const
|
|||
need to take that into account too.
|
||||
*/
|
||||
|
||||
if (_measured_latency == 0) {
|
||||
return _session.engine().samples_per_cycle() + _input->signal_latency();
|
||||
} else {
|
||||
return _measured_latency;
|
||||
}
|
||||
if (_measured_latency == 0) {
|
||||
return _session.engine().samples_per_cycle() + _input->effective_latency ();
|
||||
} else {
|
||||
return _measured_latency;
|
||||
}
|
||||
}
|
||||
|
||||
/** Caller must hold process lock */
|
||||
|
|
|
@ -146,7 +146,7 @@ Processor::state ()
|
|||
}
|
||||
}
|
||||
|
||||
node->set_property("user-latency", _user_latency);
|
||||
Latent::add_state (node);
|
||||
|
||||
return *node;
|
||||
}
|
||||
|
@ -252,7 +252,7 @@ Processor::set_state (const XMLNode& node, int version)
|
|||
}
|
||||
}
|
||||
|
||||
node.get_property ("user-latency", _user_latency);
|
||||
Latent::set_state (node, version);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -502,7 +502,7 @@ Route::process_output_buffers (BufferSet& bufs,
|
|||
* So there can be cases where adding up all latencies may not equal _signal_latency.
|
||||
*/
|
||||
if ((*i)->active ()) {
|
||||
latency += (*i)->signal_latency ();
|
||||
latency += (*i)->effective_latency ();
|
||||
}
|
||||
|
||||
if (re_inject_oob_data) {
|
||||
|
@ -569,7 +569,7 @@ Route::bounce_process (BufferSet& buffers, samplepos_t start, samplecnt_t nframe
|
|||
if (!(*i)->does_routing() && !boost::dynamic_pointer_cast<PeakMeter>(*i)) {
|
||||
(*i)->run (buffers, start - latency, start - latency + nframes, 1.0, nframes, true);
|
||||
buffers.set_count ((*i)->output_streams());
|
||||
latency += (*i)->signal_latency ();
|
||||
latency += (*i)->effective_latency ();
|
||||
}
|
||||
|
||||
if ((*i) == endpoint) {
|
||||
|
@ -598,7 +598,7 @@ Route::bounce_get_latency (boost::shared_ptr<Processor> endpoint,
|
|||
break;
|
||||
}
|
||||
if (!(*i)->does_routing() && !boost::dynamic_pointer_cast<PeakMeter>(*i)) {
|
||||
latency += (*i)->signal_latency ();
|
||||
latency += (*i)->effective_latency ();
|
||||
}
|
||||
if ((*i) == endpoint) {
|
||||
break;
|
||||
|
@ -1129,7 +1129,7 @@ Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor>
|
|||
}
|
||||
}
|
||||
|
||||
_output->set_user_latency (0);
|
||||
_output->unset_user_latency ();
|
||||
}
|
||||
|
||||
reset_instrument_info ();
|
||||
|
@ -1448,7 +1448,7 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
|
|||
++i;
|
||||
}
|
||||
|
||||
_output->set_user_latency (0);
|
||||
_output->unset_user_latency ();
|
||||
}
|
||||
|
||||
if (!removed) {
|
||||
|
@ -1576,7 +1576,7 @@ Route::replace_processor (boost::shared_ptr<Processor> old, boost::shared_ptr<Pr
|
|||
}
|
||||
|
||||
sub->ActiveChanged.connect_same_thread (*this, boost::bind (&Session::update_latency_compensation, &_session, false));
|
||||
_output->set_user_latency (0);
|
||||
_output->unset_user_latency ();
|
||||
}
|
||||
|
||||
reset_instrument_info ();
|
||||
|
@ -1648,7 +1648,7 @@ Route::remove_processors (const ProcessorList& to_be_deleted, ProcessorStreams*
|
|||
return 0;
|
||||
}
|
||||
|
||||
_output->set_user_latency (0);
|
||||
_output->unset_user_latency ();
|
||||
|
||||
if (configure_processors_unlocked (err, &lm)) {
|
||||
pstate.restore ();
|
||||
|
@ -4038,7 +4038,7 @@ Route::update_signal_latency (bool apply_to_delayline)
|
|||
Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
|
||||
|
||||
samplecnt_t l_in = 0;
|
||||
samplecnt_t l_out = _output->user_latency();
|
||||
samplecnt_t l_out = _output->effective_latency ();
|
||||
for (ProcessorList::reverse_iterator i = _processors.rbegin(); i != _processors.rend(); ++i) {
|
||||
if (boost::shared_ptr<Send> snd = boost::dynamic_pointer_cast<Send> (*i)) {
|
||||
snd->set_delay_in (l_out + _output->latency());
|
||||
|
@ -4052,8 +4052,8 @@ Route::update_signal_latency (bool apply_to_delayline)
|
|||
}
|
||||
}
|
||||
(*i)->set_output_latency (l_out);
|
||||
if ((*i)->active ()) {
|
||||
l_out += (*i)->signal_latency ();
|
||||
if ((*i)->active ()) { // XXX
|
||||
l_out += (*i)->effective_latency ();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4087,7 +4087,7 @@ Route::update_signal_latency (bool apply_to_delayline)
|
|||
(*i)->set_playback_offset (_signal_latency + _output->latency ());
|
||||
(*i)->set_capture_offset (_input->latency ());
|
||||
if ((*i)->active ()) {
|
||||
l_in += (*i)->signal_latency ();
|
||||
l_in += (*i)->effective_latency ();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4644,7 +4644,7 @@ Route::set_private_port_latencies (bool playback) const
|
|||
for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
|
||||
|
||||
if ((*i)->active ()) {
|
||||
own_latency += (*i)->signal_latency ();
|
||||
own_latency += (*i)->effective_latency ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -141,9 +141,6 @@ Send::signal_latency () const
|
|||
if (!_pending_active) {
|
||||
return 0;
|
||||
}
|
||||
if (_user_latency) {
|
||||
return _user_latency;
|
||||
}
|
||||
if (_delay_out > _delay_in) {
|
||||
return _delay_out - _delay_in;
|
||||
}
|
||||
|
|
|
@ -645,10 +645,6 @@ VSTPlugin::describe_parameter (Evoral::Parameter param)
|
|||
samplecnt_t
|
||||
VSTPlugin::signal_latency () const
|
||||
{
|
||||
if (_user_latency) {
|
||||
return _user_latency;
|
||||
}
|
||||
|
||||
#if ( defined(__x86_64__) || defined(_M_X64) )
|
||||
return *((int32_t *) (((char *) &_plugin->flags) + 24)); /* initialDelay */
|
||||
#else
|
||||
|
|
|
@ -113,6 +113,7 @@ libardour_sources = [
|
|||
'io_processor.cc',
|
||||
'kmeterdsp.cc',
|
||||
'ladspa_plugin.cc',
|
||||
'latent.cc',
|
||||
'legatize.cc',
|
||||
'location.cc',
|
||||
'location_importer.cc',
|
||||
|
|
Loading…
Reference in New Issue