songbird-host-ffi
FFI bridge for hosting C++ (JUCE) VST3/AU plugins from the Rust audio engine. Rust owns the audio thread. Third-party plugins are loaded and processed via JUCE through a thin C ABI layer. TheJucePlugin wrapper implements the Rust Plugin trait, so external plugins are interchangeable with stock Rust plugins in the audio graph.
Architecture
FFI Declarations (16 functions)
| Function | Purpose |
|---|---|
ffi_plugin_load | Load a plugin by path/format (VST3, AU, etc.) |
ffi_plugin_unload | Unload and free a plugin instance |
ffi_plugin_initialize | Set sample rate and block size |
ffi_plugin_reset | Reset plugin state |
ffi_plugin_process | Process audio buffer (non-interleaved float pointers) |
ffi_plugin_get_param_count | Number of parameters |
ffi_plugin_get_param_name | Parameter name by index |
ffi_plugin_get_param_value | Current parameter value (0.0–1.0) |
ffi_plugin_set_param_value | Set parameter value |
ffi_plugin_get_param_default | Default parameter value |
ffi_plugin_get_latency | Plugin latency in samples |
ffi_plugin_get_tail | Tail length in seconds |
ffi_plugin_save_state | Save binary plugin state |
ffi_plugin_load_state | Restore binary plugin state |
ffi_plugin_accepts_midi | Whether plugin processes MIDI |
ffi_plugin_send_midi | Send MIDI events to plugin |
JucePlugin Wrapper
Buffer Layout
Both sides use non-interleaved (planar) float buffers:AudioBuffer<float>::getWritePointer() layout, so no format conversion is needed at the boundary.
Out-of-Process Hosting (Future)
ThePlugin trait does not assume shared memory. The FFI bridge can be extended to host plugins in a separate process (like Ableton/Bitwig do) by:
- Replacing
ffi_plugin_processwith IPC (shared memory ring buffer or pipe) - Running the JUCE host in a child process
- Crashing plugin = child process dies, not the DAW
JucePlugin wrapper’s interface stays the same — only the transport layer changes.
Status
- Rust side: Complete (16
extern "C"declarations,JucePluginwrapper, 6 unit tests) - C++ side: Stubs only (needs a thin JUCE wrapper implementing the 16 functions)