Add option to limit automatable control parmaters
[ardour.git] / libs / ardour / fixed_delay.cc
1 /*
2  * Copyright (C) 2016 Robin Gareus <robin@gareus.org>
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
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.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18
19 #include "ardour/audio_buffer.h"
20 #include "ardour/buffer_set.h"
21 #include "ardour/fixed_delay.h"
22 #include "ardour/midi_buffer.h"
23
24 using namespace ARDOUR;
25
26 FixedDelay::FixedDelay ()
27         : _max_delay (0)
28         , _buf_size (0)
29         , _delay (0)
30 {
31         for (size_t i = 0; i < DataType::num_types; ++i) {
32                 _buffers.push_back (BufferVec ());
33         }
34         _count.reset ();
35 }
36
37 FixedDelay::~FixedDelay ()
38 {
39         clear ();
40 }
41
42 void
43 FixedDelay::ensure_buffers (DataType type, size_t num_buffers, size_t buffer_capacity)
44 {
45         assert (type != DataType::NIL);
46         assert (type < _buffers.size ());
47         if (num_buffers == 0) {
48                 return;
49         }
50         BufferVec& bufs = _buffers[type];
51         if (bufs.size () < num_buffers || (bufs.size () > 0 && bufs[0]->buf->capacity () < buffer_capacity)) {
52                 for (BufferVec::iterator i = bufs.begin (); i != bufs.end (); ++i) {
53                         delete (*i);
54                 }
55                 bufs.clear ();
56                 for (size_t i = 0; i < num_buffers; ++i) {
57                         bufs.push_back (new DelayBuffer (type, buffer_capacity));
58                 }
59                 _count.set (type, num_buffers);
60         }
61 }
62
63 void
64 FixedDelay::clear ()
65 {
66         for (std::vector<BufferVec>::iterator i = _buffers.begin (); i != _buffers.end (); ++i) {
67                 for (BufferVec::iterator j = (*i).begin (); j != (*i).end (); ++j) {
68                         delete *j;
69                 }
70                 (*i).clear ();
71         }
72         _buffers.clear ();
73         _count.reset ();
74 }
75
76 void
77 FixedDelay::flush()
78 {
79         for (std::vector<BufferVec>::iterator i = _buffers.begin (); i != _buffers.end (); ++i) {
80                 for (BufferVec::iterator j = (*i).begin (); j != (*i).end (); ++j) {
81                         (*j)->buf->silence (_buf_size);
82                 }
83         }
84 }
85
86 void
87 FixedDelay::configure (const ChanCount& count, samplecnt_t max_delay, bool shrink)
88 {
89         if (shrink) {
90                 if (max_delay == _max_delay && count == _count) {
91                         return;
92                 }
93                 _max_delay = max_delay;
94         } else if (max_delay <= _max_delay && count <= _count) {
95                 return;
96         } else {
97                 _max_delay = std::max (_max_delay, max_delay);
98         }
99
100         // max possible (with all engines and during export)
101         static const samplecnt_t max_block_length = 8192;
102         _buf_size = _max_delay + max_block_length;
103         for (DataType::iterator i = DataType::begin (); i != DataType::end (); ++i) {
104                 ensure_buffers (*i, count.get (*i), _buf_size);
105         }
106 }
107
108 void
109 FixedDelay::set (const ChanCount& count, samplecnt_t delay)
110 {
111         configure (count, delay, false);
112         if (_delay != delay) {
113                 flush ();
114         }
115         _delay = delay;
116 }
117
118 void
119 FixedDelay::delay (
120                 ARDOUR::DataType dt, uint32_t id,
121                 Buffer& out, const Buffer& in,
122                 pframes_t n_samples,
123                 samplecnt_t dst_offset, samplecnt_t src_offset)
124 {
125         if (_delay == 0) {
126                 out.read_from (in, n_samples, dst_offset, src_offset);
127                 return;
128         }
129
130         assert (dt < _buffers.size ());
131         assert (id < _buffers[dt].size ());
132         DelayBuffer *db = _buffers[dt][id];
133
134         if (db->pos + n_samples > _buf_size) {
135                 uint32_t w0 = _buf_size - db->pos;
136                 uint32_t w1 = db->pos + n_samples - _buf_size;
137                 db->buf->read_from (in, w0, db->pos, src_offset);
138                 db->buf->read_from (in, w1, 0, src_offset + w0);
139         } else {
140                 db->buf->read_from (in, n_samples, db->pos, src_offset);
141         }
142
143         uint32_t rp = (db->pos + _buf_size - _delay) % _buf_size;
144
145         if (rp + n_samples > _buf_size) {
146                 uint32_t r0 = _buf_size - rp;
147                 uint32_t r1 = rp + n_samples - _buf_size;
148                 out.read_from (*db->buf, r0, dst_offset, rp);
149                 out.read_from (*db->buf, r1, dst_offset + r0, 0);
150         } else {
151                 out.read_from (*db->buf, n_samples, dst_offset, rp);
152         }
153
154         db->pos = (db->pos + n_samples) % _buf_size;
155 }