add new debug bit for backend callbacks
[ardour.git] / libs / ardour / convolver.cc
1 /*
2  * Copyright (C) 2018-2019 Robin Gareus <robin@gareus.org>
3  *
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.
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 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.
17  */
18
19 #include <assert.h>
20
21 #include "pbd/error.h"
22 #include "pbd/pthread_utils.h"
23
24 #include "ardour/audioengine.h"
25 #include "ardour/audiofilesource.h"
26 #include "ardour/convolver.h"
27 #include "ardour/session.h"
28 #include "ardour/srcfilesource.h"
29 #include "ardour/source_factory.h"
30
31 #include "pbd/i18n.h"
32
33 using namespace ARDOUR::DSP;
34 using namespace ArdourZita;
35
36 using ARDOUR::Session;
37
38 Convolver::Convolver (
39                 Session& session,
40                 std::string const& path,
41                 IRChannelConfig irc,
42                 IRSettings irs)
43         : SessionHandleRef (session)
44         , _irc (irc)
45         , _ir_settings (irs)
46         , _n_samples (0)
47         , _max_size (0)
48         , _offset (0)
49         , _configured (false)
50 {
51         ARDOUR::SoundFileInfo sf_info;
52         std::string error_msg;
53
54         if (!AudioFileSource::get_soundfile_info (path, sf_info, error_msg)) {
55                 PBD::error << string_compose(_("Convolver: cannot open IR \"%1\": %2"), path, error_msg) << endmsg;
56                 throw failed_constructor ();
57         }
58
59         if (sf_info.length > 0x1000000 /*2^24*/) {
60                 PBD::error << string_compose(_("Convolver: IR \"%1\" file too long."), path) << endmsg;
61                 throw failed_constructor ();
62         }
63
64         for (unsigned int n = 0; n < sf_info.channels; ++n) {
65                 try {
66                         boost::shared_ptr<AudioFileSource> afs;
67                         afs = boost::dynamic_pointer_cast<AudioFileSource> (
68                                         SourceFactory::createExternal (DataType::AUDIO, _session,
69                                                 path, n,
70                                                 Source::Flag (ARDOUR::AudioFileSource::NoPeakFile), false));
71
72                         if (afs->sample_rate() != _session.nominal_sample_rate()) {
73                                 boost::shared_ptr<SrcFileSource> sfs (new SrcFileSource(_session, afs, ARDOUR::SrcBest));
74                                 _readables.push_back(sfs);
75                         } else {
76                                 _readables.push_back (afs);
77                         }
78                 } catch (failed_constructor& err) {
79                         PBD::error << string_compose(_("Convolver: Could not open IR \"%1\"."), path) << endmsg;
80                         throw failed_constructor ();
81                 }
82         }
83
84         if (_readables.empty ()) {
85                 PBD::error << string_compose (_("Convolver: IR \"%1\" no usable audio-channels sound."), path) << endmsg;
86                 throw failed_constructor ();
87         }
88
89         AudioEngine::instance ()->BufferSizeChanged.connect_same_thread (*this, boost::bind (&Convolver::reconfigure, this));
90
91         reconfigure ();
92 }
93
94 void
95 Convolver::reconfigure ()
96 {
97         _convproc.stop_process ();
98         _convproc.cleanup ();
99         _convproc.set_options (0);
100
101         assert (!_readables.empty ());
102
103         _offset    = 0;
104         _n_samples = _session.get_block_size ();
105         _max_size  = _readables[0]->readable_length ();
106
107         uint32_t power_of_two;
108         for (power_of_two = 1; 1U << power_of_two < _n_samples; ++power_of_two) ;
109         _n_samples = 1 << power_of_two;
110
111         int n_part = std::min ((uint32_t)Convproc::MAXPART, 4 * _n_samples);
112         int rv = _convproc.configure (
113                         /*in*/  n_inputs (),
114                         /*out*/ n_outputs (),
115                         /*max-convolution length */ _max_size,
116                         /*quantum, nominal-buffersize*/ _n_samples,
117                         /*Convproc::MINPART*/ _n_samples,
118                         /*Convproc::MAXPART*/ n_part,
119                         /*density*/ 0);
120
121         /* map channels
122          * - Mono:
123          *    always use first only
124          * - MonoToStereo:
125          *    mono-file: use 1st for M -> L, M -> R
126          *    else: use first two channels
127          * - Stereo
128          *    mono-file: use 1st for both L -> L, R -> R, no x-over
129          *    stereo-file: L -> L, R -> R  -- no L/R, R/L x-over
130          *    3chan-file: ignore 3rd channel, use as stereo-file.
131          *    4chan file:  L -> L, L -> R, R -> R, R -> L
132          */
133
134         uint32_t n_imp = n_inputs () * n_outputs ();
135         uint32_t n_chn = _readables.size ();
136
137         if (_irc == Stereo && n_chn == 3) {
138                 /* ignore 3rd channel */
139                 n_chn = 2;
140         }
141         if (_irc == Stereo && n_chn <= 2) {
142                 /* ignore x-over */
143                 n_imp = 2;
144         }
145
146 #ifndef NDEBUG
147         printf ("Convolver::reconfigure Nin=%d Nout=%d Nimp=%d Nchn=%d\n", n_inputs (), n_outputs (), n_imp, n_chn);
148 #endif
149
150         assert (n_imp <= 4);
151
152         for (uint32_t c = 0; c < n_imp && rv == 0; ++c) {
153                 int ir_c = c % n_chn;
154                 int io_o = c % n_outputs ();
155                 int io_i;
156
157                 if (n_imp == 2 && _irc == Stereo) {
158                         /*           (imp, in, out)
159                          * Stereo       (2, 2, 2)    1: L -> L, 2: R -> R
160                          */
161                         io_i = c % n_inputs ();
162                 } else {
163                         /*           (imp, in, out)
164                          * Mono         (1, 1, 1)   1: M -> M
165                          * MonoToStereo (2, 1, 2)   1: M -> L, 2: M -> R
166                          * Stereo       (4, 2, 2)   1: L -> L, 2: L -> R, 3: R -> L, 4: R -> R
167                          */
168                         io_i = (c / n_outputs ()) % n_inputs ();
169                 }
170
171
172                 boost::shared_ptr<Readable> r = _readables[ir_c];
173                 assert (r->readable_length () == _max_size);
174                 assert (r->n_channels () == 1);
175
176                 const float    chan_gain  = _ir_settings.gain * _ir_settings.channel_gain[c];
177                 const uint32_t chan_delay = _ir_settings.pre_delay + _ir_settings.channel_delay[c];
178
179 #ifndef NDEBUG
180                 printf ("Convolver map: IR-chn %d: in %d -> out %d (gain: %.1fdB delay; %d)\n", ir_c + 1, io_i + 1, io_o + 1, 20.f * log10f (chan_gain), chan_delay);
181 #endif
182
183                 uint32_t pos = 0;
184                 while (true) {
185                         float ir[8192];
186
187                         samplecnt_t to_read = std::min ((uint32_t)8192, _max_size - pos);
188                         samplecnt_t ns      = r->read (ir, pos, to_read, 0);
189
190                         if (ns == 0) {
191                                 assert (pos == _max_size);
192                                 break;
193                         }
194
195                         if (chan_gain != 1.f) {
196                                 for (samplecnt_t i = 0; i < ns; ++i) {
197                                         ir[i] *= chan_gain;
198                                 }
199                         }
200
201                         rv = _convproc.impdata_create (
202                                         /*i/o map */ io_i, io_o,
203                                         /*stride, de-interleave */ 1,
204                                         ir,
205                                         chan_delay + pos, chan_delay + pos + ns);
206
207                         if (rv != 0) {
208                                 break;
209                         }
210
211                         pos += ns;
212
213                         if (pos == _max_size) {
214                                 break;
215                         }
216                 }
217         }
218
219         if (rv == 0) {
220                 rv = _convproc.start_process (pbd_absolute_rt_priority (PBD_SCHED_FIFO, AudioEngine::instance()->client_real_time_priority() - 2), PBD_SCHED_FIFO);
221         }
222
223         assert (rv == 0); // bail out in debug builds
224
225         if (rv != 0) {
226                 _convproc.stop_process ();
227                 _convproc.cleanup ();
228                 _configured = false;
229                 return;
230         }
231
232         _configured = true;
233
234 #ifndef NDEBUG
235         _convproc.print (stdout);
236 #endif
237 }
238
239 bool
240 Convolver::ready () const
241 {
242         return _configured && _convproc.state () == Convproc::ST_PROC;
243 }
244
245 void
246 Convolver::run (float* buf, uint32_t n_samples)
247 {
248         assert (_convproc.state () == Convproc::ST_PROC);
249         assert (_irc == Mono);
250
251         uint32_t done   = 0;
252         uint32_t remain = n_samples;
253
254         while (remain > 0) {
255                 uint32_t ns = std::min (remain, _n_samples - _offset);
256
257                 float* const       in  = _convproc.inpdata (/*channel*/ 0);
258                 float const* const out = _convproc.outdata (/*channel*/ 0);
259
260                 memcpy (&in[_offset], &buf[done], sizeof (float) * ns);
261                 memcpy (&buf[done], &out[_offset], sizeof (float) * ns);
262
263                 _offset += ns;
264                 done    += ns;
265                 remain  -= ns;
266
267                 if (_offset == _n_samples) {
268                         _convproc.process (/*sync, freewheeling*/ true);
269                         _offset = 0;
270                 }
271         }
272 }
273
274 void
275 Convolver::run_stereo (float* left, float* right, uint32_t n_samples)
276 {
277         assert (_convproc.state () == Convproc::ST_PROC);
278         assert (_irc != Mono);
279
280         uint32_t done   = 0;
281         uint32_t remain = n_samples;
282
283         while (remain > 0) {
284                 uint32_t ns = std::min (remain, _n_samples - _offset);
285
286                 memcpy (&_convproc.inpdata (0)[_offset], &left[done], sizeof (float) * ns);
287                 if (_irc >= Stereo) {
288                         memcpy (&_convproc.inpdata (1)[_offset], &right[done], sizeof (float) * ns);
289                 }
290                 memcpy (&left[done],  &_convproc.outdata (0)[_offset], sizeof (float) * ns);
291                 memcpy (&right[done], &_convproc.outdata (1)[_offset], sizeof (float) * ns);
292
293                 _offset += ns;
294                 done    += ns;
295                 remain  -= ns;
296
297                 if (_offset == _n_samples) {
298                         _convproc.process (true);
299                         _offset = 0;
300                 }
301         }
302 }