Browse Source

Allow runtime buffer size changes in wasm/bridge modules

Signed-off-by: falkTX <falktx@falktx.com>
pull/321/head
falkTX 3 years ago
parent
commit
29e9fe9a9f
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
4 changed files with 162 additions and 13 deletions
  1. +15
    -0
      distrho/DistrhoStandaloneUtils.hpp
  2. +38
    -4
      distrho/src/jackbridge/JackBridge.cpp
  3. +9
    -0
      distrho/src/jackbridge/NativeBridge.hpp
  4. +100
    -9
      distrho/src/jackbridge/WebBridge.hpp

+ 15
- 0
distrho/DistrhoStandaloneUtils.hpp View File

@@ -35,6 +35,11 @@ START_NAMESPACE_DISTRHO
*/
bool supportsAudioInput();

/**
Check if the current standalone supports dynamic buffer size changes.
*/
bool supportsBufferSizeChanges();

/**
Check if the current standalone supports MIDI.
*/
@@ -50,12 +55,22 @@ bool isAudioInputEnabled();
*/
bool isMIDIEnabled();

/**
Get the current buffer size.
*/
uint32_t getBufferSize();

/**
Request permissions to use audio input.
Only valid to call if audio input is supported but not currently enabled.
*/
bool requestAudioInput();

/**
Request change to a new buffer size.
*/
bool requestBufferSizeChange(uint32_t newBufferSize);

/**
Request permissions to use MIDI.
Only valid to call if MIDI is supported but not currently enabled.


+ 38
- 4
distrho/src/jackbridge/JackBridge.cpp View File

@@ -1185,7 +1185,13 @@ bool jackbridge_set_buffer_size_callback(jack_client_t* client, JackBufferSizeCa
#elif defined(JACKBRIDGE_DIRECT)
return (jack_set_buffer_size_callback(client, bufsize_callback, arg) == 0);
#else
if (usingRealJACK && getBridgeInstance().set_buffer_size_callback_ptr != nullptr)
if (usingNativeBridge)
{
nativeBridge->bufferSizeCallback = bufsize_callback;
nativeBridge->jackBufferSizeArg = arg;
return true;
}
if (getBridgeInstance().set_buffer_size_callback_ptr != nullptr)
{
# ifdef __WINE__
WineBridge::getInstance().set_bufsize(bufsize_callback);
@@ -1371,9 +1377,10 @@ bool jackbridge_set_buffer_size(jack_client_t* client, jack_nframes_t nframes)
#elif defined(JACKBRIDGE_DIRECT)
return jack_set_buffer_size(client, nframes);
#else
if (usingRealJACK)
if (getBridgeInstance().set_buffer_size_ptr != nullptr)
return getBridgeInstance().set_buffer_size_ptr(client, nframes);
if (usingNativeBridge)
return nativeBridge->requestBufferSizeChange(nframes);
if (getBridgeInstance().set_buffer_size_ptr != nullptr)
return getBridgeInstance().set_buffer_size_ptr(client, nframes);
#endif
return false;
}
@@ -2257,6 +2264,15 @@ bool supportsAudioInput()
return true;
}

bool supportsBufferSizeChanges()
{
#if !(defined(JACKBRIDGE_DUMMY) || defined(JACKBRIDGE_DIRECT))
if (usingNativeBridge)
return nativeBridge->supportsBufferSizeChanges();
#endif
return false;
}

bool supportsMIDI()
{
#if defined(JACKBRIDGE_DUMMY)
@@ -2290,6 +2306,15 @@ bool isMIDIEnabled()
return true;
}

uint32_t getBufferSize()
{
#if !(defined(JACKBRIDGE_DUMMY) || defined(JACKBRIDGE_DIRECT))
if (usingNativeBridge)
return nativeBridge->getBufferSize();
#endif
return 0;
}

bool requestAudioInput()
{
#if !(defined(JACKBRIDGE_DUMMY) || defined(JACKBRIDGE_DIRECT))
@@ -2299,6 +2324,15 @@ bool requestAudioInput()
return false;
}

bool requestBufferSizeChange(const uint32_t newBufferSize)
{
#if !(defined(JACKBRIDGE_DUMMY) || defined(JACKBRIDGE_DIRECT))
if (usingNativeBridge)
return nativeBridge->requestBufferSizeChange(newBufferSize);
#endif
return false;
}

bool requestMIDI()
{
#if !(defined(JACKBRIDGE_DUMMY) || defined(JACKBRIDGE_DIRECT))


+ 9
- 0
distrho/src/jackbridge/NativeBridge.hpp View File

@@ -36,7 +36,9 @@ struct NativeBridge {

// JACK callbacks
JackProcessCallback jackProcessCallback = nullptr;
JackBufferSizeCallback bufferSizeCallback = nullptr;
void* jackProcessArg = nullptr;
void* jackBufferSizeArg = nullptr;

// Runtime buffers
enum PortMask {
@@ -85,11 +87,18 @@ struct NativeBridge {
#endif
}

virtual bool supportsBufferSizeChanges() const { return false; }
virtual bool supportsMIDI() const { return false; }
virtual bool isMIDIEnabled() const { return false; }
virtual bool requestAudioInput() { return false; }
virtual bool requestBufferSizeChange(uint32_t) { return false; }
virtual bool requestMIDI() { return false; }

uint32_t getBufferSize() const noexcept
{
return bufferSize;
}

uint32_t getEventCount()
{
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT


+ 100
- 9
distrho/src/jackbridge/WebBridge.hpp View File

@@ -114,7 +114,7 @@ struct WebBridge : NativeBridge {
return false;
}

bufferSize = 512;
bufferSize = 2048;
sampleRate = EM_ASM_INT_V({
var WAB = Module['WebAudioBridge'];
return WAB.audioContext.sampleRate;
@@ -212,15 +212,24 @@ struct WebBridge : NativeBridge {
// we need to use this weird awkward way for objects, otherwise build fails
constraints['audio'] = true;
constraints['video'] = false;
constraints['latency'] = 0;
constraints['sampleSize'] = 24;
constraints['mandatory'] = {};
constraints['mandatory']['autoGainControl'] = false;
constraints['mandatory']['echoCancellation'] = false;
constraints['mandatory']['noiseSuppression'] = false;
constraints['mandatory']['channelCount'] = numInputs;
constraints['autoGainControl'] = {};
constraints['autoGainControl']['exact'] = false;
constraints['echoCancellation'] = {};
constraints['echoCancellation']['exact'] = false;
constraints['noiseSuppression'] = {};
constraints['noiseSuppression']['exact'] = false;
constraints['channelCount'] = {};
constraints['channelCount']['min'] = 0;
constraints['channelCount']['ideal'] = numInputs;
constraints['latency'] = {};
constraints['latency']['min'] = 0;
constraints['latency']['ideal'] = 0;
constraints['sampleSize'] = {};
constraints['sampleSize']['min'] = 8;
constraints['sampleSize']['max'] = 32;
constraints['sampleSize']['ideal'] = 16;
// old property for chrome
constraints['mandatory']['googAutoGainControl'] = false;
constraints['googAutoGainControl'] = false;

var success = function(stream) {
WAB.captureStreamNode = WAB.audioContext['createMediaStreamSource'](stream);
@@ -239,6 +248,88 @@ struct WebBridge : NativeBridge {
return true;
}

bool supportsBufferSizeChanges() const override
{
return true;
}

bool requestBufferSizeChange(const uint32_t newBufferSize) override
{
// try to create new processor first
bool success = EM_ASM_INT({
var numInputs = $0;
var numOutputs = $1;
var newBufferSize = $2;
var WAB = Module['WebAudioBridge'];

try {
WAB.newProcessor = WAB.audioContext['createScriptProcessor'](newBufferSize, numInputs, numOutputs);
} catch (e) {
return 0;
}

// got new processor, disconnect old one
WAB.processor['disconnect'](WAB.audioContext['destination']);

if (WAB.captureStreamNode)
WAB.captureStreamNode.disconnect(WAB.processor);

return 1;
}, DISTRHO_PLUGIN_NUM_INPUTS, DISTRHO_PLUGIN_NUM_OUTPUTS, newBufferSize) != 0;

if (!success)
return false;

bufferSize = newBufferSize;
freeBuffers();
allocBuffers();

if (bufferSizeCallback != nullptr)
bufferSizeCallback(newBufferSize, jackBufferSizeArg);

EM_ASM({
var numInputs = $0;
var numOutputs = $1;
var bufferSize = $2;
var WAB = Module['WebAudioBridge'];

// store the new processor
delete WAB.processor;
WAB.processor = WAB.newProcessor;
delete WAB.newProcessor;

// setup new processor the same way as old one
WAB.processor['onaudioprocess'] = function (e) {
// var timestamp = performance.now();
for (var i = 0; i < numInputs; ++i) {
var buffer = e['inputBuffer']['getChannelData'](i);
for (var j = 0; j < bufferSize; ++j) {
// setValue($3 + ((bufferSize * i) + j) * 4, buffer[j], 'float');
HEAPF32[$3 + (((bufferSize * i) + j) << 2) >> 2] = buffer[j];
}
}
dynCall('vi', $4, [$5]);
for (var i = 0; i < numOutputs; ++i) {
var buffer = e['outputBuffer']['getChannelData'](i);
var offset = bufferSize * (numInputs + i);
for (var j = 0; j < bufferSize; ++j) {
buffer[j] = HEAPF32[$3 + ((offset + j) << 2) >> 2];
}
}
};

// connect to output
WAB.processor['connect'](WAB.audioContext['destination']);

// and input, if available
if (WAB.captureStreamNode)
WAB.captureStreamNode.connect(WAB.processor);

}, DISTRHO_PLUGIN_NUM_INPUTS, DISTRHO_PLUGIN_NUM_OUTPUTS, bufferSize, audioBufferStorage, WebAudioCallback, this);

return true;
}

bool supportsMIDI() const override
{
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_MIDI_OUTPUT


Loading…
Cancel
Save