Allow to configure vari-speed resampler quality

This also allows to disable the resampler, effectively disabling
varispeed support, for the benefit of adding no additional latency.
By default 2 * 16 samples latency are added, due to port-resampler,
this is not desirable if Ardour is used as mixer only.
This commit is contained in:
Robin Gareus 2022-05-23 15:42:16 +02:00
parent bb4a45ebaf
commit e863a7dbc9
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
6 changed files with 52 additions and 34 deletions

View File

@ -158,7 +158,11 @@ public:
static pframes_t cycle_nframes () { return _cycle_nframes; }
static double speed_ratio () { return _speed_ratio; }
static uint32_t resampler_quality () { return _resampler_quality; }
static uint32_t resampler_latency () { return _resampler_latency; }
static bool can_varispeed () { return _resampler_latency > 0; }
static void setup_resampler (uint32_t q = 17);
protected:
@ -175,7 +179,6 @@ protected:
LatencyRange _private_capture_latency;
static double _speed_ratio;
static const uint32_t _resampler_quality; /* also latency of the resampler */
private:
std::string _name; ///< port short name
@ -188,6 +191,9 @@ private:
*/
std::set<std::string> _connections;
static uint32_t _resampler_quality; // 8 <= q <= 96
static uint32_t _resampler_latency; // = _resampler_quality - 1
void port_connected_or_disconnected (boost::weak_ptr<Port>, boost::weak_ptr<Port>, bool);
void signal_drop ();
void session_global_drop ();

View File

@ -40,6 +40,9 @@ CONFIG_VARIABLE (AutoConnectOption, output_auto_connect, "output-auto-connect",
CONFIG_VARIABLE (AutoConnectOption, input_auto_connect, "input-auto-connect", AutoConnectPhysical)
CONFIG_VARIABLE (bool, strict_io, "strict-io", true)
/* 0: off, no varispeed, q: 8..96 */
CONFIG_VARIABLE (uint32_t, port_resampler_quality, "port-resampler-quality,", 17)
/* Connect all physical inputs to a dummy port, this makes raw input data available.
* `jack_port_get_buffer (jack_port_by_name (c, "system:capture_1") , n_samples);`
* nees to work for input-monitoring (recorder page).

View File

@ -42,7 +42,7 @@ AudioPort::AudioPort (const std::string& name, PortFlags flags)
, _data (0)
{
assert (name.find_first_of (':') == string::npos);
_src.setup (_resampler_quality);
_src.setup (resampler_quality ());
_src.set_rrfilt (10);
}

View File

@ -699,9 +699,9 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
}
if (_xrun_flag) {
/* There still are `Port::resampler_quality () -1` samples in the resampler
/* There still are `Port::resampler_latency ()` samples in the resampler
* buffer from before the xrun. */
_xruns.push_back (_capture_captured + Port::resampler_quality () - 1);
_xruns.push_back (_capture_captured + Port::resampler_latency ());
}
_capture_captured += rec_nframes;

View File

@ -613,6 +613,8 @@ ARDOUR::init (bool try_optimization, const char* localedir, bool with_gui)
}
#endif
Port::setup_resampler (Config->get_port_resampler_quality ());
setup_hardware_optimization (try_optimization);
if (Config->get_cpu_dma_latency () >= 0) {

View File

@ -47,7 +47,8 @@ pframes_t Port::_global_port_buffer_offset = 0;
pframes_t Port::_cycle_nframes = 0;
double Port::_speed_ratio = 1.0;
std::string Port::state_node_name = X_("Port");
const uint32_t Port::_resampler_quality = 17;
uint32_t Port::_resampler_quality = 17;
uint32_t Port::_resampler_latency = 16; // = _resampler_quality - 1;
/* a handy define to shorten what would otherwise be a needlessly verbose
* repeated phrase
@ -388,13 +389,9 @@ Port::set_public_latency_range (LatencyRange const& range, bool playback) const
if (_port_handle) {
LatencyRange r (range);
if (externally_connected () && 0 == (_flags & TransportSyncPort) && sends_output () == playback) {
#if 0
r.min *= _speed_ratio;
r.max *= _speed_ratio;
#endif
if (type () == DataType::AUDIO) {
r.min += (_resampler_quality - 1);
r.max += (_resampler_quality - 1);
r.min += (_resampler_latency);
r.max += (_resampler_latency);
}
}
port_engine.set_latency_range (_port_handle, playback, r);
@ -449,19 +446,6 @@ Port::public_latency_range (bool playback) const
if (_port_handle) {
r = port_engine.get_latency_range (_port_handle, playback);
if (externally_connected () && 0 == (_flags & TransportSyncPort) && sends_output () == playback) {
#if 0
r.min /= _speed_ratio;
r.max /= _speed_ratio;
#endif
#if 0
/* use value as set by set_public_latency_range */
if (type () == DataType::AUDIO) {
r.min += (_resampler_quality - 1);
r.max += (_resampler_quality - 1);
}
#endif
}
DEBUG_TRACE (DEBUG::LatencyIO, string_compose (
"GET PORT %1: %4 PUBLIC latency range %2 .. %3\n",
@ -493,8 +477,8 @@ Port::collect_latency_from_backend (LatencyRange& range, bool playback) const
if (!AudioEngine::instance()->port_is_mine (*c)) {
if (externally_connected () && 0 == (_flags & TransportSyncPort) && sends_output () == playback) {
if (type () == DataType::AUDIO) {
lr.min += (_resampler_quality - 1);
lr.max += (_resampler_quality - 1);
lr.min += (_resampler_latency);
lr.max += (_resampler_latency);
}
}
}
@ -542,13 +526,9 @@ Port::get_connected_latency_range (LatencyRange& range, bool playback) const
if (remote_port) {
lr = port_engine.get_latency_range (remote_port, playback);
if (externally_connected () && 0 == (_flags & TransportSyncPort) && sends_output () == playback) {
#if 0
lr.min /= _speed_ratio;
lr.max /= _speed_ratio;
#endif
if (type () == DataType::AUDIO) {
lr.min += (_resampler_quality - 1);
lr.max += (_resampler_quality - 1);
lr.min += (_resampler_latency);
lr.max += (_resampler_latency);
}
}
@ -726,13 +706,40 @@ Port::set_state (const XMLNode& node, int)
return 0;
}
/* static */ void
Port::setup_resampler (uint32_t q)
{
/* configure at application start (Ardour::init) */
static bool setup_done = false;
if (setup_done) {
return;
}
setup_done = true;
if (q == 0) {
/* no vari-speed */
_resampler_quality = 0;
_resampler_latency = 0;
return;
}
// range constrained in VMResampler::setup
if (q < 8) {
q = 8;
}
if (q > 96) {
q = 96;
}
_resampler_quality = q;
_resampler_latency = q - 1;
}
/*static*/ void
Port::set_speed_ratio (double s) {
/* see VMResampler::set_rratio() for min/max range */
if (s == 0.0) {
if (s == 0.0 || !can_varispeed ()) {
/* no resampling when stopped */
_speed_ratio = 1.0;
} else {
/* see VMResampler::set_rratio() for min/max range */
_speed_ratio = std::min ((double) Config->get_max_transport_speed(), std::max (0.02, fabs (s)));
}
}