DSP plugins
A DSP plugin adds an audio effect to the playback chain — an EQ voicing, a tube warmer, a vocal renderer. It is a separate Android app that ships a WebAssembly module; the engine loads it and runs it in the real-time audio path, with sliders and presets you declare.
How it works
You compile your effect to a .wasm module and drop it in the app’s assets/. The host discovers the package, reads its manifest, loads the module, and drives it through a tiny C ABI. Running as WebAssembly keeps the effect sandboxed and portable across every device Lydex runs on — no native build per architecture.
Audio is exchanged through a scratch buffer in the module’s own linear memory: prepare() returns its address, the host writes interleaved f64 samples there, calls process(), and reads them back. Processing is in place and real-time — no allocation, no blocking.
Declare the plugin
Describe the effect with <meta-data> under <application>, plus a discovery receiver carrying the dev.lydex.intent.action.DSP_PLUGIN intent-filter so the package manager can find the app.
| meta-data | Meaning |
|---|---|
| dev.lydex.plugin.kind | "dsp" — marks this APK as a DSP-effect plugin. |
| dev.lydex.plugin.id | A stable, unique id (e.g. "aria"). |
| dev.lydex.plugin.displayName | The name shown in the app. |
| dev.lydex.plugin.wasmAsset | Filename of your compiled .wasm module inside the APK’s assets/ folder. |
| dev.lydex.plugin.params | Parameter specs, comma-separated: id:label:min:max:default. The app renders one slider per param. |
| dev.lydex.plugin.presets | Named presets: Name:0=v,1=v|Name2:0=v,… — each sets the listed param ids to values. |
Parameters & presets
Parameters are declared as a compact string and the app renders one slider each. A param spec is id:label:min:max:default, comma-separated; a preset is Name:0=v,1=v, pipe-separated. At runtime the host pushes values through lydex_dsp_set_param(id, value).
params: 0:Sweetness:0:100:40, 1:Presence:0:100:55, 2:Air:0:100:25 presets: Pop:0=50,1=60,2=40 | Jazz:0=60,1=50,2=15
Export the ABI
Your module exports these C functions. process() runs on the audio thread — keep it allocation-free and deterministic.
| Export | Contract |
|---|---|
| lydex_dsp_prepare(rate, channels, maxFrames) → i32 | Called before playback with the stream format. Build filters for the sample rate; return the address of your interleaved-f64 audio buffer in linear memory. |
| lydex_dsp_process(frames, channels) | Process one block in place: frames×channels interleaved f64 samples sit in the buffer from prepare(). Real-time — no allocation, no blocking. |
| lydex_dsp_set_param(id, value) | Set parameter id to value (an f64 in the min..max range you declared). Called when the user moves a slider or picks a preset. |
| lydex_dsp_reset() | Clear internal state — filters, delay lines — on seek or track change. |
| lydex_dsp_latency_frames() → i32 | Report the latency you add, in frames, so the host can compensate. |
| lydex_dsp_set_enabled(on) | Bypass toggle. When off, pass audio through untouched. |
| lydex_dsp_enabled() → i32 | Return the current bypass state. |
Reference
The open-source DSP template is the place to start — a minimal but real effect (output trim plus tanh warmth) as a Rust→WebAssembly module and a thin APK, exporting the full ABI. It is the exact shape your plugin takes.