Skip to content

Add real-time-safe SPSC ring buffer and denormal-aware delay line#18

Merged
matt-edmondson merged 1 commit into
mainfrom
claude/vst-plugin-upstream-djlud9
Jun 9, 2026
Merged

Add real-time-safe SPSC ring buffer and denormal-aware delay line#18
matt-edmondson merged 1 commit into
mainfrom
claude/vst-plugin-upstream-djlud9

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Summary

Implements upstream roadmap item #3 from the .NET VST3 effects host plan: real-time-safe buffers for the audio↔UI boundary and for delay-based DSP. Both types are additive and pre-allocate their backing store so they never allocate, lock, or block on the hot path.

SpscRingBuffer<T>

A lock-free, wait-free, fixed-capacity single-producer/single-consumer ring buffer.

  • Allocation-free and non-blocking TryEnqueue / TryDequeue / TryPeek — safe to call from an audio/render thread (producer) with a UI/worker thread (consumer).
  • Correctness via acquire/release ordering (Volatile.Read/Volatile.Write); one reserved slot disambiguates full vs empty.
  • Head/tail indices are cache-line padded (separate non-generic [StructLayout(Explicit)] struct) to avoid false sharing.
  • Intended for pushing meter/scope telemetry from the audio callback to the UI thread (see plan §"Real-Time Safety").

DelayLine

A fixed-capacity circular delay line for audio-rate float samples.

  • Integer (Read) and linear-interpolated (ReadInterpolated) taps; Process(input, delay) is the common write-then-tap idiom.
  • Read(d) returns x[n-d] with d in [0, Capacity] (delay 0 = most recently written sample), so Process(x, D) outputs the input from exactly D samples earlier.
  • Denormal-aware: subnormal magnitudes are flushed to zero on write to avoid the large CPU penalty denormals cause in decaying feedback paths.
  • Power-of-two backing store for branch-free index wrapping.

Testing

Added MSTest coverage for both types (SpscRingBufferTests, DelayLineTests), including FIFO ordering, full/empty edges, wraparound, denormal flushing, interpolation, argument validation, and a 1M-item concurrent producer/consumer soak test. Full suite: 351/351 passing locally (net10.0).

Note: the local sandbox only has .NET SDK 10.0.108, which is older than the Roslyn the pinned ktsu.Sdk analyzers (2.8.0) require, so tests were run with the standard dotnet/MSTest runner against net10.0. CI runs the full multi-target build with analyzers and style enforcement.

🤖 Part of the ktsu VST plugin upstream-enablement work.

https://claude.ai/code/session_01JQ3bQMuSYuumAnQZaYUKP7


Generated by Claude Code

Adds two real-time-safe container types in support of the .NET VST3
effects host plan (upstream roadmap item #3):

- SpscRingBuffer<T>: a lock-free, wait-free, fixed-capacity
  single-producer/single-consumer ring buffer. Allocation-free and
  non-blocking on both push and pop, with acquire/release ordering and
  cache-line padding to avoid false sharing. Intended for pushing
  meter/scope telemetry from an audio callback to the UI thread.

- DelayLine: a fixed-capacity circular delay line for audio-rate float
  samples with integer and linear-interpolated taps. Denormals are
  flushed to zero on write to avoid CPU spikes in decaying feedback
  paths. Read(d) returns x[n-d] with d in [0, Capacity].

Both pre-allocate their backing store and never allocate, lock, or block
on the hot path. Includes MSTest coverage, including a concurrent
producer/consumer soak test for the ring buffer.
@matt-edmondson matt-edmondson merged commit ec63ef8 into main Jun 9, 2026
2 of 3 checks passed
@github-project-automation github-project-automation Bot moved this to Done in ktsu.dev Jun 9, 2026
@matt-edmondson matt-edmondson deleted the claude/vst-plugin-upstream-djlud9 branch June 9, 2026 03:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

2 participants