commit ceaea6080f6a704a0c992c766e28d7cdb4901f11
parent f022c766bd315b5bb22800b9ab78a4e1ec991edc
Author: falkTX <falktx@falktx.com>
Date: Sun, 10 Jul 2022 17:59:48 +0100
Rework SDL bridge to support audio input
Signed-off-by: falkTX <falktx@falktx.com>
Diffstat:
2 files changed, 145 insertions(+), 39 deletions(-)
diff --git a/distrho/src/jackbridge/JackBridge.cpp b/distrho/src/jackbridge/JackBridge.cpp
@@ -36,7 +36,7 @@
#include "../../extra/LibraryUtils.hpp"
// in case JACK fails, we fallback to RtAudio or SDL native API
-#if defined(DISTRHO_OS_WASM)
+#if defined(DISTRHO_OS_HAIKU) || defined(DISTRHO_OS_WASM)
# include "SDLBridge.hpp"
#elif defined(DISTRHO_PROPER_CPP11_SUPPORT) && !defined(DPF_JACK_STANDALONE_SKIP_RTAUDIO_FALLBACK)
# include "RtAudioBridge.hpp"
diff --git a/distrho/src/jackbridge/SDLBridge.hpp b/distrho/src/jackbridge/SDLBridge.hpp
@@ -23,7 +23,12 @@
#include <SDL.h>
struct SDLBridge {
- SDL_AudioDeviceID deviceId = 0;
+#if DISTRHO_PLUGIN_NUM_INPUTS > 0
+ SDL_AudioDeviceID captureDeviceId = 0;
+#endif
+#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
+ SDL_AudioDeviceID playbackDeviceId = 0;
+#endif
// SDL information
uint bufferSize = 0;
@@ -61,37 +66,97 @@ struct SDLBridge {
bool open(const char* const clientName)
{
- SDL_AudioSpec requested, received;
+ #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
+ SDL_InitSubSystem(SDL_INIT_AUDIO);
+
+ SDL_AudioSpec requested;
std::memset(&requested, 0, sizeof(requested));
requested.format = AUDIO_F32SYS;
- requested.channels = DISTRHO_PLUGIN_NUM_OUTPUTS;
requested.freq = 48000;
requested.samples = 512;
- requested.callback = SDLCallback;
requested.userdata = this;
SDL_SetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME, clientName);
- // SDL_SetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME, );
SDL_SetHint(SDL_HINT_AUDIO_RESAMPLING_MODE, "2");
+ #endif
+
+ #if DISTRHO_PLUGIN_NUM_INPUTS > 0
+ SDL_SetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME, "Capure");
+ requested.channels = DISTRHO_PLUGIN_NUM_INPUTS;
+ requested.callback = AudioInputCallback;
- /*
- deviceId = SDL_OpenAudioDevice("PulseAudio", 0,
- &requested, &received,
- SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
- */
- deviceId = SDL_OpenAudio(&requested, &received) == 0 ? 1 : 0;
- DISTRHO_SAFE_ASSERT_RETURN(deviceId != 0, false);
+ SDL_AudioSpec receivedCapture;
+ captureDeviceId = SDL_OpenAudioDevice(nullptr, 1, &requested, &receivedCapture,
+ SDL_AUDIO_ALLOW_FREQUENCY_CHANGE|SDL_AUDIO_ALLOW_SAMPLES_CHANGE);
+ if (captureDeviceId == 0)
+ {
+ d_stderr2("Failed to open SDL playback device, error was: %s", SDL_GetError());
+ return false;
+ }
+
+ if (receivedCapture.channels != DISTRHO_PLUGIN_NUM_INPUTS)
+ {
+ SDL_CloseAudioDevice(captureDeviceId);
+ captureDeviceId = 0;
+ d_stderr2("Invalid or missing audio input channels");
+ return false;
+ }
+ #endif
+
+ #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
+ SDL_AudioSpec receivedPlayback;
+ SDL_SetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME, "Playback");
+ requested.channels = DISTRHO_PLUGIN_NUM_OUTPUTS;
+ requested.callback = AudioOutputCallback;
- if (received.channels != DISTRHO_PLUGIN_NUM_OUTPUTS)
+ playbackDeviceId = SDL_OpenAudioDevice(nullptr, 0, &requested, &receivedPlayback,
+ SDL_AUDIO_ALLOW_FREQUENCY_CHANGE|SDL_AUDIO_ALLOW_SAMPLES_CHANGE);
+ if (playbackDeviceId == 0)
{
- SDL_CloseAudioDevice(deviceId);
- deviceId = 0;
+ d_stderr2("Failed to open SDL playback device, error was: %s", SDL_GetError());
+ return false;
+ }
+
+ if (receivedPlayback.channels != DISTRHO_PLUGIN_NUM_OUTPUTS)
+ {
+ SDL_CloseAudioDevice(playbackDeviceId);
+ playbackDeviceId = 0;
d_stderr2("Invalid or missing audio output channels");
return false;
}
+ #endif
+
+ #if DISTRHO_PLUGIN_NUM_INPUTS > 0 && DISTRHO_PLUGIN_NUM_OUTPUTS > 0
+ // if using both input and output, make sure they match
+ if (receivedCapture.samples != receivedPlayback.samples)
+ {
+ SDL_CloseAudioDevice(captureDeviceId);
+ SDL_CloseAudioDevice(playbackDeviceId);
+ captureDeviceId = playbackDeviceId = 0;
+ d_stderr2("Mismatch buffer size %u vs %u", receivedCapture.samples, receivedCapture.samples);
+ return false;
+ }
+ if (receivedCapture.freq != receivedPlayback.freq)
+ {
+ SDL_CloseAudioDevice(captureDeviceId);
+ SDL_CloseAudioDevice(playbackDeviceId);
+ captureDeviceId = playbackDeviceId = 0;
+ d_stderr2("Mismatch sample rate %u vs %u", receivedCapture.freq, receivedCapture.freq);
+ return false;
+ }
+ bufferSize = receivedCapture.samples;
+ sampleRate = receivedCapture.freq;
+ #elif DISTRHO_PLUGIN_NUM_INPUTS > 0
+ bufferSize = receivedCapture.samples;
+ sampleRate = receivedCapture.freq;
+ #elif DISTRHO_PLUGIN_NUM_OUTPUTS > 0
+ bufferSize = receivedPlayback.samples;
+ sampleRate = receivedPlayback.freq;
+ #else
+ d_stderr2("SDL without audio, unsupported for now");
+ return false;
+ #endif
- bufferSize = received.samples;
- sampleRate = received.freq;
#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
audioBufferStorage = new float[bufferSize*(DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS)];
@@ -108,11 +173,16 @@ struct SDLBridge {
bool close()
{
- DISTRHO_SAFE_ASSERT_RETURN(deviceId != 0, false);
-
- // SDL_CloseAudioDevice(deviceId);
- SDL_CloseAudio();
- deviceId = 0;
+#if DISTRHO_PLUGIN_NUM_INPUTS > 0
+ DISTRHO_SAFE_ASSERT_RETURN(captureDeviceId != 0, false);
+ SDL_CloseAudioDevice(captureDeviceId);
+ captureDeviceId = 0;
+#endif
+#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
+ DISTRHO_SAFE_ASSERT_RETURN(playbackDeviceId != 0, false);
+ SDL_CloseAudioDevice(playbackDeviceId);
+ playbackDeviceId = 0;
+#endif
#if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
delete[] audioBufferStorage;
@@ -124,17 +194,27 @@ struct SDLBridge {
bool activate()
{
- DISTRHO_SAFE_ASSERT_RETURN(deviceId != 0, false);
-
- SDL_PauseAudioDevice(deviceId, 0);
+#if DISTRHO_PLUGIN_NUM_INPUTS > 0
+ DISTRHO_SAFE_ASSERT_RETURN(captureDeviceId != 0, false);
+ SDL_PauseAudioDevice(captureDeviceId, 0);
+#endif
+#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
+ DISTRHO_SAFE_ASSERT_RETURN(playbackDeviceId != 0, false);
+ SDL_PauseAudioDevice(playbackDeviceId, 0);
+#endif
return true;
}
bool deactivate()
{
- DISTRHO_SAFE_ASSERT_RETURN(deviceId != 0, false);
-
- SDL_PauseAudioDevice(deviceId, 1);
+#if DISTRHO_PLUGIN_NUM_INPUTS > 0
+ DISTRHO_SAFE_ASSERT_RETURN(captureDeviceId != 0, false);
+ SDL_PauseAudioDevice(captureDeviceId, 1);
+#endif
+#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
+ DISTRHO_SAFE_ASSERT_RETURN(playbackDeviceId != 0, false);
+ SDL_PauseAudioDevice(playbackDeviceId, 1);
+#endif
return true;
}
@@ -184,7 +264,8 @@ struct SDLBridge {
return nullptr;
}
- static void SDLCallback(void* const userData, uchar* const stream, const int len)
+#if DISTRHO_PLUGIN_NUM_INPUTS > 0
+ static void AudioInputCallback(void* const userData, uchar* const stream, const int len)
{
SDLBridge* const self = (SDLBridge*)userData;
@@ -192,29 +273,54 @@ struct SDLBridge {
DISTRHO_SAFE_ASSERT_RETURN(stream != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(len > 0,);
- float* const fstream = (float*)stream;
+ const uint numFrames = static_cast<uint>(len / sizeof(float) / DISTRHO_PLUGIN_NUM_INPUTS);
+ DISTRHO_SAFE_ASSERT_UINT2_RETURN(numFrames == self->bufferSize, numFrames, self->bufferSize,);
+
+ const float* const fstream = (const float*)stream;
+
+ for (uint i=0; i<DISTRHO_PLUGIN_NUM_INPUTS; ++i)
+ {
+ for (uint j=0; j<numFrames; ++j)
+ self->audioBuffers[i][j] = fstream[j * DISTRHO_PLUGIN_NUM_INPUTS + i];
+ }
+
+ #if DISTRHO_PLUGIN_NUM_OUTPUTS == 0
+ // if there are no outputs, run process callback now
+ if (self->jackProcessCallback != nullptr)
+ self->jackProcessCallback(numFrames, self->jackProcessArg);
+ #endif
+ }
+#endif
+
+#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
+ static void AudioOutputCallback(void* const userData, uchar* const stream, const int len)
+ {
+ SDLBridge* const self = (SDLBridge*)userData;
+
+ // safety checks
+ DISTRHO_SAFE_ASSERT_RETURN(stream != nullptr,);
+ DISTRHO_SAFE_ASSERT_RETURN(len > 0,);
-// #if DISTRHO_PLUGIN_NUM_OUTPUTS == 0
if (self->jackProcessCallback == nullptr)
-// #endif
{
- std::memset(fstream, 0, len);
+ std::memset(stream, 0, len);
return;
}
-// #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
- const uint numFrames = static_cast<uint>(static_cast<uint>(len) / sizeof(float) / DISTRHO_PLUGIN_NUM_OUTPUTS);
+ const uint numFrames = static_cast<uint>(len / sizeof(float) / DISTRHO_PLUGIN_NUM_OUTPUTS);
+ DISTRHO_SAFE_ASSERT_UINT2_RETURN(numFrames == self->bufferSize, numFrames, self->bufferSize,);
+
+ float* const fstream = (float*)stream;
self->jackProcessCallback(numFrames, self->jackProcessArg);
for (uint i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
{
for (uint j=0; j < numFrames; ++j)
- fstream[j * DISTRHO_PLUGIN_NUM_OUTPUTS + i] = self->audioBuffers[DISTRHO_PLUGIN_NUM_INPUTS+i][j];
+ fstream[j * DISTRHO_PLUGIN_NUM_OUTPUTS + i] = self->audioBuffers[DISTRHO_PLUGIN_NUM_INPUTS + i][j];
}
-// #endif
}
-
+#endif
};
#endif