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/audio_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/audio_port.cc')
-rw-r--r-- | libs/ardour/audio_port.cc | 69 |
1 files changed, 61 insertions, 8 deletions
diff --git a/libs/ardour/audio_port.cc b/libs/ardour/audio_port.cc index 70943e35a3..a9d41afce2 100644 --- a/libs/ardour/audio_port.cc +++ b/libs/ardour/audio_port.cc @@ -18,6 +18,7 @@ #include <cassert> +#include "pbd/malign.h" #include "pbd/stacktrace.h" #include "ardour/audio_buffer.h" @@ -36,10 +37,14 @@ AudioPort::AudioPort (const std::string& name, PortFlags flags) , _buffer (new AudioBuffer (0)) { assert (name.find_first_of (':') == string::npos); + cache_aligned_malloc ((void**) &_data, sizeof (Sample) * 8192); + _src.setup (_resampler_quality); + _src.set_rrfilt (10); } AudioPort::~AudioPort () { + cache_aligned_free (_data); delete _buffer; } @@ -47,11 +52,32 @@ void AudioPort::cycle_start (pframes_t nframes) { /* caller must hold process lock */ - - Port::cycle_start (nframes); + Port::cycle_start (nframes); if (sends_output()) { _buffer->prepare (); + } else if (!externally_connected ()) { + /* ardour internal port, just silence input, don't resample */ + // TODO reset resampler only once + _src.reset (); + memset (_data, 0, _cycle_nframes * sizeof (float)); + } else { + _src.inp_data = (float*)port_engine.get_buffer (_port_handle, nframes); + _src.inp_count = nframes; + _src.out_count = _cycle_nframes; + _src.set_rratio (_cycle_nframes / (double)nframes); + _src.out_data = _data; + _src.process (); +#ifndef NDEBUG + if (_src.inp_count != 0 || _src.out_count != 0) { + printf ("AudioPort::cycle_start x-flow: %d/%d\n", _src.inp_count, _src.out_count); + } +#endif + while (_src.out_count > 0) { + *_src.out_data = _src.out_data[-1]; + ++_src.out_data; + --_src.out_count; + } } } @@ -66,6 +92,33 @@ AudioPort::cycle_end (pframes_t nframes) _buffer->silence (nframes); } } + + if (sends_output() && _port_handle) { + + if (!externally_connected ()) { + /* ardour internal port, data goes nowhere, skip resampling */ + // TODO reset resampler only once + _src.reset (); + return; + } + + _src.inp_count = _cycle_nframes; + _src.out_count = nframes; + _src.set_rratio (nframes / (double)_cycle_nframes); + _src.inp_data = _data; + _src.out_data = (float*)port_engine.get_buffer (_port_handle, nframes); + _src.process (); +#ifndef NDEBUG + if (_src.inp_count != 0 || _src.out_count != 0) { + printf ("AudioPort::cycle_end x-flow: %d/%d\n", _src.inp_count, _src.out_count); + } +#endif + while (_src.out_count > 0) { + *_src.out_data = _src.out_data[-1]; + ++_src.out_data; + --_src.out_count; + } + } } void @@ -78,8 +131,12 @@ AudioPort::get_audio_buffer (pframes_t nframes) { /* caller must hold process lock */ assert (_port_handle); - _buffer->set_data ((Sample *) port_engine.get_buffer (_port_handle, _cycle_nframes) + - _global_port_buffer_offset + _port_buffer_offset, nframes); + if (!externally_connected ()) { + _buffer->set_data ((Sample *) port_engine.get_buffer (_port_handle, _cycle_nframes) + + _global_port_buffer_offset + _port_buffer_offset, nframes); + } else { + _buffer->set_data (&_data[_global_port_buffer_offset + _port_buffer_offset], nframes); + } return *_buffer; } @@ -90,7 +147,3 @@ AudioPort::engine_get_whole_audio_buffer () assert (_port_handle); return (Sample *) port_engine.get_buffer (_port_handle, _cycle_nframes); } - - - - |