fix(vsti): crackle fix P1-P3 — SHM 8-slot ring + drain-delta pump + AudioWorklet sink
- SharedMemoryIPC.h/main.cpp: render into ring slot (idx & ringMask), 8 slots - shm.rs: ring fields + read_ring_audio; lib.rs pump drains FULL delta, not just latest - bridgeAudioNode.js: AudioWorklet primary (bridge-audio-sink), ScriptProcessor fallback - bridgeAudioWorklet.js: ring 64 blocks, underrun fade, overrun drop + crossfade - layout tests: sizeof 27560 (8-align via u64)
This commit is contained in:
@@ -62,6 +62,17 @@ struct SharedAudioBufferIPC {
|
||||
// liveness on this, so a slow (but alive) audio loop no longer looks dead.
|
||||
// Append-only field: existing offsets stay stable.
|
||||
volatile uint32_t heartbeat;
|
||||
|
||||
// VSTi crackle fix: multi-slot audio ring (appended after heartbeat — all
|
||||
// offsets above stay stable). The bridge renders block N into slot
|
||||
// (bridgeWriteIndex & ringMask), then increments bridgeWriteIndex (publish).
|
||||
// The reader drains EVERY slot between its last index and writeIndex, in
|
||||
// order, so a delayed reader no longer loses a whole block to single-slot
|
||||
// overwrite (the old 1-slot gap). ringMask = slot count - 1 (power of 2);
|
||||
// 8 slots ~= 42ms of audio @ 48k — covers a pump/WebView jank window.
|
||||
volatile uint32_t ringMask;
|
||||
float ringLeft[8][AUDIO_BLOCK_SIZE];
|
||||
float ringRight[8][AUDIO_BLOCK_SIZE];
|
||||
};
|
||||
|
||||
// G4.3: per-plugin sandbox SHM — double-buffered audio handoff.
|
||||
|
||||
Reference in New Issue
Block a user