| @@ -4,6 +4,7 @@ | |||
| #include <math.hpp> | |||
| #include <system.hpp> | |||
| #include <map> | |||
| #include <algorithm> | |||
| #pragma GCC diagnostic push | |||
| #ifndef __clang__ | |||
| @@ -23,7 +24,7 @@ struct RtAudioDevice : audio::Device { | |||
| RtAudio::StreamParameters inputParameters; | |||
| RtAudio::StreamParameters outputParameters; | |||
| RtAudio::StreamOptions options; | |||
| int blockSize = 256; | |||
| int blockSize = 0; | |||
| int sampleRate = 44100; | |||
| RtAudioDevice(RtAudio::Api api, int deviceId) { | |||
| @@ -31,6 +32,8 @@ struct RtAudioDevice : audio::Device { | |||
| if (!rtAudio) { | |||
| throw Exception(string::f("Failed to create RtAudio driver %d", api)); | |||
| } | |||
| rtAudio->showWarnings(false); | |||
| try { | |||
| deviceInfo = rtAudio->getDeviceInfo(deviceId); | |||
| } | |||
| @@ -70,17 +73,24 @@ struct RtAudioDevice : audio::Device { | |||
| options.streamName = "VCV Rack"; | |||
| int closestSampleRate = deviceInfo.preferredSampleRate; | |||
| for (int sr : deviceInfo.sampleRates) { | |||
| if (std::abs(sr - sampleRate) < std::abs(closestSampleRate - sampleRate)) { | |||
| closestSampleRate = sr; | |||
| if (sampleRate > 0) { | |||
| // Find the closest sample rate to the requested one. | |||
| for (int sr : deviceInfo.sampleRates) { | |||
| if (std::abs(sr - sampleRate) < std::abs(closestSampleRate - sampleRate)) { | |||
| closestSampleRate = sr; | |||
| } | |||
| } | |||
| } | |||
| if (blockSize <= 0) { | |||
| blockSize = 256; | |||
| } | |||
| INFO("Opening audio RtAudio device %d with %d in %d out", deviceId, inputParameters.nChannels, outputParameters.nChannels); | |||
| try { | |||
| rtAudio->openStream( | |||
| outputParameters.nChannels == 0 ? NULL : &outputParameters, | |||
| inputParameters.nChannels == 0 ? NULL : &inputParameters, | |||
| outputParameters.nChannels > 0 ? &outputParameters : NULL, | |||
| inputParameters.nChannels > 0 ? &inputParameters : NULL, | |||
| RTAUDIO_FLOAT32, closestSampleRate, (unsigned int*) &blockSize, | |||
| &rtAudioCallback, this, &options, NULL); | |||
| } | |||
| @@ -270,9 +280,24 @@ struct RtAudioDriver : audio::Driver { | |||
| void rtaudioInit() { | |||
| std::vector<RtAudio::Api> apis; | |||
| RtAudio::getCompiledApi(apis); | |||
| for (RtAudio::Api api : apis) { | |||
| RtAudioDriver* driver = new RtAudioDriver(api); | |||
| audio::addDriver((int) api, driver); | |||
| // I don't like the order returned by getCompiledApi(), so reorder it here. | |||
| std::vector<RtAudio::Api> orderedApis = { | |||
| RtAudio::LINUX_ALSA, | |||
| RtAudio::UNIX_JACK, | |||
| RtAudio::LINUX_PULSE, | |||
| RtAudio::LINUX_OSS, | |||
| RtAudio::WINDOWS_WASAPI, | |||
| RtAudio::WINDOWS_ASIO, | |||
| RtAudio::WINDOWS_DS, | |||
| RtAudio::MACOSX_CORE, | |||
| }; | |||
| for (RtAudio::Api api : orderedApis) { | |||
| auto it = std::find(apis.begin(), apis.end(), api); | |||
| if (it != apis.end()) { | |||
| RtAudioDriver* driver = new RtAudioDriver(api); | |||
| audio::addDriver((int) api, driver); | |||
| } | |||
| } | |||
| } | |||