2 * Copyright (C) 2014-2017 Robin Gareus <robin@gareus.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "pbd/compose.h"
24 #include "ardour/audio_buffer.h"
25 #include "ardour/buffer_set.h"
26 #include "ardour/debug.h"
27 #include "ardour/delayline.h"
28 #include "ardour/midi_buffer.h"
29 #include "ardour/runtime_functions.h"
31 #define MAX_BUFFER_SIZE 8192
35 using namespace ARDOUR;
37 DelayLine::DelayLine (Session& s, const std::string& name)
38 : Processor (s, string_compose ("latcomp-%1-%2", name, this))
44 , _pending_flush (false)
48 DelayLine::~DelayLine ()
53 DelayLine::set_name (const string& name)
55 return Processor::set_name (string_compose ("latcomp-%1-%2", name, this));
58 #define FADE_LEN (128)
61 DelayLine::run (BufferSet& bufs, samplepos_t /* start_sample */, samplepos_t /* end_sample */, double /* speed */, pframes_t n_samples, bool)
64 Glib::Threads::Mutex::Lock lm (_set_delay_mutex, Glib::Threads::TRY_LOCK);
65 assert (lm.locked ());
67 assert (n_samples <= MAX_BUFFER_SIZE);
69 const sampleoffset_t pending_delay = _pending_delay;
70 sampleoffset_t delay_diff = _delay - pending_delay;
71 const bool pending_flush = _pending_flush;
73 if (delay_diff == 0 && _delay == 0) {
77 _pending_flush = false;
79 // TODO handle pending_flush.
82 if (_buf.size () == bufs.count ().n_audio () && _buf.size () > 0) {
84 /* handle delay-changes first */
86 /* delay increases: fade out, insert silence, fade-in */
87 const samplecnt_t fade_in_len = std::min (n_samples, (pframes_t)FADE_LEN);
88 samplecnt_t fade_out_len;
90 if (_delay < FADE_LEN) {
91 /* if old delay was 0 or smaller than new-delay, add some data to fade.
92 * Add at most (FADE_LEN - _delay) samples, but no more than -delay_diff
94 samplecnt_t add = std::min ((samplecnt_t)FADE_LEN - _delay, (samplecnt_t) -delay_diff);
95 fade_out_len = std::min (_delay + add, (samplecnt_t)FADE_LEN);
98 AudioDlyBuf::iterator bi = _buf.begin ();
99 for (BufferSet::audio_iterator i = bufs.audio_begin (); i != bufs.audio_end (); ++i, ++bi) {
100 Sample* rb = (*bi).get ();
101 write_to_rb (rb, i->data (), add);
103 _woff = (_woff + add) & _bsiz_mask;
107 fade_out_len = FADE_LEN;
110 /* fade-out, end of previously written data */
111 for (AudioDlyBuf::iterator i = _buf.begin(); i != _buf.end (); ++i) {
112 Sample* rb = (*i).get ();
113 for (uint32_t s = 0; s < fade_out_len; ++s) {
114 sampleoffset_t off = (_woff + _bsiz - s) & _bsiz_mask;
115 rb[off] *= s / (float) fade_out_len;
117 /* clear data in rb */
118 // TODO optimize this using memset
119 for (uint32_t s = 0; s < -delay_diff; ++s) {
120 sampleoffset_t off = (_woff + _bsiz + s) & _bsiz_mask;
125 _woff = (_woff - delay_diff) & _bsiz_mask;
127 /* fade-in, directly apply to input buffer */
128 for (BufferSet::audio_iterator i = bufs.audio_begin (); i != bufs.audio_end (); ++i) {
129 Sample* src = i->data ();
130 for (uint32_t s = 0; s < fade_in_len; ++s) {
131 src[s] *= s / (float) fade_in_len;
134 } else if (delay_diff > 0) {
135 /* delay decreases: cross-fade, if possible */
136 const samplecnt_t fade_out_len = std::min (_delay, (samplecnt_t)FADE_LEN);
137 const samplecnt_t fade_in_len = std::min (n_samples, (pframes_t)FADE_LEN);
138 const samplecnt_t xfade_len = std::min (fade_out_len, fade_in_len);
140 AudioDlyBuf::iterator bi = _buf.begin ();
141 for (BufferSet::audio_iterator i = bufs.audio_begin (); i != bufs.audio_end (); ++i, ++bi) {
142 Sample* rb = (*bi).get ();
143 Sample* src = i->data ();
145 // TODO consider handling fade_out & fade_in separately
146 // if fade_out_len < fade_in_len.
147 for (uint32_t s = 0; s < xfade_len; ++s) {
148 sampleoffset_t off = (_roff + s) & _bsiz_mask;
149 const gain_t g = s / (float) xfade_len;
151 src[s] += (1.f - g) * rb[off];
156 sampleoffset_t check = (_roff + delay_diff) & _bsiz_mask;
158 _roff = (_woff + _bsiz - pending_delay) & _bsiz_mask;
160 assert (_roff == check);
165 _delay = pending_delay;
168 /* fade out data after read-pointer, clear buffer until write-pointer */
169 const samplecnt_t fade_out_len = std::min (_delay, (samplecnt_t)FADE_LEN);
171 for (AudioDlyBuf::iterator i = _buf.begin(); i != _buf.end (); ++i) {
172 Sample* rb = (*i).get ();
174 for (; s < fade_out_len; ++s) {
175 sampleoffset_t off = (_roff + s) & _bsiz_mask;
176 rb[off] *= 1. - (s / (float) fade_out_len);
178 for (; s < _delay; ++s) {
179 sampleoffset_t off = (_roff + s) & _bsiz_mask;
182 assert (_woff == ((_roff + s) & _bsiz_mask));
184 // TODO consider adding a fade-in to bufs
187 /* delay audio buffers */
188 assert (_delay == ((_woff - _roff + _bsiz) & _bsiz_mask));
189 AudioDlyBuf::iterator bi = _buf.begin ();
192 } else if (n_samples <= _delay) {
193 /* write all samples to rb, read all from rb */
194 for (BufferSet::audio_iterator i = bufs.audio_begin (); i != bufs.audio_end (); ++i, ++bi) {
195 Sample* rb = (*bi).get ();
196 write_to_rb (rb, i->data (), n_samples);
197 read_from_rb (rb, i->data (), n_samples);
199 _roff = (_roff + n_samples) & _bsiz_mask;
200 _woff = (_woff + n_samples) & _bsiz_mask;
202 /* only write _delay samples to ringbuffer, memmove buffer */
203 samplecnt_t tail = n_samples - _delay;
204 for (BufferSet::audio_iterator i = bufs.audio_begin (); i != bufs.audio_end (); ++i, ++bi) {
205 Sample* rb = (*bi).get ();
206 Sample* src = i->data ();
207 write_to_rb (rb, &src[tail], _delay);
208 memmove (&src[_delay], src, tail * sizeof(Sample));
209 read_from_rb (rb, src, _delay);
211 _roff = (_roff + _delay) & _bsiz_mask;
212 _woff = (_woff + _delay) & _bsiz_mask;
215 /* set new delay for MIDI only */
216 _delay = pending_delay;
218 /* prepare for the case that an audio-port is added */
223 if (_midi_buf.get ()) {
224 for (BufferSet::midi_iterator i = bufs.midi_begin (); i != bufs.midi_end (); ++i) {
225 if (i != bufs.midi_begin ()) { break; } // XXX only one buffer for now
227 MidiBuffer* dly = _midi_buf.get ();
230 dly->silence (n_samples);
233 // If the delay time changes, iterate over all events in the dly-buffer
234 // and adjust the time in-place. <= 0 becomes 0.
236 // iterate over all events in dly-buffer and subtract one cycle
237 // (n_samples) from the timestamp, bringing them closer to de-queue.
238 for (MidiBuffer::iterator m = dly->begin (); m != dly->end (); ++m) {
239 MidiBuffer::TimeType *t = m.timeptr ();
240 if (*t > n_samples + delay_diff) {
241 *t -= n_samples + delay_diff;
248 // delay events in current-buffer, in place.
249 for (MidiBuffer::iterator m = mb.begin (); m != mb.end (); ++m) {
250 MidiBuffer::TimeType *t = m.timeptr ();
255 // move events from dly-buffer into current-buffer until n_samples
256 // and remove them from the dly-buffer
257 for (MidiBuffer::iterator m = dly->begin (); m != dly->end ();) {
258 const Evoral::Event<MidiBuffer::TimeType> ev (*m, false);
259 if (ev.time () >= n_samples) {
262 mb.insert_event (ev);
266 /* For now, this is only relevant if there is there's a positive delay.
267 * In the future this could also be used to delay 'too early' events
268 * (ie '_global_port_buffer_offset + _port_buffer_offset' - midi_port.cc)
271 // move events after n_samples from current-buffer into dly-buffer
272 // and trim current-buffer after n_samples
273 for (MidiBuffer::iterator m = mb.begin (); m != mb.end ();) {
274 const Evoral::Event<MidiBuffer::TimeType> ev (*m, false);
275 if (ev.time () < n_samples) {
279 dly->insert_event (ev);
288 DelayLine::set_delay (samplecnt_t signal_delay)
291 Glib::Threads::Mutex::Lock lm (_set_delay_mutex, Glib::Threads::TRY_LOCK);
292 assert (lm.locked ());
295 if (signal_delay < 0) {
297 cerr << "WARNING: latency compensation is not possible.\n";
300 if (signal_delay == _pending_delay) {
301 DEBUG_TRACE (DEBUG::LatencyCompensation,
302 string_compose ("%1 set_delay - no change: %2 samples for %3 channels\n",
303 name (), signal_delay, _configured_output.n_audio ()));
307 DEBUG_TRACE (DEBUG::LatencyCompensation,
308 string_compose ("%1 set_delay to %2 samples for %3 channels\n",
309 name (), signal_delay, _configured_output.n_audio ()));
311 if (signal_delay + MAX_BUFFER_SIZE + 1 > _bsiz) {
312 allocate_pending_buffers (signal_delay, _configured_output);
315 _pending_delay = signal_delay;
320 DelayLine::can_support_io_configuration (const ChanCount& in, ChanCount& out)
327 DelayLine::allocate_pending_buffers (samplecnt_t signal_delay, ChanCount const& cc)
329 assert (signal_delay >= 0);
331 /* If no buffers are required, don't allocate any.
332 * This may backfire later, allocating buffers on demand
333 * may take time and cause x-runs.
335 * The default buffersize is 4 * 16kB and - once allocated -
336 * usually sufficies for the lifetime of the delayline instance.
338 if (signal_delay == _pending_delay && signal_delay == 0) {
342 samplecnt_t rbs = signal_delay + MAX_BUFFER_SIZE + 1;
343 rbs = std::max (_bsiz, rbs);
345 uint64_t power_of_two;
346 for (power_of_two = 1; 1 << power_of_two < rbs; ++power_of_two) {}
347 rbs = 1 << power_of_two;
349 if (cc.n_audio () == _buf.size () && _bsiz == rbs) {
353 if (cc.n_audio () == 0) {
357 AudioDlyBuf pending_buf;
358 for (uint32_t i = 0; i < cc.n_audio (); ++i) {
359 boost::shared_array<Sample> b (new Sample[rbs]);
360 pending_buf.push_back (b);
361 memset (b.get (), 0, rbs * sizeof (Sample));
364 AudioDlyBuf::iterator bo = _buf.begin ();
365 AudioDlyBuf::iterator bn = pending_buf.begin ();
367 sampleoffset_t offset = (_roff <= _woff) ? 0 : rbs - _bsiz;
369 for (; bo != _buf.end () && bn != pending_buf.end(); ++bo, ++bn) {
370 Sample* rbo = (*bo).get ();
371 Sample* rbn = (*bn).get ();
372 if (_roff == _woff) {
374 } else if (_roff < _woff) {
375 /* copy data between _roff .. _woff to new buffer */
376 copy_vector (&rbn[_roff], &rbo[_roff], _woff - _roff);
378 /* copy data between _roff .. old_size to end of new buffer, increment _roff
379 * copy data from 0.._woff to beginning of new buffer
381 copy_vector (&rbn[_roff + offset], &rbo[_roff], _bsiz - _roff);
382 copy_vector (rbn, rbo, _woff);
386 assert (signal_delay >= _pending_delay);
387 assert ((_roff <= (_woff + signal_delay - _pending_delay) & (rbs -1)) || offset > 0);
389 assert (_roff < rbs);
392 _bsiz_mask = _bsiz - 1;
393 _buf.swap (pending_buf);
397 DelayLine::configure_io (ChanCount in, ChanCount out)
400 Glib::Threads::Mutex::Lock lm (_set_delay_mutex, Glib::Threads::TRY_LOCK);
401 assert (lm.locked ());
404 if (out != in) { // always 1:1
408 if (_configured_output != out) {
409 allocate_pending_buffers (_pending_delay, out);
412 DEBUG_TRACE (DEBUG::LatencyCompensation,
413 string_compose ("configure IO: %1 Ain: %2 Aout: %3 Min: %4 Mout: %5\n",
414 name (), in.n_audio (), out.n_audio (), in.n_midi (), out.n_midi ()));
416 // TODO support multiple midi buffers
417 if (in.n_midi () > 0 && !_midi_buf) {
418 _midi_buf.reset (new MidiBuffer (16384));
424 return Processor::configure_io (in, out);
430 _pending_flush = true;
436 XMLNode& node (Processor::state ());
437 node.set_property ("type", "delay");
442 DelayLine::write_to_rb (Sample* rb, Sample* src, samplecnt_t n_samples)
444 assert (n_samples < _bsiz);
445 if (_woff + n_samples < _bsiz) {
446 copy_vector (&rb[_woff], src, n_samples);
448 const samplecnt_t s0 = _bsiz - _woff;
449 const samplecnt_t s1 = n_samples - s0;
451 copy_vector (&rb[_woff], src, s0);
452 copy_vector (rb, &src[s0], s1);
457 DelayLine::read_from_rb (Sample* rb, Sample* dst, samplecnt_t n_samples)
459 assert (n_samples < _bsiz);
460 if (_roff + n_samples < _bsiz) {
461 copy_vector (dst, &rb[_roff], n_samples);
463 const samplecnt_t s0 = _bsiz - _roff;
464 const samplecnt_t s1 = n_samples - s0;
466 copy_vector (dst, &rb[_roff], s0);
467 copy_vector (&dst[s0], rb, s1);