๐ AudioLab Routing Overview - Complete Visual Guide¶
Purpose: Ultra-clear visual diagrams showing every step of audio flow from code to speakers. Target Audience: New developers confused by audio routing complexity. Last Updated: 2025-10-03
๐ Table of Contents¶
- Complete Audio Flow
- Development Testing Routing
- Latency Breakdown
- Multi-DAW Testing Setup
- Compatibility Matrix
๐ DIAGRAM 1: COMPLETE AUDIO FLOW¶
Visual Overview¶
๐น MIDI INPUT ๐ง AUDIO OUTPUT
Controller/Keyboard Studio Monitors
โ โฒ
โ USB/MIDI DIN โ XLR/TRS
โ โ
โผ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโ
โ DAW HOST โ โ AUDIO INTERFACE โ
โ (Reaper/Cubase/Live) โ โ RME/UA/Focusrite โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโโโโโ โ
โ โ Plugin Slot #1 โ โ โ โ ASIO Driver โ โ
โ โ โ โ โ โ (Windows) โ โ
โ โ โโโโโโโโโโโโโโโโโโโ โ โ โ โ โ โ
โ โ โ AudioLab โ โ โ Processed โ โ CoreAudio โ โ
โ โ โ Plugin โ โ โโโAudio Bufferโโโโโบโ โ (macOS) โ โ
โ โ โ (VST3/AU) โ โ โ 44.1/48kHz โ โ โ โ
โ โ โ โ โ โ 64-512 samples โ โ Buffer Size: โ โ
โ โ โ processBlock() โ โ โ โ โ 128 samples โ โ
โ โ โ โ โ โ โ โ โ โ โ
โ โ โ DSP Chain โ โ โ โ โ Latency: โ โ
โ โ โ โ โ โ โ โ โ ~3ms โ โ
โ โ โ Output Mix โ โ โ โ โโโโโโโโโโฌโโโโโโโโ โ
โ โ โโโโโโโโโโโโโโโโโโโ โ โ โ โ โ
โ โ โ โ โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโโโโโ โ
โ โ โ โ D/A Converter โ โ
โ Host Features: โ โ โ 24-bit/192kHz โ โ
โ โข Real-time thread priority โ โ โโโโโโโโโโฌโโโโโโโโ โ
โ โข Buffer management โ โ โ โ
โ โข Latency compensation โ โโโโโโโโโโโโโผโโโโโโโโโโโ
โ โข Parameter automation โ โ
โ โข State save/recall โ โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ Analog Output
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ [๐ Speakers]
โ VIRTUAL ROUTING (Dev/Testing) โ
โ โข VoiceMeeter Banana โ
โ โข Audio Hijack (macOS) โ
โ โข JACK Audio (Linux) โ
โ โข Loopback (macOS) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Component Details¶
๐น MIDI INPUT¶
- Types Supported:
- USB MIDI controllers (Akai, Novation, Arturia)
- Traditional MIDI DIN (via interface)
- Virtual MIDI ports (loopMIDI, IAC Driver)
-
DAW internal MIDI routing
-
Typical Latency: <1ms
- USB MIDI: 0.5-1ms
- DIN MIDI: 1-2ms (physical cable overhead)
-
Virtual: <0.1ms (software only)
-
Message Format:
-
DAW Configuration:
- Input device selection: Preferences โ MIDI Devices
- Channel routing: Track input selector
- MIDI learn: Right-click parameter โ Learn
๐ฅ๏ธ DAW HOST¶
Role: Audio engine and plugin host container
Buffer Management: | Buffer Size | Latency @ 48kHz | Use Case | |-------------|-----------------|----------| | 64 samples | ~1.3ms | Live performance, low CPU | | 128 samples | ~2.7ms | Recording, balanced | | 256 samples | ~5.3ms | Mixing, more plugins | | 512 samples | ~10.7ms | Mastering, maximum stability |
Sample Rate Options: - 44.1kHz: CD quality, standard - 48kHz: Video standard, pro audio default - 96kHz: High-resolution, double processing cost - 192kHz: Mastering grade, 4ร processing cost
Thread Model:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ GUI Thread (60Hz updates) โ โ Parameter changes
โ - Meter drawing โ โ Visual feedback
โ - User interaction โ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโ
โ Message Queue
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Audio Thread (Real-time) โ โ HIGHEST PRIORITY
โ - processBlock() calls โ โ NO memory allocation
โ - Buffer processing โ โ NO disk I/O
โ - Plugin chain execution โ โ Lock-free atomics only
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Critical Rules: - โ ๏ธ NEVER allocate memory in audio thread - โ ๏ธ NEVER use mutexes/locks in audio thread - โ ๏ธ NEVER call file I/O in audio thread - โ DO use lock-free FIFOs for inter-thread communication - โ DO pre-allocate all buffers in constructor
๐ PLUGIN (AudioLab)¶
Format Support:
VST3 (Steinberg)
โโ Windows: .vst3 bundle
โโ macOS: .vst3 bundle
โโ Linux: .vst3 bundle
AU (Apple)
โโ macOS only: .component bundle
AAX (Avid)
โโ Windows: .aaxplugin
โโ macOS: .aaxplugin
Processing Modes: | Mode | Input | Output | Use Case | |------|-------|--------|----------| | Mono | 1 | 1 | Vocal processing, bass | | Stereo | 2 | 2 | Mix bus, mastering | | MonoโStereo | 1 | 2 | Reverb, stereo widener | | Surround 5.1 | 6 | 6 | Film mixing |
Latency Compensation:
// In your AudioProcessor constructor or prepareToPlay:
void MyProcessor::prepareToPlay(double sampleRate, int samplesPerBlock) {
// Calculate fixed latency (e.g., FFT lookahead)
int fftLatency = fftSize / 2; // 2048 / 2 = 1024 samples
// Report to host for automatic delay compensation
setLatencySamples(fftLatency);
}
Parameter Automation (Thread-Safe):
// CORRECT: Atomic parameter access
void MyProcessor::processBlock(AudioBuffer<float>& buffer, MidiBuffer&) {
// Load atomic value ONCE per block
float gain = gainParameter->load();
// Use local copy for processing
for (int ch = 0; ch < buffer.getNumChannels(); ++ch) {
buffer.applyGain(ch, 0, buffer.getNumSamples(), gain);
}
}
// WRONG: Repeated atomic loads (slow)
for (int sample = 0; sample < numSamples; ++sample) {
float val = buffer.getSample(ch, sample);
val *= gainParameter->load(); // โ Atomic load every sample!
buffer.setSample(ch, sample, val);
}
๐๏ธ AUDIO INTERFACE¶
Driver Models:
| Platform | Driver | Latency | Pros | Cons |
|---|---|---|---|---|
| Windows | ASIO | 2-5ms | Professional standard | Exclusive mode |
| WDM/MME | 50-200ms | Universal | Unusable for music | |
| WASAPI | 10-30ms | Modern | Limited DAW support | |
| macOS | CoreAudio | 3-8ms | Built-in, stable | Less control than ASIO |
| Linux | JACK | 2-10ms | Flexible routing | Configuration complex |
| ALSA | 5-20ms | Direct hardware | Limited features |
Popular Interfaces - Latency Performance:
๐ BEST (2-3ms round-trip @ 64 samples):
โข RME Babyface Pro FS
โข Universal Audio Apollo Twin
โข Antelope Audio Discrete
โ
EXCELLENT (3-5ms @ 128 samples):
โข Focusrite Clarett
โข PreSonus Quantum
โข MOTU M4
โ ๏ธ GOOD (5-8ms @ 256 samples):
โข Focusrite Scarlett (3rd gen)
โข Audient iD4
โข SSL 2+
โ AVOID for pro work:
โข Built-in laptop audio (100-300ms)
โข Cheap USB dongles (50-150ms)
โข Bluetooth audio (150-500ms + dropouts)
Round-Trip Latency Calculation:
RTL = (Buffer Size / Sample Rate) ร 2 + Driver Overhead
Example @ 48kHz, 128 buffer, RME interface:
RTL = (128 / 48000) ร 2 + 0.001
RTL = 0.00533 + 0.001
RTL = 6.33ms โ
Excellent for live monitoring
๐ DIAGRAM 2: DEVELOPMENT TESTING ROUTING¶
Scenario: Testing plugin while developing with A/B reference comparison¶
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ DEVELOPMENT WORKSTATION โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ DAW #1 (Reaper) โ โ DAW #2 (Cubase) โ โ
โ โ Development DAW โ โ Reference DAW โ โ
โ โ โ โ โ โ
โ โ Track 1: Test Signal โ โ Track 1: Same Signal โ โ
โ โ โโ White Noise โ โ โโ White Noise โ โ
โ โ โโ Sine Sweep โ โ โโ Sine Sweep โ โ
โ โ โโ Music Loop โ โ โโ Music Loop โ โ
โ โ โ โ โ โ โ โ
โ โ โผ โ โ โผ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ AudioLab Plugin โ โ โ โ FabFilter Pro-Q โ โ โ
โ โ โ (DEV BUILD) โ โ โ โ (Reference) โ โ โ
โ โ โ ๐ด TESTING โ โ โ โ โ
KNOWN GOOD โ โ โ
โ โ โโโโโโโโโโฌโโโโโโโโโโ โ โ โโโโโโโโโโฌโโโโโโโโโโ โ โ
โ โ โ โ โ โ โ โ
โ โ โ Output โ โ โ Output โ โ
โ โโโโโโโโโโโโโผโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโผโโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ VIRTUAL CABLES (VoiceMeeter) โ โ
โ โ โ โ
โ โ ๐ด BUS A: Development Plugin โ โ
โ โ โโ Routable to analyzers โ โ
โ โ โ โ
โ โ ๐ต BUS B: Reference Plugin โ โ
โ โ โโ Routable to analyzers โ โ
โ โ โ โ
โ โ ๐ข BUS C: Monitor Mix โ โ
โ โ โโ A/B switch: BUS A โ BUS B โ โ
โ โ โโ Output to physical interface โ โ
โ โ โ โ
โ โ Controls: โ โ
โ โ โข Instant A/B toggle (hotkey: F1) โ โ
โ โ โข Volume match (critical!) โ โ
โ โ โข Polarity invert for null testing โ โ
โ โโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโ โ
โ โผ โผ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ Spectrum โ โ Phase Scope โ โ Level Meters โ โ
โ โ Analyzer โ โ (Correlation) โ โ (LUFS/Peak) โ โ
โ โ - Voxengo SPAN โ โ - s(M)exoscope โ โ - dpMeter โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ PHYSICAL AUDIO INTERFACE โ โ
โ โ (RME Babyface Pro) โ โ
โ โ โ โ
โ โ Outputs: โ โ
โ โ โข Main L/R โ Studio Monitors โ โ
โ โ โข Headphones โ Detailed listening โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Bus Configuration Details¶
๐ด BUS A: Development Plugin Output¶
Purpose: Route audio from your in-development plugin
Connection:
Reaper Track Output
โ VoiceMeeter VAIO Input 1
โ VoiceMeeter BUS A
โ Routable to any destination
Use Cases: - Real-time frequency analysis - Phase correlation checking - LUFS/loudness monitoring - Null test against reference (inverted phase)
Hotkey Setup (Reaper):
Actions โ Show action list โ Search "Track: Toggle mute for track 01"
Assign: F1 (for instant A/B switching)
๐ต BUS B: Reference Plugin Output¶
Purpose: Known-good commercial plugin for comparison
Selection Criteria:
Good References:
โ
FabFilter Pro-Q 3 (EQ reference)
โ
Valhalla VintageVerb (Reverb reference)
โ
Soundtoys Decapitator (Saturation reference)
Why these work:
โข Industry-standard sound quality
โข Predictable, well-documented behavior
โข Active development (bug-free)
Matching Settings:
โ ๏ธ CRITICAL: Volume-match before comparing!
Steps:
1. Generate pink noise test signal
2. Measure RMS level of BUS A output โ -18dBFS
3. Measure RMS level of BUS B output โ -16dBFS
4. Adjust BUS B gain: -2dB to match
5. NOW compare (ears are VERY sensitive to level differences)
๐ข BUS C: Final Monitor Mix¶
Purpose: Switchable output to physical speakers
Routing Logic:
IF A/B Switch = Position A:
BUS C Input โ BUS A
ELSE:
BUS C Input โ BUS B
BUS C Output โ Physical Interface Main Outs
Controls: - Volume: Master fader (pre-calibrated to -12dBFS = 85dB SPL) - Mute: Emergency silence (SPACE bar) - Solo: Isolate single bus - Polarity Invert: For null testing (if plugins match perfectly, output = silence)
Null Test Procedure:
1. Route identical signal to BUS A and BUS B
2. Set both plugins to IDENTICAL settings
3. Enable "Polarity Invert" on BUS B
4. Sum BUS A + BUS B โ BUS C
5. RESULT:
โข Perfect null (silence) = plugins are IDENTICAL
โข Residual sound = differences exist (expected for analog modeling)
Analyzer Tools Configuration¶
๐ Spectrum Analyzer (Voxengo SPAN)¶
Routing: Insert on BUS C (post-plugin, pre-speakers)
Settings:
FFT Size: 8192 # High resolution for low frequencies
Overlap: 4ร # Smooth display
Window: Blackman-Harris # Accurate magnitude
Range: -120dB to 0dB # Full dynamic range
Slope: Flat (0dB/oct) # Not A-weighted (see raw response)
What to Look For: - โ Smooth frequency response (no unexpected peaks/dips) - โ Low-frequency extension (how low before rolloff?) - โ High-frequency air (above 10kHz behavior) - โ ๏ธ Aliasing artifacts (unexpected content above Nyquist/2)
๐ฏ Phase Scope (s(M)exoscope)¶
Purpose: Detect stereo imaging issues
Routing: Stereo insert on BUS C
Interpretation:
Display Pattern:
โ Vertical line = MONO (L = R perfectly)
โ โฑ Diagonal = Good stereo imaging
โ โ Circle = Wide stereo (careful of phase issues)
โ โณ X-pattern = OUT OF PHASE (will disappear in mono!)
Critical Checks: - Bass content (< 120Hz) should be MOSTLY mono - Mid-range can be wider - Extreme width = potential mono compatibility issues
๐ Level Meters (dpMeter)¶
Routing: Post-fader on BUS C
Metrics:
Peak: -6dBFS max (headroom for inter-sample peaks)
RMS: -18dBFS average (mixing level)
LUFS-I: -14 LUFS (streaming target)
Crest: 12-18dB (dynamic range indicator)
Warnings: - ๐ด Peak > -0.1dBFS: Clipping imminent! - ๐ก RMS > -6dBFS: Too loud, reduce gain - ๐ข LUFS-I = -14ยฑ1: Perfect for streaming
๐ DIAGRAM 3: LATENCY BREAKDOWN¶
Complete Signal Path Timing¶
๐น MIDI Note Pressed
โ
โ โฑ๏ธ USB MIDI Latency: 0.5-1ms
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ DAW RECEIVES MIDI EVENT โ
โ Timestamp: Buffer-aligned โ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ โฑ๏ธ Input Buffer Fill Time
โ (Buffer Size / Sample Rate)
โ 128 samples @ 48kHz = 2.67ms
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ PLUGIN processBlock() CALLED โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Your DSP Processing โ โ
โ โ โ โ
โ โ Fixed Latency Sources: โ โ
โ โ โข FFT Lookahead: 1024 samples (21ms) โ โ
โ โ โข Linear Phase EQ: 2048 samples (43ms) โ โ
โ โ โข Reverb Pre-delay: 960 samples (20ms) โ โ
โ โ โ โ
โ โ Variable Latency Sources: โ โ
โ โ โข Adaptive Algorithms: 0-500 samples โ โ
โ โ โข Dynamic Oversampling: 64-256 samples โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ โฑ๏ธ Plugin Processing: 0-50ms (algorithm-dependent)
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ OUTPUT BUFFER ACCUMULATION โ
โ (Mixing with other tracks) โ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ โฑ๏ธ Output Buffer: 2.67ms (matches input)
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ AUDIO INTERFACE DRIVER โ
โ โ
โ โข ASIO Buffer Handoff: 0.5-1ms โ
โ โข USB Transfer (if USB): 1-2ms โ
โ โข Internal DSP (UA/Antelope): 0-1ms โ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ โฑ๏ธ Driver + Hardware: 1-5ms
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ D/A CONVERTER โ
โ (Digital โ Analog) โ
โ Conversion time: ~0.1ms โ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
๐ SOUND WAVES
(Propagation: 1ms per foot @ room temp)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
TOTAL ROUND-TRIP LATENCY
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Calculation:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ LATENCY CONTRIBUTORS โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ MIDI Input: 0.5 - 1ms โ
โ Input Buffer: 2.67ms (128@48kHz) โ
โ Plugin Process: 0 - 50ms (lookahead) โ
โ Output Buffer: 2.67ms โ
โ Driver Overhead: 1 - 5ms โ
โ D/A Conversion: 0.1ms โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ TOTAL: 7 - 61ms โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ฏ ACCEPTABLE LATENCY RANGES:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
0-10ms โ IMPERCEPTIBLE
โข Live performance ready
โข No compensation needed
โข Feels "instant"
โ ๏ธ 10-20ms โ NOTICEABLE
โข Workable for most users
โข Tight timing may feel slightly off
โข Piano/drums most affected
โ 20-30ms โ PROBLEMATIC
โข Live playing is difficult
โข Use input monitoring instead
โข Acceptable for mixing only
๐ >30ms โ UNUSABLE
โข Significant delay perception
โข Cannot perform in real-time
โข Pre-record or reduce buffer
Latency Source Deep-Dive¶
๐ฅ Input Buffer Latency¶
What It Is: Time to fill buffer before processing starts
Formula:
Input Latency (ms) = (Buffer Size / Sample Rate) ร 1000
Examples:
โข 64 samples @ 44.1kHz = 1.45ms
โข 128 samples @ 48kHz = 2.67ms
โข 256 samples @ 96kHz = 2.67ms (same duration!)
โข 512 samples @ 48kHz = 10.67ms
Control: ASIO Control Panel โ Buffer Size
Trade-offs:
Smaller Buffer (64):
โ
Lower latency (good for tracking)
โ Higher CPU usage
โ More prone to dropouts/clicks
Larger Buffer (512):
โ
More stable (good for mixing)
โ
Lower CPU usage
โ Higher latency (bad for live playing)
Sweet Spot for Development: 128-256 samples - Balanced latency/stability - Matches most users' real-world settings - Catches buffer-size-dependent bugs
โ๏ธ Plugin Processing Latency¶
Fixed Latency (Algorithmic Requirement):
// FFT-based processing (frequency domain)
int fftSize = 2048;
int latency = fftSize / 2; // 1024 samples = 21ms @ 48kHz
// Linear-phase EQ (symmetric FIR filter)
int firTaps = 2048;
int latency = firTaps / 2; // 1024 samples
// Lookahead limiter/compressor
int lookaheadSamples = 480; // 10ms @ 48kHz
int latency = lookaheadSamples; // Exactly 10ms
Reporting to Host:
void MyAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock) {
// Calculate your fixed latency
int totalLatency = fftLatency + lookaheadLatency;
// CRITICAL: Tell host for delay compensation
setLatencySamples(totalLatency);
// Host will now automatically align this track with others
}
What Happens If You Don't Report: - โ Multi-track recordings will be out of sync - โ Parallel processing will phase-cancel - โ Automation will be offset
Variable Latency (Avoid If Possible):
// โ ๏ธ PROBLEMATIC: Latency changes during playback
void processBlock(AudioBuffer<float>& buffer, MidiBuffer&) {
if (qualityMode == HIGH) {
setLatencySamples(2048); // โ Can't change mid-playback!
} else {
setLatencySamples(512);
}
}
// โ
BETTER: Fix latency at initialization
void prepareToPlay(double sampleRate, int samplesPerBlock) {
// Use MAXIMUM possible latency always
setLatencySamples(2048);
// Lower quality modes just waste some of the buffer
// (Better than glitchy latency changes)
}
๐ค Output Buffer Latency¶
What It Is: Matches input buffer (double-buffering)
Why It Exists:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ DOUBLE BUFFERING (prevents glitches) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Buffer A: [Writing new samples] โ
โ Buffer B: [Playing current samples] โ
โ โ
โ Every buffer period, they SWAP: โ
โ โข No interruption to playback โ
โ โข No race conditions โ
โ โข Smooth, click-free audio โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Cannot Be Reduced: This is fundamental to stable audio I/O
๐ง Driver Overhead Latency¶
Platform Differences:
| Driver | Typical Overhead | Notes |
|---|---|---|
| ASIO (Windows) | 0.5-2ms | Best case, professional interfaces |
| WDM (Windows) | 10-30ms | Avoid for music production |
| CoreAudio (macOS) | 1-3ms | Excellent, built-in |
| JACK (Linux) | 1-5ms | Configuration-dependent |
Interface Quality Matters:
๐ Professional (RME, UA, Antelope):
โข Optimized drivers: ~1ms overhead
โข Direct hardware control
โข Stable at 64-sample buffers
โ Budget (Generic USB, Realtek):
โข Poor drivers: 5-20ms overhead
โข Software resampling layers
โข Unstable below 512 samples
Latency Debugging Checklist¶
When users report "high latency":
โก Check ASIO buffer size (should be 128-256 for live use)
โก Verify sample rate matches interface settings (no resampling)
โก Disable audio enhancements (Windows: Sound Control Panel โ Disable all)
โก Close other audio apps (Spotify, YouTube = buffer conflicts)
โก Check plugin latency reporting (DAW's delay compensation active?)
โก Test with interface's direct monitoring (zero-latency proof-of-concept)
โก Update interface drivers (old drivers = extra overhead)
โก Check CPU usage (overload = buffer underruns = glitches)
๐ DIAGRAM 4: MULTI-DAW TESTING SETUP¶
Cross-DAW Compatibility Validation¶
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ MULTI-DAW TESTING WORKSTATION โ
โ โ
โ โโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ โ
โ โ Reaper 7.x โ โ Cubase 13 โ โ Ableton Live12 โ โ
โ โ (FREE) โ โ (Trial/Edu) โ โ (Trial 90d) โ โ
โ โ โ โ โ โ โ โ
โ โ โ
Tests: โ โ โ
Tests: โ โ โ
Tests: โ โ
โ โ โข VST3 load โ โ โข VST3 strict โ โ โข VST3/AU โ โ
โ โ โข Automation โ โ โข ASIO-Guard โ โ โข Freeze/Flat โ โ
โ โ โข Rendering โ โ โข Sidechain โ โ โข MPE MIDI โ โ
โ โ โข ReaScript โ โ โข Expression โ โ โข Clip Launch โ โ
โ โโโโโโโโโฌโโโโโโโโโ โโโโโโโโโฌโโโโโโโโโ โโโโโโโโโฌโโโโโโโโโ โ
โ โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ AUTOMATED TEST SUITE โ โ
โ โ (Python + DAW Scripts) โ โ
โ โ โ โ
โ โ Per-DAW Tests: โ โ
โ โ 1. Plugin Scan & Load โ โ
โ โ 2. Parameter Recall โ โ
โ โ 3. Automation Write/Read โ โ
โ โ 4. State Save/Load โ โ
โ โ 5. Preset Management โ โ
โ โ 6. Sidechain Routing โ โ
โ โ 7. Crash Recovery โ โ
โ โ 8. Sample Rate Change โ โ
โ โโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โผ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ VALIDATION โ โ AUDIO CAPTURE โ โ
โ โ REPORTS โ โ & ANALYSIS โ โ
โ โ โ โ โ โ
โ โ โข Parameters Load: โ โ โข Bounce Quality: โ โ
โ โ โ
All correct โ โ Compare bit-exact โ โ
โ โ โ โ โ โ
โ โ โข Automation: โ โ โข CPU Usage: โ โ
โ โ โ
Follows curves โ โ Log per DAW โ โ
โ โ โ โ โ โ
โ โ โข State Recall: โ โ โข Memory Leaks: โ โ
โ โ โ
No crashes โ โ Valgrind/ASAN โ โ
โ โ โ โ โ โ
โ โ โข Crash Tests: โ โ โข Buffer Stability: โ โ
โ โ โ ๏ธ 2 failures โ โ Dropout detection โ โ
โ โ (see log) โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Final Report: test_results_2025-10-03.html โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Per-DAW Testing Matrix¶
โ Reaper (Cockos)¶
Pros for Testing: - โก Fast plugin scan (< 5 seconds for 100 plugins) - ๐ ReaScript automation (Python/Lua scripting) - ๐๏ธ Flexible routing (any track to any track) - ๐พ Human-readable project files (easy to diff)
Known Quirks:
Issue: Reaper's unique routing matrix
Impact: Sidechain inputs use different API than other DAWs
Solution: Test sidechain via getBusCount() and explicit bus routing
Issue: Non-destructive FX rendering
Impact: Plugin state might not match offline render
Solution: Verify setNonRealtime() is respected in processBlock()
Test Script (ReaScript Lua):
-- automate_parameter_test.lua
function runPluginTest()
-- Load plugin on track 1
track = reaper.GetTrack(0, 0)
fx_idx = reaper.TrackFX_AddByName(track, "AudioLab Plugin", false, -1)
-- Set parameter 0 to 0.5
reaper.TrackFX_SetParam(track, fx_idx, 0, 0.5)
-- Read back (should match within float precision)
value = reaper.TrackFX_GetParam(track, fx_idx, 0)
if math.abs(value - 0.5) < 0.0001 then
reaper.ShowConsoleMsg("โ
Parameter set/get: PASS\n")
else
reaper.ShowConsoleMsg("โ Parameter set/get: FAIL\n")
end
end
runPluginTest()
โ Cubase (Steinberg)¶
Pros for Testing: - ๐ Strictest VST3 validation (catches spec violations) - ๐ต Advanced MIDI (Expression Maps, Note Expression) - ๐ ASIO-Guard stress test (parallel processing)
Known Quirks:
Issue: ASIO-Guard moves processing to background thread
Impact: Timing assumptions break, race conditions exposed
Solution: All inter-thread communication MUST be lock-free
Issue: Sample rate changes during project (film work)
Impact: prepareToPlay() called mid-session
Solution: Properly reset ALL state in prepareToPlay(), not just constructor
Issue: Strict state validation
Impact: setState() with invalid data = instant crash dialog
Solution: Robust state versioning with fallback to defaults
Critical Test:
// Test ASIO-Guard compatibility
void AudioLabProcessor::processBlock(AudioBuffer<float>& buffer, MidiBuffer& midi) {
// โ WRONG: Assumes buffer timestamp is continuous
currentTime += buffer.getNumSamples(); // Breaks with ASIO-Guard!
// โ
CORRECT: Use PlayHead position
if (auto* playHead = getPlayHead()) {
if (auto pos = playHead->getPosition()) {
currentTime = pos->getTimeInSamples().orFallback(0);
}
}
}
โ Ableton Live (Ableton AG)¶
Pros for Testing: - ๐ญ Unique workflows (clip launching, freeze tracks) - ๐น MPE MIDI support (polyphonic expression) - โก Session view (non-linear arrangement)
Known Quirks:
Issue: Plugin scanning is VERY sensitive to crashes
Impact: One crash during scan = plugin blacklisted forever
Solution: Clear plugin cache: ~/Library/Preferences/Ableton/Live x.x.x/
Issue: Freeze track converts to audio offline
Impact: Must handle setNonRealtime(true) correctly
Solution: Disable any real-time-only features (spectrum analyzers, etc.)
Issue: Clip automation vs. arrangement automation
Impact: Parameters can have TWO automation sources simultaneously
Solution: Properly handle parameter changes from multiple sources
Test Scenario:
1. Load plugin on MIDI track
2. Create automation in Clip view (sawtooth LFO on cutoff)
3. Create DIFFERENT automation in Arrangement view (step sequence)
4. Switch between Session/Arrangement
5. VERIFY: Plugin responds to correct automation source
6. VERIFY: No clicks/pops on automation switch
โ Pro Tools (Avid) [If Available]¶
Pros for Testing: - ๐ Industry standard (film/music post-production) - ๐ AAX format strictest validation - ๐น Video sync (frame-accurate timing)
Known Quirks:
Issue: Sample rate changes are VERY slow
Impact: Users avoid SR changes; plugin must handle gracefully
Solution: Don't force sample rate; adapt to whatever PT provides
Issue: AAX requires separate build pipeline
Impact: Different SDK, different signing, different bugs
Solution: Test VST3 AND AAX builds separately
Issue: Track freeze is destructive
Impact: No way to "unfreeze" without re-recording
Solution: Ensure offline render is IDENTICAL to real-time
Automated Testing Suite¶
Test Harness (Python + DAW Scripting):
# test_all_daws.py
import subprocess
import os
DAWS = {
'reaper': {
'executable': r'C:\Program Files\REAPER\reaper.exe',
'script': 'reaper_tests.lua',
'timeout': 300
},
'cubase': {
'executable': r'C:\Program Files\Steinberg\Cubase 13\Cubase13.exe',
'project': 'cubase_test_template.cpr',
'timeout': 600
},
'ableton': {
'executable': r'C:\ProgramData\Ableton\Live 12\Program\Ableton Live 12.exe',
'project': 'ableton_test_template.als',
'timeout': 600
}
}
def run_daw_tests(daw_name, config):
"""Run automated tests in specified DAW"""
print(f"๐งช Testing {daw_name.upper()}...")
# Launch DAW with test project
process = subprocess.Popen([
config['executable'],
config.get('project', ''),
'--headless' # If supported
])
# Monitor for crashes
try:
process.wait(timeout=config['timeout'])
except subprocess.TimeoutExpired:
print(f"โ ๏ธ {daw_name} test timed out")
process.kill()
return False
# Parse results
if process.returncode == 0:
print(f"โ
{daw_name} tests PASSED")
return True
else:
print(f"โ {daw_name} tests FAILED (code {process.returncode})")
return False
# Run all tests
results = {}
for daw, config in DAWS.items():
results[daw] = run_daw_tests(daw, config)
# Generate report
print("\n" + "="*50)
print("FINAL RESULTS:")
for daw, passed in results.items():
status = "โ
PASS" if passed else "โ FAIL"
print(f" {daw.upper():15} {status}")
Test Checklist by Category¶
1๏ธโฃ Plugin Scan & Load¶
Reaper:
โก Plugin appears in FX browser
โก Loads in < 2 seconds
โก No console warnings
Cubase:
โก Passes VST3 validator (strict mode)
โก Correct category assignment
โก Thumbnail/icon displays
Ableton:
โก Survives initial scan without crash
โก Appears in Browser โ Plug-ins
โก Tags/categories correct
2๏ธโฃ Parameter Recall¶
All DAWs:
โก Set all parameters to random values
โก Save project
โก Close DAW
โก Reopen project
โก VERIFY: All parameters match saved values
โก VERIFY: No parameters reset to default
โก VERIFY: No NaN or infinity values
Common Bug:
// โ WRONG: Saving GUI state, not audio state
void AudioProcessor::getStateInformation(MemoryBlock& destData) {
// If GUI hasn't opened yet, parameters might be uninitialized!
auto value = editor->getSliderValue(); // โ Editor might not exist
}
// โ
CORRECT: Save audio processor state
void AudioProcessor::getStateInformation(MemoryBlock& destData) {
// Always save from AudioProcessor's parameter objects
auto value = parameters.getRawParameterValue("cutoff")->load();
}
3๏ธโฃ Automation Write/Read¶
All DAWs:
โก Enable automation write on parameter
โก Move parameter while playing
โก Switch to automation read mode
โก VERIFY: Parameter follows recorded automation
โก VERIFY: Smooth curves (no stairstepping)
โก VERIFY: No clicks/pops during automation
Smoothing Requirement:
// Automation can change VERY rapidly (every sample)
// Your plugin MUST smooth parameter changes!
void processBlock(AudioBuffer<float>& buffer, MidiBuffer&) {
// โ WRONG: Direct parameter use
float cutoff = *cutoffParam;
filter.setCutoff(cutoff); // Causes clicks!
// โ
CORRECT: Smoothed parameter
cutoffSmoothed.setTargetValue(*cutoffParam);
for (int sample = 0; sample < buffer.getNumSamples(); ++sample) {
float smoothCutoff = cutoffSmoothed.getNextValue();
// Use smooth value for this sample
}
}
4๏ธโฃ State Save/Load Stress Test¶
All DAWs:
โก Create 100 random presets
โก For each preset:
โก Load preset
โก Save project
โก Load project
โก VERIFY: State matches
โก No memory leaks (check RAM usage)
โก No crashes after 100 iterations
5๏ธโฃ Crash Recovery¶
Cubase (best crash handling):
โก Trigger intentional crash (null pointer dereference)
โก VERIFY: Cubase shows crash dialog
โก VERIFY: Cubase offers to disable plugin
โก VERIFY: Project still loads without plugin
Reaper:
โก Crash should NOT take down entire DAW
โก VERIFY: Track bypasses automatically
Ableton:
โก Crash during scan = blacklisted
โก VERIFY: Can re-scan after fixing bug
6๏ธโฃ Sample Rate Change¶
All DAWs:
โก Load plugin at 44.1kHz
โก Change project to 48kHz
โก VERIFY: prepareToPlay() called with new rate
โก VERIFY: No audio glitches during transition
โก VERIFY: Frequency-dependent parameters scale correctly
Example:
โข LPF at 1kHz @ 44.1kHz should stay at 1kHz @ 48kHz
โข NOT scale to 1088Hz (ratio-based error)
๐๏ธ COMPATIBILITY MATRIX¶
Feature Support by DAW¶
| Feature | Reaper | Cubase | Ableton | Pro Tools | Notes |
|---|---|---|---|---|---|
| VST3 | โ | โ | โ | โ | PT uses AAX only |
| VST2 (legacy) | โ | โ | โ | โ | Deprecated, avoid |
| AU (macOS) | โ | โ | โ | โ | |
| AAX | โ | โ | โ | โ | Requires iLok licensing |
| Sidechain | โ | โ | โ | โ | Different APIs per DAW |
| MIDI Input | โ | โ | โ | โ | |
| MPE MIDI | โ ๏ธ | โ | โ | โ ๏ธ | Limited in Reaper/PT |
| Surround | โ | โ | โ | โ | Live is stereo-centric |
| Latency Comp | โ | โ | โ | โ | All modern DAWs |
| Offline Render | โ | โ | โ | โ | Via setNonRealtime() |
| Plugin Delay | โ | โ | โ | โ | Via setLatencySamples() |
| Resize GUI | โ | โ | โ ๏ธ | โ | Live has issues |
| Automation | โ | โ | โ | โ | Different curve types |
| Presets (.vstpreset) | โ | โ | โ | โ | AAX uses .tfx format |
Platform Support Matrix¶
| Platform | VST3 | AU | AAX | Recommended |
|---|---|---|---|---|
| Windows 10/11 | โ | โ | โ | VST3 primary |
| macOS (Intel) | โ | โ | โ | AU + VST3 |
| macOS (Apple Silicon) | โ | โ | โ | Native ARM builds! |
| Linux | โ | โ | โ | VST3 only |
Architecture Support¶
Windows:
โ
x64 (64-bit) - REQUIRED (32-bit is dead)
โ x86 (32-bit) - SKIP (no modern DAWs support)
macOS:
โ
x86_64 (Intel)
โ
arm64 (Apple Silicon M1/M2/M3)
โ ๏ธ Universal Binary (both) - RECOMMENDED
Linux:
โ
x86_64
โ ๏ธ ARM64 (Raspberry Pi) - niche but growing
Known DAW-Specific Bugs¶
Reaper¶
Bug: ReaComp sidechain routing differs from spec
Workaround: Detect Reaper via host name, use alternate bus index
Bug: Resizing can cause OpenGL context loss
Workaround: Recreate GL context on resize event
Cubase¶
Bug: ASIO-Guard + fast automation = race condition
Workaround: Use atomic<float> for ALL shared parameters
Bug: Expression Maps don't send Note Off sometimes
Workaround: Implement note timeout (kill after 10 seconds)
Ableton Live¶
Bug: Freeze sometimes renders at wrong sample rate
Workaround: Check getPlayHead() sample rate, resample if needed
Bug: GUI resize can crash on Windows
Workaround: Disable resizing on Windows (check #ifdef _WIN32)
Pro Tools¶
Bug: Bouncing stems doesn't call setNonRealtime()
Workaround: Detect long buffer sizes (> 8192) as offline hint
Bug: Surround bus routing is AAX-specific
Workaround: Read AAX SDK docs (completely different from VST)
๐ Best Practices Summary¶
Do's โ ¶
- Test in multiple DAWs BEFORE releasing
-
Minimum: Reaper (free) + one commercial DAW trial
-
Report latency accurately
-
Handle sample rate changes gracefully
-
Save complete state
-
Smooth all parameter changes
Don'ts โ¶
- DON'T assume buffer size is constant
-
Some DAWs change it mid-session!
-
DON'T use malloc/new in audio thread
-
Pre-allocate everything in prepareToPlay()
-
DON'T assume stereo
-
Support mono, surround via getNumInputChannels()
-
DON'T hardcode sample rate
-
Calculate everything from getSampleRate()
-
DON'T ignore setNonRealtime()
- Offline render might need different settings
๐ Further Resources¶
- VST3 SDK Documentation
- JUCE Forum - DAW Compatibility
- Reaper ReaScript API
- Ableton Live Object Model (LOM)
Document Status: โ Complete Next Review: When new DAW versions release Maintained By: AudioLab DevOps Team