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