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"

// 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"


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

@@ -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

Loading…
Cancel
Save