30a0a25eb49c5a76a4b8f9252e152445e44792e7
[ardour.git] / libs / backends / portaudio / portaudio_io.cc
1 /*
2  * Copyright (C) 2015 Robin Gareus <robin@gareus.org>
3  * Copyright (C) 2015 Tim Mayberry <mojofunk@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <assert.h>
24 #include <glibmm.h>
25 #include "portaudio_io.h"
26
27 #include "pbd/compose.h"
28
29 #include "debug.h"
30
31 #define INTERLEAVED_INPUT
32 #define INTERLEAVED_OUTPUT
33
34 using namespace ARDOUR;
35
36 PortAudioIO::PortAudioIO ()
37         : _state (-1)
38         , _initialized (false)
39         , _capture_channels (0)
40         , _playback_channels (0)
41         , _stream (0)
42         , _input_buffer (0)
43         , _output_buffer (0)
44         , _cur_sample_rate (0)
45         , _cur_input_latency (0)
46         , _cur_output_latency (0)
47         , _host_api_index(-1)
48 {
49 }
50
51 PortAudioIO::~PortAudioIO ()
52 {
53         if (_state == 0) {
54                 pcm_stop();
55         }
56         if (_initialized) {
57                 Pa_Terminate();
58         }
59
60         clear_device_lists ();
61
62         free (_input_buffer); _input_buffer = NULL;
63         free (_output_buffer); _output_buffer = NULL;
64 }
65
66
67 int
68 PortAudioIO::available_sample_rates(int device_id, std::vector<float>& sampleRates)
69 {
70         static const float ardourRates[] = { 8000.0, 22050.0, 24000.0, 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0};
71
72         if (!initialize_pa()) return -1;
73
74         // TODO use  separate int device_input, int device_output ?!
75         if (device_id == -1) {
76                 device_id = get_default_input_device ();
77         }
78
79         DEBUG_AUDIO (
80             string_compose ("Querying Samplerates for device %1\n", device_id));
81
82         sampleRates.clear();
83         const PaDeviceInfo* nfo = Pa_GetDeviceInfo(device_id);
84
85         if (nfo) {
86                 PaStreamParameters inputParam;
87                 PaStreamParameters outputParam;
88
89                 inputParam.device = device_id;
90                 inputParam.channelCount = nfo->maxInputChannels;
91                 inputParam.sampleFormat = paFloat32;
92                 inputParam.suggestedLatency = 0;
93                 inputParam.hostApiSpecificStreamInfo = 0;
94
95                 outputParam.device = device_id;
96                 outputParam.channelCount = nfo->maxOutputChannels;
97                 outputParam.sampleFormat = paFloat32;
98                 outputParam.suggestedLatency = 0;
99                 outputParam.hostApiSpecificStreamInfo = 0;
100
101                 for (uint32_t i = 0; i < sizeof(ardourRates)/sizeof(float); ++i) {
102                         if (paFormatIsSupported == Pa_IsFormatSupported(
103                                                 nfo->maxInputChannels > 0 ? &inputParam : NULL,
104                                                 nfo->maxOutputChannels > 0 ? &outputParam : NULL,
105                                                 ardourRates[i])) {
106                                 sampleRates.push_back (ardourRates[i]);
107                         }
108                 }
109         }
110
111         if (sampleRates.empty()) {
112                 // fill in something..
113                 sampleRates.push_back (44100.0);
114                 sampleRates.push_back (48000.0);
115         }
116
117         return 0;
118 }
119
120 int
121 PortAudioIO::available_buffer_sizes(int device_id, std::vector<uint32_t>& bufferSizes)
122 {
123         // TODO
124         static const uint32_t ardourSizes[] = { 64, 128, 256, 512, 1024, 2048, 4096 };
125         for(uint32_t i = 0; i < sizeof(ardourSizes)/sizeof(uint32_t); ++i) {
126                 bufferSizes.push_back (ardourSizes[i]);
127         }
128         return 0;
129 }
130
131 void
132 PortAudioIO::input_device_list(std::map<int, std::string> &devices) const
133 {
134         for (std::map<int, paDevice*>::const_iterator i = _input_devices.begin ();
135              i != _input_devices.end ();
136              ++i) {
137                 devices.insert (std::pair<int, std::string>(i->first, Glib::locale_to_utf8(i->second->name)));
138         }
139 }
140
141 void
142 PortAudioIO::output_device_list(std::map<int, std::string> &devices) const
143 {
144         for (std::map<int, paDevice*>::const_iterator i = _output_devices.begin ();
145              i != _output_devices.end ();
146              ++i) {
147                 devices.insert (std::pair<int, std::string>(i->first, Glib::locale_to_utf8(i->second->name)));
148         }
149 }
150
151 bool
152 PortAudioIO::initialize_pa ()
153 {
154         PaError err = paNoError;
155
156         if (!_initialized) {
157                 err = Pa_Initialize();
158                 if (err != paNoError) {
159                         return false;
160                 }
161                 _initialized = true;
162         }
163
164         return true;
165 }
166
167 void
168 PortAudioIO::host_api_list (std::vector<std::string>& api_list)
169 {
170         if (!initialize_pa()) return;
171
172         PaHostApiIndex count = Pa_GetHostApiCount();
173
174         if (count < 0) return;
175
176         for (int i = 0; i < count; ++i) {
177                 const PaHostApiInfo* info = Pa_GetHostApiInfo (i);
178                 if (info->name != NULL) { // possible?
179                         api_list.push_back (info->name);
180                 }
181         }
182 }
183
184 bool
185 PortAudioIO::set_host_api (const std::string& host_api_name)
186 {
187         PaHostApiIndex new_index = get_host_api_index_from_name (host_api_name);
188
189         if (new_index < 0) {
190                 DEBUG_AUDIO ("Portaudio: Error setting host API\n");
191                 return false;
192         }
193         _host_api_index = new_index;
194         _host_api_name = host_api_name;
195         return true;
196 }
197
198 PaHostApiIndex
199 PortAudioIO::get_host_api_index_from_name (const std::string& name)
200 {
201         if (!initialize_pa()) return -1;
202
203         PaHostApiIndex count = Pa_GetHostApiCount();
204
205         if (count < 0) {
206                 DEBUG_AUDIO ("Host API count < 0\n");
207                 return -1;
208         }
209
210         for (int i = 0; i < count; ++i) {
211                 const PaHostApiInfo* info = Pa_GetHostApiInfo (i);
212                 if (info->name != NULL) { // possible?
213                         if (name == info->name) return i;
214                 }
215         }
216         DEBUG_AUDIO (string_compose ("Unable to get host API from name: %1\n", name));
217
218         return -1;
219 }
220
221 PaDeviceIndex
222 PortAudioIO::get_default_input_device ()
223 {
224         const PaHostApiInfo* info = Pa_GetHostApiInfo (_host_api_index);
225         if (info == NULL) return -1;
226         return info->defaultInputDevice;
227 }
228
229 PaDeviceIndex
230 PortAudioIO::get_default_output_device ()
231 {
232         const PaHostApiInfo* info = Pa_GetHostApiInfo (_host_api_index);
233         if (info == NULL) return -1;
234         return info->defaultOutputDevice;
235 }
236
237 void
238 PortAudioIO::clear_device_lists ()
239 {
240         for (std::map<int, paDevice*>::const_iterator i = _input_devices.begin (); i != _input_devices.end(); ++i) {
241                 delete i->second;
242         }
243         _input_devices.clear();
244
245         for (std::map<int, paDevice*>::const_iterator i = _output_devices.begin (); i != _output_devices.end(); ++i) {
246                 delete i->second;
247         }
248         _output_devices.clear();
249 }
250
251 void
252 PortAudioIO::add_default_devices ()
253 {
254         const PaHostApiInfo* info = Pa_GetHostApiInfo (_host_api_index);
255         if (info == NULL) return;
256
257         const PaDeviceInfo* nfo_i = Pa_GetDeviceInfo(get_default_input_device());
258         const PaDeviceInfo* nfo_o = Pa_GetDeviceInfo(get_default_output_device());
259         if (nfo_i && nfo_o) {
260                 _input_devices.insert (std::pair<int, paDevice*> (-1,
261                                         new paDevice("Default",
262                                                 nfo_i->maxInputChannels,
263                                                 nfo_o->maxOutputChannels
264                                                 )));
265                 _output_devices.insert (std::pair<int, paDevice*> (-1,
266                                         new paDevice("Default",
267                                                 nfo_i->maxInputChannels,
268                                                 nfo_o->maxOutputChannels
269                                                 )));
270         }
271 }
272
273 void
274 PortAudioIO::add_devices ()
275 {
276         const PaHostApiInfo* info = Pa_GetHostApiInfo (_host_api_index);
277         if (info == NULL) return;
278
279         int n_devices = Pa_GetDeviceCount();
280
281         DEBUG_AUDIO (string_compose ("PortAudio found %1 devices\n", n_devices));
282
283         for (int i = 0 ; i < n_devices; ++i) {
284                 const PaDeviceInfo* nfo = Pa_GetDeviceInfo(i);
285
286                 if (!nfo) continue;
287                 if (nfo->hostApi != _host_api_index) continue;
288
289                 DEBUG_AUDIO (string_compose (" (%1) '%2' '%3' in: %4 (lat: %5 .. %6) out: %7 "
290                                              "(lat: %8 .. %9) sr:%10\n",
291                                              i,
292                                              info->name,
293                                              nfo->name,
294                                              nfo->maxInputChannels,
295                                              nfo->defaultLowInputLatency * 1e3,
296                                              nfo->defaultHighInputLatency * 1e3,
297                                              nfo->maxOutputChannels,
298                                              nfo->defaultLowOutputLatency * 1e3,
299                                              nfo->defaultHighOutputLatency * 1e3,
300                                              nfo->defaultSampleRate));
301
302                 if ( nfo->maxInputChannels == 0 && nfo->maxOutputChannels == 0) {
303                         continue;
304                 }
305
306                 if (nfo->maxInputChannels > 0) {
307                         _input_devices.insert (std::pair<int, paDevice*> (i, new paDevice(
308                                                         nfo->name,
309                                                         nfo->maxInputChannels,
310                                                         nfo->maxOutputChannels
311                                                         )));
312                 }
313                 if (nfo->maxOutputChannels > 0) {
314                         _output_devices.insert (std::pair<int, paDevice*> (i, new paDevice(
315                                                         nfo->name,
316                                                         nfo->maxInputChannels,
317                                                         nfo->maxOutputChannels
318                                                         )));
319                 }
320         }
321 }
322
323 void
324 PortAudioIO::discover()
325 {
326         DEBUG_AUDIO ("PortAudio: discover\n");
327         if (!initialize_pa()) return;
328
329         clear_device_lists ();
330         add_default_devices ();
331         add_devices ();
332 }
333
334 void
335 PortAudioIO::pcm_stop ()
336 {
337         if (_stream) {
338                 Pa_CloseStream (_stream);
339         }
340         _stream = NULL;
341
342         _capture_channels = 0;
343         _playback_channels = 0;
344         _cur_sample_rate = 0;
345         _cur_input_latency = 0;
346         _cur_output_latency = 0;
347
348         free (_input_buffer); _input_buffer = NULL;
349         free (_output_buffer); _output_buffer = NULL;
350         _state = -1;
351 }
352
353 int
354 PortAudioIO::pcm_start()
355 {
356         PaError err = Pa_StartStream (_stream);
357
358         if (err != paNoError) {
359                 _state = -1;
360                 return -1;
361         }
362         return 0;
363 }
364
365 #ifdef __APPLE__
366 static uint32_t lower_power_of_two (uint32_t v) {
367         v--;
368         v |= v >> 1;
369         v |= v >> 2;
370         v |= v >> 4;
371         v |= v >> 8;
372         v |= v >> 16;
373         v++;
374         return v >> 1;
375 }
376 #endif
377
378 int
379 PortAudioIO::pcm_setup (
380                 int device_input, int device_output,
381                 double sample_rate, uint32_t samples_per_period)
382 {
383         _state = -2;
384
385         PaError err = paNoError;
386         const PaDeviceInfo *nfo_in;
387         const PaDeviceInfo *nfo_out;
388         const PaStreamInfo *nfo_s;
389                 
390         if (!initialize_pa()) {
391                 DEBUG_AUDIO ("PortAudio Initialization Failed\n");
392                 goto error;
393         }
394
395         if (device_input == -1) {
396                 device_input = get_default_input_device ();
397         }
398         if (device_output == -1) {
399                 device_output = get_default_output_device ();
400         }
401
402         _capture_channels = 0;
403         _playback_channels = 0;
404         _cur_sample_rate = 0;
405         _cur_input_latency = 0;
406         _cur_output_latency = 0;
407
408         DEBUG_AUDIO (string_compose (
409             "PortAudio Device IDs: i:%1 o:%2\n", device_input, device_output));
410
411         nfo_in = Pa_GetDeviceInfo(device_input);
412         nfo_out = Pa_GetDeviceInfo(device_output);
413
414         if (!nfo_in && ! nfo_out) {
415                 DEBUG_AUDIO ("PortAudio Cannot Query Device Info\n");
416                 goto error;
417         }
418
419         if (nfo_in) {
420                 _capture_channels = nfo_in->maxInputChannels;
421         }
422         if (nfo_out) {
423                 _playback_channels = nfo_out->maxOutputChannels;
424         }
425
426         if(_capture_channels == 0 && _playback_channels == 0) {
427                 DEBUG_AUDIO ("PortAudio no input or output channels.\n");
428                 goto error;
429         }
430
431 #ifdef __APPLE__
432         // pa_mac_core_blocking.c pa_stable_v19_20140130
433         // BUG: ringbuffer alloc requires power-of-two chn count.
434         if ((_capture_channels & (_capture_channels - 1)) != 0) {
435                 DEBUG_AUDIO (
436                     "Adjusted capture channels to power of two (portaudio rb bug)\n");
437                 _capture_channels = lower_power_of_two (_capture_channels);
438         }
439
440         if ((_playback_channels & (_playback_channels - 1)) != 0) {
441                 DEBUG_AUDIO (
442                     "Adjusted capture channels to power of two (portaudio rb bug)\n");
443                 _playback_channels = lower_power_of_two (_playback_channels);
444         }
445 #endif
446
447         DEBUG_AUDIO (string_compose ("PortAudio Channels: in:%1 out:%2\n",
448                                      _capture_channels,
449                                      _playback_channels));
450
451         PaStreamParameters inputParam;
452         PaStreamParameters outputParam;
453
454         if (nfo_in) {
455                 inputParam.device = device_input;
456                 inputParam.channelCount = _capture_channels;
457 #ifdef INTERLEAVED_INPUT
458                 inputParam.sampleFormat = paFloat32;
459 #else
460                 inputParam.sampleFormat = paFloat32 | paNonInterleaved;
461 #endif
462                 inputParam.suggestedLatency = nfo_in->defaultLowInputLatency;
463                 inputParam.hostApiSpecificStreamInfo = NULL;
464         }
465
466         if (nfo_out) {
467                 outputParam.device = device_output;
468                 outputParam.channelCount = _playback_channels;
469 #ifdef INTERLEAVED_OUTPUT
470                 outputParam.sampleFormat = paFloat32;
471 #else
472                 outputParam.sampleFormat = paFloat32 | paNonInterleaved;
473 #endif
474                 outputParam.suggestedLatency = nfo_out->defaultLowOutputLatency;
475                 outputParam.hostApiSpecificStreamInfo = NULL;
476         }
477
478         // XXX re-consider using callback API, testing needed.
479         err = Pa_OpenStream (
480                         &_stream,
481                         _capture_channels > 0 ? &inputParam: NULL,
482                         _playback_channels > 0 ? &outputParam: NULL,
483                         sample_rate,
484                         samples_per_period,
485                         paClipOff | paDitherOff,
486                         NULL, NULL);
487
488         if (err != paNoError) {
489                 DEBUG_AUDIO ("PortAudio failed to start stream.\n");
490                 goto error;
491         }
492
493         nfo_s = Pa_GetStreamInfo (_stream);
494         if (!nfo_s) {
495                 DEBUG_AUDIO ("PortAudio failed to query stream information.\n");
496                 pcm_stop();
497                 goto error;
498         }
499
500         _cur_sample_rate = nfo_s->sampleRate;
501         _cur_input_latency = nfo_s->inputLatency * _cur_sample_rate;
502         _cur_output_latency = nfo_s->outputLatency * _cur_sample_rate;
503
504         DEBUG_AUDIO (string_compose ("PA Sample Rate %1 SPS\n", _cur_sample_rate));
505
506         DEBUG_AUDIO (string_compose ("PA Input Latency %1ms, %2 spl\n",
507                                      1e3 * nfo_s->inputLatency,
508                                      _cur_input_latency));
509
510         DEBUG_AUDIO (string_compose ("PA Output Latency %1ms, %2 spl\n",
511                                      1e3 * nfo_s->outputLatency,
512                                      _cur_output_latency));
513
514         _state = 0;
515
516         if (_capture_channels > 0) {
517                 _input_buffer = (float*) malloc (samples_per_period * _capture_channels * sizeof(float));
518                 if (!_input_buffer) {
519                         DEBUG_AUDIO ("PortAudio failed to allocate input buffer.\n");
520                         pcm_stop();
521                         goto error;
522                 }
523         }
524
525         if (_playback_channels > 0) {
526                 _output_buffer = (float*) calloc (samples_per_period * _playback_channels, sizeof(float));
527                 if (!_output_buffer) {
528                         DEBUG_AUDIO ("PortAudio failed to allocate output buffer.\n");
529                         pcm_stop();
530                         goto error;
531                 }
532         }
533
534         return 0;
535
536 error:
537         _capture_channels = 0;
538         _playback_channels = 0;
539         free (_input_buffer); _input_buffer = NULL;
540         free (_output_buffer); _output_buffer = NULL;
541         return -1;
542 }
543
544 int
545 PortAudioIO::next_cycle (uint32_t n_samples)
546 {
547         bool xrun = false;
548         PaError err;
549         err = Pa_IsStreamActive (_stream);
550         if (err != 1) {
551                 //   0: inactive / aborted
552                 // < 0: error
553                 return -1;
554         }
555
556         // TODO, check drift..  process part with larger capacity first.
557         // Pa_GetStreamReadAvailable(_stream) < Pa_GetStreamWriteAvailable(_stream)
558
559         if (_playback_channels > 0) {
560                 err = Pa_WriteStream (_stream, _output_buffer, n_samples);
561                 if (err) xrun = true;
562         }
563
564         if (_capture_channels > 0) {
565                 err = Pa_ReadStream (_stream, _input_buffer, n_samples);
566                 if (err) {
567                         memset (_input_buffer, 0, sizeof(float) * n_samples * _capture_channels);
568                         xrun = true;
569                 }
570         }
571
572
573         return xrun ? 1 : 0;
574 }
575
576
577 #ifdef INTERLEAVED_INPUT
578
579 int
580 PortAudioIO::get_capture_channel (uint32_t chn, float *input, uint32_t n_samples)
581 {
582         assert(chn < _capture_channels);
583         const uint32_t stride = _capture_channels;
584         float *ptr = _input_buffer + chn;
585         while (n_samples-- > 0) {
586                 *input++ = *ptr;
587                 ptr += stride;
588         }
589         return 0;
590 }
591
592 #else
593
594 int
595 PortAudioIO::get_capture_channel (uint32_t chn, float *input, uint32_t n_samples)
596 {
597         assert(chn < _capture_channels);
598         memcpy((void*)input, &(_input_buffer[chn * n_samples]), n_samples * sizeof(float));
599         return 0;
600 }
601
602 #endif
603
604
605 #ifdef INTERLEAVED_OUTPUT
606
607 int
608 PortAudioIO::set_playback_channel (uint32_t chn, const float *output, uint32_t n_samples)
609 {
610         assert(chn < _playback_channels);
611         const uint32_t stride = _playback_channels;
612         float *ptr = _output_buffer + chn;
613         while (n_samples-- > 0) {
614                 *ptr = *output++;
615                 ptr += stride;
616         }
617         return 0;
618 }
619
620 #else
621
622 int
623 PortAudioIO::set_playback_channel (uint32_t chn, const float *output, uint32_t n_samples)
624 {
625         assert(chn < _playback_channels);
626         memcpy((void*)&(_output_buffer[chn * n_samples]), (void*)output, n_samples * sizeof(float));
627         return 0;
628 }
629
630 #endif