Add proper API to expose plugin tailtime
This is in preparation to display current tail time, and allow a user to override it. This is similar to existing processor latency API.
This commit is contained in:
parent
79fcb3d0ba
commit
520bbfe515
@ -40,6 +40,7 @@
|
||||
#include "ardour/midi_ring_buffer.h"
|
||||
#include "ardour/midi_state_tracker.h"
|
||||
#include "ardour/parameter_descriptor.h"
|
||||
#include "ardour/tailtime.h"
|
||||
#include "ardour/types.h"
|
||||
#include "ardour/variant.h"
|
||||
|
||||
@ -74,7 +75,7 @@ typedef std::set<uint32_t> PluginOutputConfiguration;
|
||||
*
|
||||
* Plugins are not used directly in Ardour but always wrapped by a PluginInsert.
|
||||
*/
|
||||
class LIBARDOUR_API Plugin : public PBD::StatefulDestructible, public HasLatency
|
||||
class LIBARDOUR_API Plugin : public PBD::StatefulDestructible, public HasLatency, public HasTailTime
|
||||
{
|
||||
public:
|
||||
Plugin (ARDOUR::AudioEngine&, ARDOUR::Session&);
|
||||
@ -172,12 +173,14 @@ public:
|
||||
return plugin_latency ();
|
||||
}
|
||||
|
||||
samplecnt_t signal_tailtime () const
|
||||
{
|
||||
return plugin_tailtime ();
|
||||
}
|
||||
|
||||
/** the max possible latency a plugin will have */
|
||||
virtual samplecnt_t max_latency () const { return 0; }
|
||||
|
||||
samplecnt_t effective_tail() const;
|
||||
PBD::Signal0<void> TailChanged;
|
||||
|
||||
virtual int set_block_size (pframes_t nframes) = 0;
|
||||
virtual bool requires_fixed_sized_buffers () const { return false; }
|
||||
virtual bool inplace_broken () const { return false; }
|
||||
@ -429,7 +432,7 @@ private:
|
||||
/** tail duration in samples. e.g. for reverb or delay plugins.
|
||||
*
|
||||
* The default when unknown is 2 sec */
|
||||
virtual samplecnt_t plugin_tail () const;
|
||||
virtual samplecnt_t plugin_tailtime () const;
|
||||
|
||||
|
||||
/** Fill _presets with our presets */
|
||||
|
@ -43,7 +43,7 @@ namespace ARDOUR
|
||||
{
|
||||
class ReadOnlyControl;
|
||||
|
||||
class LIBARDOUR_API RegionFxPlugin : public SessionObject, public PlugInsertBase, public Latent, public Temporal::TimeDomainProvider
|
||||
class LIBARDOUR_API RegionFxPlugin : public SessionObject, public PlugInsertBase, public Latent, public TailTime, public Temporal::TimeDomainProvider
|
||||
{
|
||||
public:
|
||||
RegionFxPlugin (Session&, Temporal::TimeDomain const, std::shared_ptr<Plugin> = std::shared_ptr<Plugin> ());
|
||||
@ -61,6 +61,8 @@ public:
|
||||
|
||||
/* Latent */
|
||||
samplecnt_t signal_latency () const;
|
||||
/* TailTime */
|
||||
samplecnt_t signal_tailtime () const;
|
||||
|
||||
/* PlugInsertBase */
|
||||
uint32_t get_count () const
|
||||
@ -153,10 +155,6 @@ public:
|
||||
return _required_buffers;
|
||||
}
|
||||
|
||||
/* wrapped Plugin API */
|
||||
PBD::Signal0<void> TailChanged;
|
||||
samplecnt_t effective_tail () const;
|
||||
|
||||
private:
|
||||
/* disallow copy construction */
|
||||
RegionFxPlugin (RegionFxPlugin const&);
|
||||
@ -178,7 +176,8 @@ private:
|
||||
/** details of the match currently being used */
|
||||
Match _match;
|
||||
|
||||
uint32_t _plugin_signal_latency;
|
||||
samplecnt_t _plugin_signal_latency;
|
||||
samplecnt_t _plugin_signal_tailtime;
|
||||
|
||||
typedef std::vector<std::shared_ptr<Plugin>> Plugins;
|
||||
Plugins _plugins;
|
||||
|
69
libs/ardour/ardour/tailtime.h
Normal file
69
libs/ardour/ardour/tailtime.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.
|
||||
*/
|
||||
|
||||
#ifndef __ardour_tailtime_h__
|
||||
#define __ardour_tailtime_h__
|
||||
|
||||
#include "pbd/signals.h"
|
||||
|
||||
#include "ardour/libardour_visibility.h"
|
||||
#include "ardour/types.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
class LIBARDOUR_API HasTailTime {
|
||||
public:
|
||||
virtual ~HasTailTime () {}
|
||||
virtual samplecnt_t signal_tailtime () const = 0;
|
||||
};
|
||||
|
||||
class LIBARDOUR_API TailTime : public HasTailTime {
|
||||
public:
|
||||
TailTime ();
|
||||
TailTime (TailTime const&);
|
||||
virtual ~TailTime() {}
|
||||
|
||||
samplecnt_t effective_tailtime () const;
|
||||
|
||||
samplecnt_t user_latency () const {
|
||||
if (_use_user_tailtime) {
|
||||
return _user_tailtime;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void unset_user_tailtime ();
|
||||
void set_user_tailtime (samplecnt_t val);
|
||||
|
||||
PBD::Signal0<void> TailTimeChanged;
|
||||
|
||||
protected:
|
||||
int set_state (const XMLNode& node, int version);
|
||||
void add_state (XMLNode*) const;
|
||||
|
||||
private:
|
||||
samplecnt_t _use_user_tailtime;
|
||||
samplecnt_t _user_tailtime;
|
||||
};
|
||||
|
||||
} /* namespace */
|
||||
|
||||
|
||||
#endif /* __ardour_tailtime_h__*/
|
||||
|
@ -182,7 +182,7 @@ public:
|
||||
|
||||
/* API for Ardour -- Setup/Processing */
|
||||
uint32_t plugin_latency ();
|
||||
uint32_t plugin_tail ();
|
||||
uint32_t plugin_tailtime ();
|
||||
bool set_block_size (int32_t);
|
||||
bool activate ();
|
||||
bool deactivate ();
|
||||
@ -444,7 +444,7 @@ public:
|
||||
|
||||
private:
|
||||
samplecnt_t plugin_latency () const;
|
||||
samplecnt_t plugin_tail () const;
|
||||
samplecnt_t plugin_tailtime () const;
|
||||
void init ();
|
||||
void find_presets ();
|
||||
void forward_resize_view (int w, int h);
|
||||
|
@ -2488,7 +2488,7 @@ AudioRegion::_add_plugin (std::shared_ptr<RegionFxPlugin> rfx, std::shared_ptr<R
|
||||
}
|
||||
|
||||
rfx->LatencyChanged.connect_same_thread (*this, boost::bind (&AudioRegion::fx_latency_changed, this, false));
|
||||
rfx->TailChanged.connect_same_thread (*this, boost::bind (&AudioRegion::fx_tail_changed, this, false));
|
||||
rfx->TailTimeChanged.connect_same_thread (*this, boost::bind (&AudioRegion::fx_tail_changed, this, false));
|
||||
rfx->set_block_size (_session.get_block_size ());
|
||||
|
||||
if (from_set_state) {
|
||||
@ -2576,7 +2576,7 @@ AudioRegion::fx_tail_changed (bool no_emit)
|
||||
{
|
||||
uint32_t t = 0;
|
||||
for (auto const& rfx : _plugins) {
|
||||
t = max<uint32_t> (t, rfx->effective_tail ());
|
||||
t = max<uint32_t> (t, rfx->effective_tailtime ());
|
||||
}
|
||||
if (t == _fx_tail) {
|
||||
return;
|
||||
|
@ -318,14 +318,7 @@ Plugin::input_streams () const
|
||||
}
|
||||
|
||||
samplecnt_t
|
||||
Plugin::effective_tail () const
|
||||
{
|
||||
/* consider adding a user-override per plugin; compare to HasLatency, Latent */
|
||||
return max<samplecnt_t> (0, min<samplecnt_t> (plugin_tail (), Config->get_max_tail_samples ()));
|
||||
}
|
||||
|
||||
samplecnt_t
|
||||
Plugin::plugin_tail () const
|
||||
Plugin::plugin_tailtime () const
|
||||
{
|
||||
return _session.sample_rate () * Config->get_tail_duration_sec ();
|
||||
}
|
||||
|
@ -2475,7 +2475,7 @@ Region::fx_tail_changed (bool)
|
||||
{
|
||||
uint32_t t = 0;
|
||||
for (auto const& rfx : _plugins) {
|
||||
t = max<uint32_t> (t, rfx->plugin()->effective_tail ());
|
||||
t = max<uint32_t> (t, rfx->effective_tailtime ());
|
||||
}
|
||||
if (t == _fx_tail) {
|
||||
return;
|
||||
|
@ -250,6 +250,7 @@ RegionFxPlugin::get_state () const
|
||||
XMLNode* node = new XMLNode (/*state_node_name*/ "RegionFXPlugin");
|
||||
|
||||
Latent::add_state (node);
|
||||
TailTime::add_state (node);
|
||||
|
||||
node->set_property ("type", _plugins[0]->state_node_name ());
|
||||
node->set_property ("unique-id", _plugins[0]->unique_id ());
|
||||
@ -383,6 +384,10 @@ RegionFxPlugin::set_state (const XMLNode& node, int version)
|
||||
ac->Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
|
||||
}
|
||||
}
|
||||
|
||||
Latent::set_state (node, version);
|
||||
TailTime::set_state (node, version);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -422,7 +427,6 @@ RegionFxPlugin::add_plugin (std::shared_ptr<Plugin> plugin)
|
||||
plugin->ParameterChangedExternally.connect_same_thread (*this, boost::bind (&RegionFxPlugin::parameter_changed_externally, this, _1, _2));
|
||||
plugin->StartTouch.connect_same_thread (*this, boost::bind (&RegionFxPlugin::start_touch, this, _1));
|
||||
plugin->EndTouch.connect_same_thread (*this, boost::bind (&RegionFxPlugin::end_touch, this, _1));
|
||||
plugin->TailChanged.connect_same_thread (*this, [this](){ TailChanged (); });
|
||||
}
|
||||
|
||||
plugin->set_insert (this, _plugins.size ());
|
||||
@ -503,12 +507,12 @@ RegionFxPlugin::signal_latency () const
|
||||
}
|
||||
|
||||
ARDOUR::samplecnt_t
|
||||
RegionFxPlugin::effective_tail () const
|
||||
RegionFxPlugin::signal_tailtime () const
|
||||
{
|
||||
if (_plugins.empty ()) {
|
||||
return 0;
|
||||
}
|
||||
return _plugins.front ()->effective_tail ();
|
||||
return _plugins.front ()->signal_tailtime ();
|
||||
}
|
||||
|
||||
PlugInsertBase::UIElements
|
||||
@ -1440,6 +1444,11 @@ RegionFxPlugin::connect_and_run (BufferSet& bufs, samplepos_t start, samplepos_t
|
||||
_plugin_signal_latency= l;
|
||||
LatencyChanged (); /* EMIT SIGNAL */
|
||||
}
|
||||
const samplecnt_t t = effective_latency ();
|
||||
if (_plugin_signal_tailtime != l) {
|
||||
_plugin_signal_tailtime = t;
|
||||
TailTimeChanged (); /* EMIT SIGNAL */
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
87
libs/ardour/tailtime.cc
Normal file
87
libs/ardour/tailtime.cc
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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/tailtime.h"
|
||||
#include "ardour/rc_configuration.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
|
||||
TailTime::TailTime ()
|
||||
: HasTailTime ()
|
||||
, _use_user_tailtime (false)
|
||||
, _user_tailtime (0)
|
||||
{}
|
||||
|
||||
TailTime::TailTime (TailTime const& other)
|
||||
: HasTailTime ()
|
||||
, _use_user_tailtime (other._use_user_tailtime)
|
||||
, _user_tailtime (other._user_tailtime)
|
||||
{}
|
||||
|
||||
samplecnt_t
|
||||
TailTime::effective_tailtime () const
|
||||
{
|
||||
if (_use_user_tailtime) {
|
||||
return _user_tailtime;
|
||||
} else {
|
||||
return std::max<samplecnt_t> (0, std::min<samplecnt_t> (signal_tailtime (), Config->get_max_tail_samples ()));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TailTime::set_user_tailtime (samplecnt_t val)
|
||||
{
|
||||
if (_use_user_tailtime && _user_tailtime == val) {
|
||||
return;
|
||||
}
|
||||
_use_user_tailtime = true;
|
||||
_user_tailtime = val;
|
||||
TailTimeChanged (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
void
|
||||
TailTime::unset_user_tailtime ()
|
||||
{
|
||||
if (!_use_user_tailtime) {
|
||||
return;
|
||||
}
|
||||
_use_user_tailtime = false;
|
||||
_user_tailtime = 0;
|
||||
TailTimeChanged (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
TailTime::set_state (const XMLNode& node, int version)
|
||||
{
|
||||
node.get_property ("user-tailtime", _user_tailtime);
|
||||
if (!node.get_property ("use-user-tailtime", _use_user_tailtime)) {
|
||||
_use_user_tailtime = _user_tailtime > 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
TailTime::add_state (XMLNode* node) const
|
||||
{
|
||||
node->set_property ("user-tailtime", _user_tailtime);
|
||||
node->set_property ("use-user-tailtime", _use_user_tailtime);
|
||||
}
|
@ -678,9 +678,9 @@ VST3Plugin::set_block_size (pframes_t n_samples)
|
||||
}
|
||||
|
||||
samplecnt_t
|
||||
VST3Plugin::plugin_tail () const
|
||||
VST3Plugin::plugin_tailtime () const
|
||||
{
|
||||
return _plug->plugin_tail ();
|
||||
return _plug->plugin_tailtime ();
|
||||
}
|
||||
|
||||
samplecnt_t
|
||||
@ -1816,7 +1816,7 @@ VST3PI::plugin_latency ()
|
||||
}
|
||||
|
||||
uint32_t
|
||||
VST3PI::plugin_tail ()
|
||||
VST3PI::plugin_tailtime ()
|
||||
{
|
||||
if (!_plugin_tail) { // XXX this is currently never reset
|
||||
_plugin_tail = _processor->getTailSamples ();
|
||||
|
@ -256,6 +256,7 @@ libardour_sources = [
|
||||
'system_exec.cc',
|
||||
'revision.cc',
|
||||
'rt_midibuffer.cc',
|
||||
'tailtime.cc',
|
||||
'template_utils.cc',
|
||||
'tempo_map_importer.cc',
|
||||
'thawlist.cc',
|
||||
|
Loading…
Reference in New Issue
Block a user