Browse Source

Rework SDL bridge to support audio input

Signed-off-by: falkTX <falktx@falktx.com>
pull/321/head
falkTX 3 years ago
parent
commit
ceaea6080f
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
2 changed files with 145 additions and 39 deletions
  1. +1
    -1
      distrho/src/jackbridge/JackBridge.cpp
  2. +144
    -38
      distrho/src/jackbridge/SDLBridge.hpp

+ 1
- 1
distrho/src/jackbridge/JackBridge.cpp View File

@@ -36,7 +36,7 @@
#include "../../extra/LibraryUtils.hpp" #include "../../extra/LibraryUtils.hpp"


// in case JACK fails, we fallback to RtAudio or SDL native API // 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" # include "SDLBridge.hpp"
#elif defined(DISTRHO_PROPER_CPP11_SUPPORT) && !defined(DPF_JACK_STANDALONE_SKIP_RTAUDIO_FALLBACK) #elif defined(DISTRHO_PROPER_CPP11_SUPPORT) && !defined(DPF_JACK_STANDALONE_SKIP_RTAUDIO_FALLBACK)
# include "RtAudioBridge.hpp" # include "RtAudioBridge.hpp"


+ 144
- 38
distrho/src/jackbridge/SDLBridge.hpp View File

@@ -23,7 +23,12 @@
#include <SDL.h> #include <SDL.h>


struct SDLBridge { 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 // SDL information
uint bufferSize = 0; uint bufferSize = 0;
@@ -61,37 +66,97 @@ struct SDLBridge {


bool open(const char* const clientName) 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)); std::memset(&requested, 0, sizeof(requested));
requested.format = AUDIO_F32SYS; requested.format = AUDIO_F32SYS;
requested.channels = DISTRHO_PLUGIN_NUM_OUTPUTS;
requested.freq = 48000; requested.freq = 48000;
requested.samples = 512; requested.samples = 512;
requested.callback = SDLCallback;
requested.userdata = this; requested.userdata = this;


SDL_SetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME, clientName); 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"); 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"); d_stderr2("Invalid or missing audio output channels");
return false; 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 #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
audioBufferStorage = new float[bufferSize*(DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS)]; audioBufferStorage = new float[bufferSize*(DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS)];
@@ -108,11 +173,16 @@ struct SDLBridge {


bool close() 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 #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
delete[] audioBufferStorage; delete[] audioBufferStorage;
@@ -124,17 +194,27 @@ struct SDLBridge {


bool activate() 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; return true;
} }


bool deactivate() 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; return true;
} }


@@ -184,7 +264,8 @@ struct SDLBridge {
return nullptr; 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; SDLBridge* const self = (SDLBridge*)userData;


@@ -192,29 +273,54 @@ struct SDLBridge {
DISTRHO_SAFE_ASSERT_RETURN(stream != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(stream != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(len > 0,); 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) if (self->jackProcessCallback == nullptr)
// #endif
{ {
std::memset(fstream, 0, len);
std::memset(stream, 0, len);
return; 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); self->jackProcessCallback(numFrames, self->jackProcessArg);


for (uint i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) for (uint i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
{ {
for (uint j=0; j < numFrames; ++j) 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 #endif

Loading…
Cancel
Save