amend ab3889ff: portaudio backend uses a vector for connections
[ardour.git] / libs / backends / alsa / alsa_slave.cc
1 /*
2  * Copyright (C) 2017 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
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19
20 #include <cmath>
21 #include <glibmm.h>
22
23 #include "pbd/compose.h"
24 #include "pbd/error.h"
25 #include "pbd/pthread_utils.h"
26
27 #include "alsa_slave.h"
28
29 #include "pbd/i18n.h" 
30
31 using namespace ARDOUR;
32
33 AlsaAudioSlave::AlsaAudioSlave (
34                         const char   *play_name,
35                         const char   *capt_name,
36                         unsigned int  master_rate,
37                         unsigned int  master_samples_per_period,
38                         unsigned int  slave_rate,
39                         unsigned int  slave_samples_per_period,
40                         unsigned int  periods_per_cycle)
41         : _pcmi (play_name, capt_name, 0, slave_rate, slave_samples_per_period, periods_per_cycle, 2, /* Alsa_pcmi::DEBUG_ALL */ 0)
42         , _run (false)
43         , _active (false)
44         , _samples_since_dll_reset (0)
45         , _ratio (1.0)
46         , _slave_speed (1.0)
47         , _draining (1)
48         , _rb_capture (4 * /* AlsaAudioBackend::_max_buffer_size */ 8192 * _pcmi.ncapt ())
49         , _rb_playback (4 * /* AlsaAudioBackend::_max_buffer_size */ 8192 * _pcmi.nplay ())
50         , _samples_per_period (master_samples_per_period)
51         , _capt_buff (0)
52         , _play_buff (0)
53         , _src_buff (0)
54 {
55         if (0 != _pcmi.state()) {
56                 return;
57         }
58
59         /* from alsa-slave to master */
60         _ratio = (double) master_rate / (double) _pcmi.fsamp();
61
62 #ifndef NDEBUG
63         fprintf (stdout, " --[[ ALSA Slave %s/%s ratio: %.4f\n", play_name, capt_name, _ratio);
64         _pcmi.printinfo ();
65         fprintf (stdout, " --]]\n");
66 #endif
67
68         _src_capt.setup (_ratio, _pcmi.ncapt (), /*quality*/ 32); // save capture to master
69         _src_play.setup (1.0 / _ratio, _pcmi.nplay (), /*quality*/ 32); // master to slave play
70
71         _src_capt.set_rrfilt (100);
72         _src_play.set_rrfilt (100);
73
74         _capt_buff = (float*) malloc (sizeof(float) * _pcmi.ncapt () * _samples_per_period);
75         _play_buff = (float*) malloc (sizeof(float) * _pcmi.nplay () * _samples_per_period);
76         _src_buff  = (float*) malloc (sizeof(float) * std::max (_pcmi.nplay (), _pcmi.ncapt ()));
77 }
78
79 AlsaAudioSlave::~AlsaAudioSlave ()
80 {
81         stop ();
82         free (_capt_buff);
83         free (_play_buff);
84         free (_src_buff);
85 }
86
87 void
88 AlsaAudioSlave::reset_resampler (ArdourZita::VResampler& src)
89 {
90         src.reset ();
91         src.inp_count = src.inpsize () - 1;
92         src.out_count = 200000;
93         src.process ();
94 }
95
96 bool
97 AlsaAudioSlave::start ()
98 {
99         if (_run) {
100                 return false;
101         }
102
103         _run = true;
104         if (pbd_realtime_pthread_create (PBD_SCHED_FIFO, -20, 100000,
105                                 &_thread, _process_thread, this))
106         {
107                 if (pthread_create (&_thread, NULL, _process_thread, this)) {
108                         _run = false;
109                         PBD::error << _("AlsaAudioBackend: failed to create slave process thread.") << endmsg;
110                         return false;
111                 }
112         }
113
114         int timeout = 5000;
115         while (!_active && --timeout > 0) { Glib::usleep (1000); }
116
117         if (timeout == 0 || !_active) {
118                 _run = false;
119                 PBD::error << _("AlsaAudioBackend: failed to start slave process thread.") << endmsg;
120                 return false;
121         }
122
123         return true;
124 }
125
126 void
127 AlsaAudioSlave::stop ()
128 {
129         void *status;
130         if (!_run) {
131                 return;
132         }
133
134         _run = false;
135         if (pthread_join (_thread, &status)) {
136                 PBD::error << _("AlsaAudioBackend: slave failed to terminate properly.") << endmsg;
137         }
138         _pcmi.pcm_stop ();
139 }
140
141 void*
142 AlsaAudioSlave::_process_thread (void* arg)
143 {
144         AlsaAudioSlave* aas = static_cast<AlsaAudioSlave*> (arg);
145         return aas->process_thread ();
146 }
147
148 void*
149 AlsaAudioSlave::process_thread ()
150 {
151          _active = true;
152
153         bool reset_dll = true;
154         int last_n_periods = 0;
155         int no_proc_errors = 0;
156         const int bailout = 2 * _pcmi.fsamp () / _pcmi.fsize ();
157
158         double dll_dt = (double) _pcmi.fsize () / (double)_pcmi.fsamp ();
159         double dll_w1 = 2 * M_PI * 0.1 * dll_dt;
160         double dll_w2 = dll_w1 * dll_w1;
161
162         const double sr_norm = 1e-6 * (double) _pcmi.fsamp () / (double) _pcmi.fsize ();
163
164         _pcmi.pcm_start ();
165
166         while (_run) {
167                 bool xrun = false;
168                 long nr = _pcmi.pcm_wait ();
169
170                 /* update DLL */
171                 uint64_t clock0 = g_get_monotonic_time();
172
173                 if (reset_dll || last_n_periods != 1) {
174                         reset_dll = false;
175                         dll_dt = 1e6 * (double) _pcmi.fsize () / (double) _pcmi.fsamp();
176                         _t0 = clock0;
177                         _t1 = clock0 + dll_dt;
178                         _samples_since_dll_reset = 0;
179                 } else {
180                         const double er = clock0 - _t1;
181                         _t0 = _t1;
182                         _t1 = _t1 + dll_w1 * er + dll_dt;
183                         dll_dt += dll_w2 * er;
184                         _samples_since_dll_reset += _pcmi.fsize ();
185                 }
186
187                 _slave_speed = (_t1 - _t0) * sr_norm; // XXX atomic
188
189                 if (_pcmi.state () > 0) {
190                         ++no_proc_errors;
191                         xrun = true;
192                 }
193
194                 if (_pcmi.state () < 0) {
195                         PBD::error << _("AlsaAudioBackend: Slave I/O error.") << endmsg;
196                         break;
197                 }
198
199                 if (no_proc_errors > bailout) {
200                         PBD::error << _("AlsaAudioBackend: Slave terminated due to continuous x-runs.") << endmsg;
201                         break;
202                 }
203
204                 const size_t spp = _pcmi.fsize ();
205                 const bool drain = g_atomic_int_get (&_draining);
206                 last_n_periods = 0;
207
208                 while (nr >= (long)spp) {
209                         no_proc_errors = 0;
210
211                         _pcmi.capt_init (spp);
212                         if (drain) {
213                                 /* do nothing */
214                         } else if (_rb_capture.write_space () >= _pcmi.ncapt () * spp) {
215 #if 0 // failsafe: write interleave sample by sample
216                                 for (uint32_t s = 0; s < spp; ++s) {
217                                         for (uint32_t c = 0; c < _pcmi.ncapt (); ++c) {
218                                                 float d;
219                                                 _pcmi.capt_chan (c, &d, 1);
220                                                 _rb_capture.write (&d, 1);
221                                         }
222                                 }
223 #else
224                                 unsigned int nchn = _pcmi.ncapt ();
225                                 PBD::RingBuffer<float>::rw_vector vec;
226                                 _rb_capture.get_write_vector (&vec);
227                                 if (vec.len[0] >= nchn * spp) {
228                                         for (uint32_t c = 0; c < nchn; ++c) {
229                                                 _pcmi.capt_chan (c, vec.buf[0] + c, spp, nchn);
230                                         }
231                                 } else {
232                                         uint32_t c;
233                                         /* first copy continuous area */
234                                         uint32_t k = vec.len[0] / nchn;
235                                         for (c = 0; c < nchn; ++c) {
236                                                 _pcmi.capt_chan (c, vec.buf[0] + c, k, nchn);
237                                         }
238
239                                         /* possible samples at end of first buffer chunk, 
240                                          * incomplete audio-sample */
241                                         uint32_t s = vec.len[0] - k * nchn;
242                                         assert (s < nchn);
243
244                                         for (c = 0; c < s; ++c) {
245                                                 _pcmi.capt_chan (c, vec.buf[0] + k * nchn + c, 1, nchn);
246                                         }
247                                         /* cont'd audio-sample at second ringbuffer chunk */
248                                         for (; c < nchn; ++c) {
249                                                 _pcmi.capt_chan (c, vec.buf[1] + c - s, spp - k, nchn);
250                                         }
251                                         /* remaining data in 2nd area */
252                                         for (c = 0; c < s; ++c) {
253                                                 _pcmi.capt_chan (c, vec.buf[1] + c + nchn - s, spp - k, nchn);
254                                         }
255                                 }
256                                 _rb_capture.increment_write_idx (spp * nchn);
257 #endif
258                         } else {
259                                 g_atomic_int_set(&_draining, 1);
260                         }
261                         _pcmi.capt_done (spp);
262
263
264                         if (drain) {
265                                 _rb_playback.increment_read_idx (_rb_playback.read_space ());
266                         }
267
268                         _pcmi.play_init (spp);
269                         if (_rb_playback.read_space () >= _pcmi.nplay () * spp) {
270 #if 0 // failsafe: read sample by sample de-interleave
271                                 for (uint32_t s = 0; s < spp; ++s) {
272                                         for (uint32_t c = 0; c < _pcmi.nplay (); ++c) {
273                                                 float d;
274                                                 _rb_playback.read (&d, 1);
275                                                 _pcmi.play_chan (c, (const float*)&d, 1); 
276                                         }
277                                 }
278 #else
279                                 unsigned int nchn = _pcmi.nplay ();
280                                 PBD::RingBuffer<float>::rw_vector vec;
281                                 _rb_playback.get_read_vector (&vec);
282                                 if (vec.len[0] >= nchn * spp) {
283                                         for (uint32_t c = 0; c < nchn; ++c) {
284                                                 _pcmi.play_chan (c, vec.buf[0] + c, spp, nchn);
285                                         }
286                                 } else {
287                                         uint32_t c;
288                                         uint32_t k = vec.len[0] / nchn;
289                                         for (c = 0; c < nchn; ++c) {
290                                                 _pcmi.play_chan (c, vec.buf[0] + c, k, nchn);
291                                         }
292
293                                         uint32_t s = vec.len[0] - k * nchn;
294                                         assert (s < nchn);
295
296                                         for (c = 0; c < s; ++c) {
297                                                 _pcmi.play_chan (c, vec.buf[0] + k * nchn + c, 1, nchn);
298                                         }
299
300                                         for (; c < nchn; ++c) {
301                                                 _pcmi.play_chan (c, vec.buf[1] + c - s, spp - k, nchn);
302                                         }
303                                         for (c = 0; c < s; ++c) {
304                                                 _pcmi.play_chan (c, vec.buf[1] + c + nchn - s, spp - k, nchn);
305                                         }
306                                 }
307                                 _rb_playback.increment_read_idx (spp * nchn);
308 #endif
309                         } else {
310                                 if (!drain) {
311                                         printf ("Slave Process: Playback Buffer Underflow, have %u want %lu\n", _rb_playback.read_space (), _pcmi.nplay () * spp); // XXX DEBUG 
312                                         _play_latency += spp * _ratio;
313                                         update_latencies (_play_latency, _capt_latency);
314                                 }
315                                 /* silence outputs */
316                                 for (uint32_t c = 0; c < _pcmi.nplay (); ++c) {
317                                         _pcmi.clear_chan (c, spp);
318                                 }
319                         }
320                         _pcmi.play_done (spp);
321
322                         nr -= spp;
323                         ++last_n_periods;
324                 }
325
326                 if (xrun && (_pcmi.capt_xrun() > 0 || _pcmi.play_xrun() > 0)) {
327                         reset_dll = true;
328                         _samples_since_dll_reset = 0;
329                         g_atomic_int_set(&_draining, 1);
330                 }
331         }
332
333         _pcmi.pcm_stop ();
334         _active = false;
335
336         if (_run) {
337                 Halted (); /* Emit Signal */
338         }
339         return 0;
340 }
341
342 void
343 AlsaAudioSlave::cycle_start (double tme, double mst_speed, bool drain)
344 {
345         //printf ("SRC %f / %f = %f\n", mst_speed, _slave_speed, mst_speed / _slave_speed);
346         //printf ("DRIFT (mst) %11.1f - (slv) %11.1f = %.1f us = %.1f spl\n", tme, _t0, tme - _t0, (tme - _t0) * _pcmi.fsamp () * 1e-6);
347         //printf ("Slave capt: %u play: %u\n", _rb_capture.read_space (), _rb_playback.read_space ());
348
349         // TODO LPF filter ratios, atomic _slave_speed
350         const double slave_speed = _slave_speed;
351
352         _src_capt.set_rratio (mst_speed / slave_speed);
353         _src_play.set_rratio (slave_speed / mst_speed);
354
355         memset (_capt_buff, 0, sizeof(float) * _pcmi.ncapt () * _samples_per_period);
356
357         if (drain) {
358                 g_atomic_int_set(&_draining, 1);
359                 return;
360         }
361
362         if (g_atomic_int_get (&_draining)) {
363                 _rb_capture.increment_read_idx (_rb_capture.read_space());
364                 return;
365         }
366
367         /* resample slave capture data from ringbuffer */
368         unsigned int nchn = _pcmi.ncapt ();
369         _src_capt.out_count = _samples_per_period;
370         _src_capt.out_data  = _capt_buff;
371
372         /* estimate required samples */
373         const double rratio = _ratio * mst_speed / slave_speed;
374         if (_rb_capture.read_space() < ceil (nchn * _samples_per_period / rratio)) {
375                 printf ("--- UNDERFLOW ---  have %u  want %.1f\n", _rb_capture.read_space(), ceil (nchn * _samples_per_period / rratio)); // XXX DEBUG
376                 _capt_latency += _samples_per_period;
377                 update_latencies (_play_latency, _capt_latency);
378                 return;
379         }
380
381         bool underflow = false;
382         while (_src_capt.out_count && _active) {
383                 if (_rb_capture.read_space() < nchn) {
384                         underflow = true;
385                         break;
386                 }
387                 unsigned int n;
388                 PBD::RingBuffer<float>::rw_vector vec;
389                 _rb_capture.get_read_vector (&vec);
390                 if (vec.len[0] < nchn) {
391                         _rb_capture.read (_src_buff, nchn);
392                         _src_capt.inp_count = 1;
393                         _src_capt.inp_data  = _src_buff;
394                         _src_capt.process ();
395                 } else {
396                         _src_capt.inp_count = n = vec.len[0] / nchn;
397                         _src_capt.inp_data  = vec.buf[0];
398                         _src_capt.process ();
399                         n -= _src_capt.inp_count;
400                         _rb_capture.increment_read_idx (n * _pcmi.ncapt ());
401                 }
402         }
403
404         if (underflow) {
405                 std::cerr << "ALSA Slave: Capture Ringbuffer Underflow\n"; // XXX
406                 g_atomic_int_set(&_draining, 1);
407         }
408
409         if (!_active || underflow) {
410                 memset (_capt_buff, 0, sizeof(float) * _pcmi.ncapt () * _samples_per_period);
411         }
412
413         memset (_play_buff, 0, sizeof(float) * _pcmi.nplay () * _samples_per_period);
414 }
415
416 void
417 AlsaAudioSlave::cycle_end ()
418 {
419         bool drain_done = false;
420         bool overflow = false;
421
422         if (g_atomic_int_get (&_draining)) {
423                 if (_rb_capture.read_space() == 0 && _rb_playback.read_space() == 0 && _samples_since_dll_reset > _pcmi.fsamp ()) {
424                         reset_resampler (_src_capt);
425                         reset_resampler (_src_play);
426                         memset (_src_buff, 0, sizeof (float) * _pcmi.nplay());
427                         /* prefill ringbuffers, resampler variance */
428                         for (int i = 0; i < 16; ++i) {
429                                 _rb_playback.write (_src_buff, _pcmi.nplay());
430                         }
431                         memset (_src_buff, 0, sizeof (float) * _pcmi.ncapt());
432                         // It's safe to write here, process-thread NO-OPs while draining.
433                         for (int i = 0; i < 16; ++i) {
434                                 _rb_capture.write (_src_buff, _pcmi.ncapt());
435                         }
436                         _capt_latency = 16;
437                         _play_latency = 16 + _ratio * _pcmi.fsize () * (_pcmi.play_nfrag () - 1);
438                         update_latencies (_play_latency, _capt_latency);
439                         drain_done = true;
440                 } else {
441                         return;
442                 }
443         }
444
445         /* resample collected playback data into ringbuffer */
446         unsigned int nchn = _pcmi.nplay ();
447         _src_play.inp_count = _samples_per_period;
448         _src_play.inp_data  = _play_buff;
449
450         while (_src_play.inp_count && _active) {
451                 unsigned int n;
452                 PBD::RingBuffer<float>::rw_vector vec;
453                 _rb_playback.get_write_vector (&vec);
454                 if (vec.len[0] < nchn) {
455                         _src_play.out_count = 1;
456                         _src_play.out_data  = _src_buff;
457                         _src_play.process ();
458                         if (_rb_playback.write_space() < nchn) {
459                                 overflow = true;
460                                 break;
461                         } else if (_src_play.out_count == 0) {
462                                 _rb_playback.write (_src_buff, nchn);
463                         }
464                 } else {
465                         _src_play.out_count = n = vec.len[0] / nchn;
466                         _src_play.out_data  = vec.buf[0];
467                         _src_play.process ();
468                         n -= _src_play.out_count;
469                         if (_rb_playback.write_space() < n * nchn) {
470                                 overflow = true;
471                                 break;
472                         }
473                         _rb_playback.increment_write_idx (n * nchn);
474                 }
475         }
476
477         if (overflow) {
478                 std::cerr << "ALSA Slave: Playback Ringbuffer Overflow\n"; // XXX
479                 g_atomic_int_set(&_draining, 1);
480                 return;
481         }
482         if (drain_done) {
483                 g_atomic_int_set(&_draining, 0);
484         }
485 }
486
487 void
488 AlsaAudioSlave::freewheel (bool onoff)
489 {
490         if (onoff) {
491                 g_atomic_int_set(&_draining, 1);
492         }
493 }
494
495 /* master read slave's capture.
496  * resampled at cycle_start, before master can call this
497  */
498 uint32_t
499 AlsaAudioSlave::capt_chan (uint32_t chn, float* dst, uint32_t n_samples)
500 {
501         uint32_t nchn = _pcmi.ncapt ();
502         assert (chn < nchn && n_samples == _samples_per_period);
503         float* src = &_capt_buff[chn];
504         for (uint32_t s = 0; s < n_samples; ++s) {
505                 dst[s] = src[s * nchn];
506         }
507         return n_samples;
508 }
509
510 /* write from master to slave output,
511  * resampled at cycle_end, after master called this.
512  */
513 uint32_t
514 AlsaAudioSlave::play_chan (uint32_t chn, float* src, uint32_t n_samples)
515 {
516         uint32_t nchn = _pcmi.nplay ();
517         assert (chn < nchn && n_samples == _samples_per_period);
518         float* dst = &_play_buff[chn];
519         for (uint32_t s = 0; s < n_samples; ++s) {
520                 dst[s * nchn] = src[s];
521         }
522         return n_samples;
523 }