diff options
author | Robin Gareus <robin@gareus.org> | 2017-10-29 18:30:18 +0100 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2017-10-29 20:04:00 +0100 |
commit | 927788a0b0bf6a621e7cee60365f4e8cbd67d829 (patch) | |
tree | 43ebe89319b4b9416391f2f195dbc4f8effad161 /libs/ardour/port.cc | |
parent | 7fb3c3e137d7a96998f21a4ec275339b4bc08c1a (diff) |
Move vari-speed into backend (resample ports)
Previously Ardour used a /local/ per track vari-speed mechanism.
Now that the disk-reader is a latency-compensated processor, the speed
of each disk-reader would need to be maintained locally, offset by each
disk-reader's output latency. Furthermore each disk-reader may
produce a different number of samples, depending on its global alignment.
This commit introduces port-data resampling directly at the engine-level:
Up/down-sample all input ports at the beginning, and down/up-sample output
port-data using the inverse ratio at the end of the session's process
cycle.
The session itself is unaware of the speed-change, and only needs to
handle transport speeds {-1, 0, +1}.
This also allows for aligned cue-monitoring and vari-speed recording,
and also pitch-shifts synthesized MIDI along.
Diffstat (limited to 'libs/ardour/port.cc')
-rw-r--r-- | libs/ardour/port.cc | 55 |
1 files changed, 53 insertions, 2 deletions
diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc index 81290aa021..b469194ea5 100644 --- a/libs/ardour/port.cc +++ b/libs/ardour/port.cc @@ -43,7 +43,9 @@ PBD::Signal0<void> Port::PortSignalDrop; bool Port::_connecting_blocked = false; 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 = 12; /* a handy define to shorten what would otherwise be a needlessly verbose * repeated phrase @@ -350,7 +352,7 @@ Port::increment_port_buffer_offset (pframes_t nframes) } void -Port::set_public_latency_range (LatencyRange& range, bool playback) const +Port::set_public_latency_range (LatencyRange const& range, bool playback) const { /* this sets the visible latency that the rest of the port system sees. because we do latency compensation, all (most) of our visible @@ -363,7 +365,16 @@ Port::set_public_latency_range (LatencyRange& range, bool playback) const (playback ? "PLAYBACK" : "CAPTURE")));; if (_port_handle) { - port_engine.set_latency_range (_port_handle, playback, range); + LatencyRange r (range); + if (externally_connected ()) { +#if 0 + r.min *= _speed_ratio; + r.max *= _speed_ratio; +#endif + r.min += (_resampler_quality - 1); + r.max += (_resampler_quality - 1); + } + port_engine.set_latency_range (_port_handle, playback, r); } } @@ -419,6 +430,14 @@ Port::public_latency_range (bool /*playback*/) const if (_port_handle) { r = port_engine.get_latency_range (_port_handle, sends_output() ? true : false); + if (externally_connected ()) { +#if 0 + r.min /= _speed_ratio; + r.max /= _speed_ratio; +#endif + r.min += (_resampler_quality - 1); + r.max += (_resampler_quality - 1); + } DEBUG_TRACE (DEBUG::Latency, string_compose ( "GET PORT %1: %4 PUBLIC latency range %2 .. %3\n", @@ -458,6 +477,14 @@ 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 ()) { +#if 0 + lr.min /= _speed_ratio; + lr.max /= _speed_ratio; +#endif + lr.min += (_resampler_quality - 1); + lr.max += (_resampler_quality - 1); + } DEBUG_TRACE (DEBUG::Latency, string_compose ( "\t%1 <-> %2 : latter has latency range %3 .. %4\n", @@ -564,6 +591,19 @@ Port::physically_connected () const return port_engine.physically_connected (_port_handle); } +bool +Port::externally_connected () const +{ + if (!_port_handle) { + return false; + } + + // TODO: When used with JACK, check if this port + // is connected to any non-ardour ports. + + return port_engine.physically_connected (_port_handle); +} + XMLNode& Port::get_state () const { @@ -621,3 +661,14 @@ Port::set_state (const XMLNode& node, int) return 0; } + +/*static*/ void +Port::set_speed_ratio (double s) { + /* see VMResampler::set_rratio() for min/max range */ + _speed_ratio = std::min (16.0, std::max (0.5, s)); +} + +/*static*/ void +Port::set_cycle_samplecnt (pframes_t n) { + _cycle_nframes = floor (n * _speed_ratio); +} |