Audio Stutter Prevention
Learn how SAMMY Three’s multi-layered buffering system protects against audio stuttering and how to avoid main thread blocking in your applicationSAMMY Three uses a sophisticated audio buffering system to maintain smooth playback even when your application’s main thread gets temporarily busy. However, extended main thread blocking can still cause audio stuttering. This guide explains how the system works and how to prevent audio issues.
How the buffering system works
SAMMY Three implements a three-layer buffering system to protect against audio stuttering:Layer 1: JavaScript Audio Queue
The initial buffer that holds raw audio data waiting to be scheduled.- Buffer Size: 7,680 samples per buffer
- Duration: 320ms per buffer at 24kHz sample rate
- Queue Depth: Typically holds 640ms to 1.6 seconds of audio
Layer 2: Web Audio API Pre-scheduled Buffers
Audio buffers that are pre-scheduled in the Web Audio API’s internal queue.- Schedule Window: Maintains 400ms of audio scheduled ahead of current playback
- Key Benefit: These buffers play automatically, even if JavaScript is blocked
Layer 3: Initial Buffering Delay
A startup delay that ensures the system begins with adequate buffering.- Delay: 300ms before first audio plays
- Purpose: Builds up initial buffer cushion
The Web Audio API continues playing pre-scheduled buffers independently of JavaScript execution, which is why brief main thread blocks don’t cause stuttering.
The 400ms critical threshold
The most important number to remember is 400ms - this is how far ahead the audio streamer schedules buffers.What happens during main thread blocking:
- Safe (< 400ms)
- Risky (≈ 400ms)
- Stuttering (> 400ms)
Scenario: 200ms main thread block
- ✅ Pre-scheduled buffers continue playing
- ✅ No audible gaps or stuttering
- ✅ System recovers seamlessly when thread unblocks
Common causes of main thread blocking
Understanding what can block your main thread helps prevent audio issues:Safe operations (typically < 100ms)
- DOM updates and style recalculations
- Moderate API calls with async/await
- Standard React re-renders
- Small array operations
Risky operations (100-400ms)
These operations are on the edge of causing stuttering. Consider optimizing or moving to web workers.
- Large DOM manipulations
- Complex calculations without chunking
- Processing moderate-sized images
- Multiple synchronous API calls
- Large state updates in React
Dangerous operations (> 400ms)
These will definitely cause audio stuttering. Always use web workers or async patterns for these operations.
- Synchronous file I/O operations
- Processing large datasets synchronously
- Complex image/video processing
- Blocking network requests
- Heavy cryptographic operations
Best practices to prevent stuttering
1. Use Web Workers for heavy computation
Move CPU-intensive tasks off the main thread:2. Chunk large operations
Break up large synchronous operations into smaller chunks:3. Use requestIdleCallback for non-critical work
Schedule non-critical work for when the browser is idle:4. Optimize React renders
Prevent unnecessary re-renders that can block the thread:5. Monitor performance
Use the Performance API to identify blocking operations:Use Chrome DevTools Performance tab to profile your application and identify long tasks that might cause audio stuttering.
Audio recording considerations
The audio recording system processes buffers approximately every 43ms (2048 samples at 48kHz). While this is much shorter than the playback buffer, blocking the main thread can still affect recording quality by preventing timely processing of audio worklet messages.Recording is generally more sensitive to main thread blocking than playback, but the 400ms playback buffer is the more critical threshold for user-noticeable stuttering.
Summary
To prevent audio stuttering in SAMMY Three:- Remember the 400ms rule: Keep main thread operations under 400ms
- Use Web Workers: Move heavy computation off the main thread
- Chunk large operations: Break up synchronous work
- Monitor performance: Profile your app to identify blocking operations
- Optimize rendering: Minimize unnecessary React re-renders