Only show user-presets in favorite sidebar
[ardour.git] / libs / ardour / delayline.cc
1 /*
2     Copyright (C) 2006, 2013 Paul Davis
3     Copyright (C) 2013, 2014 Robin Gareus <robin@gareus.org>
4
5     This program is free software; you can redistribute it and/or modify it
6     under the terms of the GNU General Public License as published by the Free
7     Software Foundation; either version 2 of the License, or (at your option)
8     any later version.
9
10     This program is distributed in the hope that it will be useful, but WITHOUT
11     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13     for more details.
14
15     You should have received a copy of the GNU General Public License along
16     with this program; if not, write to the Free Software Foundation, Inc.,
17     675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include <assert.h>
21 #include <cmath>
22
23 #include "pbd/compose.h"
24
25 #include "ardour/audio_buffer.h"
26 #include "ardour/buffer_set.h"
27 #include "ardour/debug.h"
28 #include "ardour/delayline.h"
29 #include "ardour/midi_buffer.h"
30 #include "ardour/runtime_functions.h"
31
32 using namespace std;
33 using namespace PBD;
34 using namespace ARDOUR;
35
36 DelayLine::DelayLine (Session& s, const std::string& name)
37     : Processor (s, string_compose ("latcomp-%1-%2", name, this))
38                 , _bsiz (0)
39                 , _delay (0)
40                 , _pending_delay (0)
41                 , _roff (0)
42                 , _woff (0)
43                 , _pending_flush (false)
44 {
45 }
46
47 DelayLine::~DelayLine ()
48 {
49 }
50
51 bool
52 DelayLine::set_name (const string& name)
53 {
54         return Processor::set_name (string_compose ("latcomp-%1-%2", name, this));
55 }
56
57 #define FADE_LEN (128)
58
59 void
60 DelayLine::run (BufferSet& bufs, samplepos_t /* start_sample */, samplepos_t /* end_sample */, double /* speed */, pframes_t n_samples, bool)
61 {
62 #ifndef NDEBUG
63         Glib::Threads::Mutex::Lock lm (_set_delay_mutex, Glib::Threads::TRY_LOCK);
64         assert (lm.locked ());
65 #endif
66
67         const sampleoffset_t pending_delay = _pending_delay;
68         sampleoffset_t delay_diff = _delay - pending_delay;
69         const bool pending_flush = _pending_flush;
70         _pending_flush = false;
71
72         // TODO handle pending_flush.
73
74         /* Audio buffers */
75         if (_buf.size () == bufs.count ().n_audio () && _buf.size () > 0) {
76
77                 /* handle delay-changes first */
78                 if (delay_diff < 0) {
79                         /* delay increases: fade out, insert silence, fade-in */
80                         const samplecnt_t fade_in_len = std::min (n_samples, (pframes_t)FADE_LEN);
81                         samplecnt_t fade_out_len;
82
83                         if (_delay < FADE_LEN) {
84                                 /* if old delay was 0 or smaller than new-delay, add some data to fade.
85                                  * Add at most (FADE_LEN - _delay) samples, but no more than -delay_diff
86                                  */
87                                 samplecnt_t add = std::min ((samplecnt_t)FADE_LEN - _delay, (samplecnt_t) -delay_diff);
88                                 fade_out_len = std::min (_delay + add, (samplecnt_t)FADE_LEN);
89
90                                 if (add > 0) {
91                                         AudioDlyBuf::iterator bi = _buf.begin ();
92                                         for (BufferSet::audio_iterator i = bufs.audio_begin (); i != bufs.audio_end (); ++i, ++bi) {
93                                                 Sample* rb = (*bi).get ();
94                                                 write_to_rb (rb, i->data (), add);
95                                         }
96                                         _woff = (_woff + add) & _bsiz_mask;
97                                         delay_diff += add;
98                                 }
99                         } else {
100                                 fade_out_len = FADE_LEN;
101                         }
102
103                         /* fade-out, end of previously written data */
104                         for (AudioDlyBuf::iterator i = _buf.begin(); i != _buf.end (); ++i) {
105                                 Sample* rb = (*i).get ();
106                                 for (uint32_t s = 0; s < fade_out_len; ++s) {
107                                         sampleoffset_t off = (_woff + _bsiz - s) & _bsiz_mask;
108                                         rb[off] *= s / (float) fade_out_len;
109                                 }
110                                 /* clear data in rb */
111                                 // TODO optimize this using memset
112                                 for (uint32_t s = 0; s < -delay_diff; ++s) {
113                                         sampleoffset_t off = (_woff + _bsiz + s) & _bsiz_mask;
114                                         rb[off] = 0.f;
115                                 }
116                         }
117
118                         _woff = (_woff - delay_diff) & _bsiz_mask;
119
120                         /* fade-in, directly apply to input buffer */
121                         for (BufferSet::audio_iterator i = bufs.audio_begin (); i != bufs.audio_end (); ++i) {
122                                 Sample* src = i->data ();
123                                 for (uint32_t s = 0; s < fade_in_len; ++s) {
124                                         src[s] *= s / (float) fade_in_len;
125                                 }
126                         }
127                 } else if (delay_diff > 0) {
128                         /* delay decreases: cross-fade, if possible */
129                         const samplecnt_t fade_out_len = std::min (_delay, (samplecnt_t)FADE_LEN);
130                         const samplecnt_t fade_in_len = std::min (n_samples, (pframes_t)FADE_LEN);
131                         const samplecnt_t xfade_len = std::min (fade_out_len, fade_in_len);
132
133                         AudioDlyBuf::iterator bi = _buf.begin ();
134                         for (BufferSet::audio_iterator i = bufs.audio_begin (); i != bufs.audio_end (); ++i, ++bi) {
135                                 Sample* rb = (*bi).get ();
136                                 Sample* src = i->data ();
137
138                                 // TODO consider handling fade_out & fade_in separately
139                                 // if fade_out_len < fade_in_len.
140                                 for (uint32_t s = 0; s < xfade_len; ++s) {
141                                         sampleoffset_t off = (_roff + s) & _bsiz_mask;
142                                         const gain_t g = s / (float) xfade_len;
143                                         src[s] *= g;
144                                         src[s] += (1.f - g) * rb[off];
145                                 }
146                         }
147
148 #ifndef NDEBUG
149                         sampleoffset_t check = (_roff + delay_diff) & _bsiz_mask;
150 #endif
151                         _roff = (_woff + _bsiz - pending_delay) & _bsiz_mask;
152 #ifndef NDEBUG
153                         assert (_roff == check);
154 #endif
155                 }
156
157                 /* set new delay */
158                 _delay = pending_delay;
159
160                 if (pending_flush) {
161                         /* fade out data after read-pointer, clear buffer until write-pointer */
162                         const samplecnt_t fade_out_len = std::min (_delay, (samplecnt_t)FADE_LEN);
163
164                         for (AudioDlyBuf::iterator i = _buf.begin(); i != _buf.end (); ++i) {
165                                 Sample* rb = (*i).get ();
166                                 uint32_t s = 0;
167                                 for (; s < fade_out_len; ++s) {
168                                         sampleoffset_t off = (_roff + s) & _bsiz_mask;
169                                         rb[off] *= 1. - (s / (float) fade_out_len);
170                                 }
171                                 for (; s < _delay; ++s) {
172                                         sampleoffset_t off = (_roff + s) & _bsiz_mask;
173                                         rb[off] = 0;
174                                 }
175                                 assert (_woff == ((_roff + s) & _bsiz_mask));
176                         }
177                         // TODO consider adding a fade-in to bufs
178                 }
179
180                 /* delay audio buffers */
181                 assert (_delay == ((_woff - _roff + _bsiz) & _bsiz_mask));
182                 AudioDlyBuf::iterator bi = _buf.begin ();
183                 if (_delay == 0) {
184                         /* do nothing */
185                 } else if (n_samples <= _delay) {
186                         /* write all samples to rb, read all from rb */
187                         for (BufferSet::audio_iterator i = bufs.audio_begin (); i != bufs.audio_end (); ++i, ++bi) {
188                                 Sample* rb = (*bi).get ();
189                                 write_to_rb (rb, i->data (), n_samples);
190                                 read_from_rb (rb, i->data (), n_samples);
191                         }
192                         _roff = (_roff + n_samples) & _bsiz_mask;
193                         _woff = (_woff + n_samples) & _bsiz_mask;
194                 } else {
195                         /* only write _delay samples to ringbuffer, memmove buffer */
196                         samplecnt_t tail = n_samples - _delay;
197                         for (BufferSet::audio_iterator i = bufs.audio_begin (); i != bufs.audio_end (); ++i, ++bi) {
198                                 Sample* rb = (*bi).get ();
199                                 Sample* src = i->data ();
200                                 write_to_rb (rb, &src[tail], _delay);
201                                 memmove (&src[_delay], src, tail * sizeof(Sample));
202                                 read_from_rb (rb, src, _delay);
203                         }
204                         _roff = (_roff + _delay) & _bsiz_mask;
205                         _woff = (_woff + _delay) & _bsiz_mask;
206                 }
207         } else {
208                 /* set new delay for MIDI only */
209                 _delay = pending_delay;
210         }
211
212         if (_midi_buf.get ()) {
213                 for (BufferSet::midi_iterator i = bufs.midi_begin (); i != bufs.midi_end (); ++i) {
214                         if (i != bufs.midi_begin ()) { break; } // XXX only one buffer for now
215
216                         MidiBuffer* dly = _midi_buf.get ();
217                         MidiBuffer& mb (*i);
218                         if (pending_flush) {
219                                 dly->silence (n_samples);
220                         }
221
222                         // If the delay time changes, iterate over all events in the dly-buffer
223                         // and adjust the time in-place. <= 0 becomes 0.
224                         //
225                         // iterate over all events in dly-buffer and subtract one cycle
226                         // (n_samples) from the timestamp, bringing them closer to de-queue.
227                         for (MidiBuffer::iterator m = dly->begin (); m != dly->end (); ++m) {
228                                 MidiBuffer::TimeType *t = m.timeptr ();
229                                 if (*t > n_samples + delay_diff) {
230                                         *t -= n_samples + delay_diff;
231                                 } else {
232                                         *t = 0;
233                                 }
234                         }
235
236                         if (_delay != 0) {
237                                 // delay events in current-buffer, in place.
238                                 for (MidiBuffer::iterator m = mb.begin (); m != mb.end (); ++m) {
239                                         MidiBuffer::TimeType *t = m.timeptr ();
240                                         *t += _delay;
241                                 }
242                         }
243
244                         // move events from dly-buffer into current-buffer until n_samples
245                         // and remove them from the dly-buffer
246                         for (MidiBuffer::iterator m = dly->begin (); m != dly->end ();) {
247                                 const Evoral::Event<MidiBuffer::TimeType> ev (*m, false);
248                                 if (ev.time () >= n_samples) {
249                                         break;
250                                 }
251                                 mb.insert_event (ev);
252                                 m = dly->erase (m);
253                         }
254
255                         /* For now, this is only relevant if there is there's a positive delay.
256                          * In the future this could also be used to delay 'too early' events
257                          * (ie '_global_port_buffer_offset + _port_buffer_offset' - midi_port.cc)
258                          */
259                         if (_delay != 0) {
260                                 // move events after n_samples from current-buffer into dly-buffer
261                                 // and trim current-buffer after n_samples
262                                 for (MidiBuffer::iterator m = mb.begin (); m != mb.end ();) {
263                                         const Evoral::Event<MidiBuffer::TimeType> ev (*m, false);
264                                         if (ev.time () < n_samples) {
265                                                 ++m;
266                                                 continue;
267                                         }
268                                         dly->insert_event (ev);
269                                         m = mb.erase (m);
270                                 }
271                         }
272                 }
273         }
274 }
275
276 bool
277 DelayLine::set_delay (samplecnt_t signal_delay)
278 {
279 #ifndef NDEBUG
280         Glib::Threads::Mutex::Lock lm (_set_delay_mutex, Glib::Threads::TRY_LOCK);
281         assert (lm.locked ());
282 #endif
283
284         if (signal_delay < 0) {
285                 signal_delay = 0;
286                 cerr << "WARNING: latency compensation is not possible.\n";
287         }
288
289         if (signal_delay == _pending_delay) {
290                 DEBUG_TRACE (DEBUG::LatencyCompensation,
291                                 string_compose ("%1 set_delay - no change: %2 samples for %3 channels\n",
292                                         name (), signal_delay, _configured_output.n_audio ()));
293                 return false;
294         }
295
296         DEBUG_TRACE (DEBUG::LatencyCompensation,
297                         string_compose ("%1 set_delay to %2 samples for %3 channels\n",
298                                 name (), signal_delay, _configured_output.n_audio ()));
299
300         if (signal_delay + 8192 + 1 > _bsiz) {
301                 allocate_pending_buffers (signal_delay, _configured_output);
302         }
303
304         _pending_delay = signal_delay;
305         return true;
306 }
307
308 bool
309 DelayLine::can_support_io_configuration (const ChanCount& in, ChanCount& out)
310 {
311         out = in;
312         return true;
313 }
314
315 void
316 DelayLine::allocate_pending_buffers (samplecnt_t signal_delay, ChanCount const& cc)
317 {
318         assert (signal_delay >= 0);
319         samplecnt_t rbs = signal_delay + 8192 + 1;
320         rbs = std::max (_bsiz, rbs);
321
322         uint64_t power_of_two;
323         for (power_of_two = 1; 1 << power_of_two < rbs; ++power_of_two) {}
324         rbs = 1 << power_of_two;
325
326         if (cc.n_audio () == _buf.size () && _bsiz == rbs) {
327                 return;
328         }
329
330         _buf.clear ();
331         if (cc.n_audio () == 0) {
332                 return;
333         }
334
335         AudioDlyBuf pending_buf;
336         for (uint32_t i = 0; i < cc.n_audio (); ++i) {
337                 boost::shared_array<Sample> b (new Sample[rbs]);
338                 pending_buf.push_back (b);
339                 memset (b.get (), 0, rbs * sizeof (Sample));
340         }
341
342         AudioDlyBuf::iterator bo = _buf.begin ();
343         AudioDlyBuf::iterator bn = pending_buf.begin ();
344
345         for (; bo != _buf.end () && bn != pending_buf.end(); ++bo, ++bn) {
346                 Sample* rbo = (*bo).get ();
347                 Sample* rbn = (*bn).get ();
348                 if (_roff < _woff) {
349                         /* copy data between _roff .. _woff to new buffer */
350                         copy_vector (&rbn[_roff], &rbo[_roff], _woff - _roff);
351                 } else {
352                         /* copy data between _roff .. old_size to end of new buffer, increment _roff
353                          * copy data from 0.._woff to beginning of new buffer
354                          */
355                         sampleoffset_t offset = rbs - _bsiz;
356                         copy_vector (&rbn[_roff + offset], &rbo[_roff], _bsiz - _roff);
357                         copy_vector (rbn, rbo, _woff);
358                         _roff += offset;
359                         assert (_roff < rbs);
360                 }
361         }
362         _bsiz = rbs;
363         _bsiz_mask = _bsiz - 1;
364         _buf.swap (pending_buf);
365 }
366
367 bool
368 DelayLine::configure_io (ChanCount in, ChanCount out)
369 {
370 #ifndef NDEBUG
371         Glib::Threads::Mutex::Lock lm (_set_delay_mutex, Glib::Threads::TRY_LOCK);
372         assert (lm.locked ());
373 #endif
374
375         if (out != in) { // always 1:1
376                 return false;
377         }
378
379         if (_configured_output != out) {
380                 allocate_pending_buffers (_pending_delay, out);
381         }
382
383         DEBUG_TRACE (DEBUG::LatencyCompensation,
384                         string_compose ("configure IO: %1 Ain: %2 Aout: %3 Min: %4 Mout: %5\n",
385                                 name (), in.n_audio (), out.n_audio (), in.n_midi (), out.n_midi ()));
386
387         // TODO support multiple midi buffers
388         if (in.n_midi () > 0 && !_midi_buf) {
389                 _midi_buf.reset (new MidiBuffer (16384));
390         }
391 #ifndef NDEBUG
392         lm.release ();
393 #endif
394
395         return Processor::configure_io (in, out);
396 }
397
398 void
399 DelayLine::flush ()
400 {
401         _pending_flush = true;
402 }
403
404 XMLNode&
405 DelayLine::state ()
406 {
407         XMLNode& node (Processor::state ());
408         node.set_property ("type", "delay");
409         return node;
410 }
411
412 void
413 DelayLine::write_to_rb (Sample* rb, Sample* src, samplecnt_t n_samples)
414 {
415         assert (n_samples < _bsiz);
416         if (_woff + n_samples < _bsiz) {
417                 copy_vector (&rb[_woff], src, n_samples);
418         } else {
419                 const samplecnt_t s0 = _bsiz - _woff;
420                 const samplecnt_t s1 = n_samples - s0;
421
422                 copy_vector (&rb[_woff], src, s0);
423                 copy_vector (rb, &src[s0], s1);
424         }
425 }
426
427 void
428 DelayLine::read_from_rb (Sample* rb, Sample* dst, samplecnt_t n_samples)
429 {
430         assert (n_samples < _bsiz);
431         if (_roff + n_samples < _bsiz) {
432                 copy_vector (dst, &rb[_roff], n_samples);
433         } else {
434                 const samplecnt_t s0 = _bsiz - _roff;
435                 const samplecnt_t s1 = n_samples - s0;
436
437                 copy_vector (dst, &rb[_roff], s0);
438                 copy_vector (&dst[s0], rb, s1);
439         }
440 }