summaryrefslogtreecommitdiff
path: root/libs/ardour/audio_port.cc
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2017-10-29 18:30:18 +0100
committerRobin Gareus <robin@gareus.org>2017-10-29 20:04:00 +0100
commit927788a0b0bf6a621e7cee60365f4e8cbd67d829 (patch)
tree43ebe89319b4b9416391f2f195dbc4f8effad161 /libs/ardour/audio_port.cc
parent7fb3c3e137d7a96998f21a4ec275339b4bc08c1a (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.cc69
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);
}
-
-
-
-