PluginChainSampleProvider class.
Architecture
The plugin chain implements NAudio’sISampleProvider interface, integrating seamlessly with the audio engine:
Chain Structure
Each plugin chain consists of two distinct sections:1. Instrument Slot
- Purpose: Holds a single VSTi (VST Instrument)
- Cardinality: One instrument per track
- Processing: Generates audio from MIDI input
- Replacement: Adding a new instrument replaces the existing one
2. Effects Chain
- Purpose: Processes audio through multiple effects
- Cardinality: Multiple effects in sequence
- Default Plugins: Every track includes Utility and SimpleEq
- Processing Order: Effects are applied in list order
The effects chain always includes a
UtilityPlugin and SimpleEqPlugin by default, ensuring basic mixing controls are available on every track.Plugin Management
Adding Plugins
- VSTi Plugins: Replace the existing instrument and dispose of the old one
- VST/Built-in Effects: Append to the effects chain
Removing Plugins
- Mark for Deletion: Sets
DeleteRequested = true - Dispose Resources: Calls
Dispose()for VST plugins - Remove from Chain: Clears instrument slot or removes from effects list
Clearing All Plugins
The
.ToList() call creates a copy of the collection, allowing safe removal during iteration.Audio Processing Pipeline
Read Method
TheRead() method is called by NAudio’s audio engine on each buffer:
ProcessAudio Method
- Temporary Buffer: Ensures clean input/output separation
- In-place Processing:
tempBufferserves as both input and output to the plugin - Buffer Copying: Safely handles offset positioning in the main buffer
Plugins receive and write to the same buffer (
tempBuffer) in their Process() method, enabling efficient in-place processing.Signal Flow Diagram
Bypass and Enable Control
Plugins can be bypassed without removing them from the chain:- No need to remove/re-add plugins
- Maintains plugin order
- Preserves plugin settings
- A/B comparison of processed/unprocessed audio
Toggle Method
TheIAudioProcessor interface provides a convenience method:
Thread Safety Considerations
ToList() Protection
The plugin chain uses.ToList() when iterating during processing:
- Creates a snapshot of the current plugin list
- Protects against collection modification during iteration
- Allows safe removal of plugins during processing
Delete Requested Flag
Plugins use aDeleteRequested flag for deferred cleanup:
- Set
DeleteRequested = truewhen removing a plugin - Plugin skips processing on next audio callback
- Plugin is disposed and removed from the chain
- Avoids removing plugins mid-processing
- Ensures current audio callback completes safely
- Defers resource cleanup to a safe point
Integration Example
Creating a plugin chain for a track:Performance Characteristics
Buffer Copying Overhead
Buffer Copying Overhead
Each plugin in the chain requires buffer copying:
- Copy to temp buffer
- Plugin processing
- Copy back to main buffer
Processing Order Matters
Processing Order Matters
Effects are applied sequentially:
- Order affects the final sound
- CPU-intensive plugins later in the chain process already-processed audio
- Consider placing lighter effects first for optimal performance
Enabled Check Performance
Enabled Check Performance
Checking
Enabled before processing:- Near-zero overhead for disabled plugins
- Bypass without removing from chain
- Instant enable/disable without plugin reload
Related Topics
VST Plugin Support
Learn how VST plugins integrate into the chain
Built-in Plugins
Explore the default plugins in every chain
Plugin Overview
Understanding the IAudioProcessor interface