This document describes the OpenMP parallelization patches applied to the rubberband library during the Emscripten build process.
Patches are applied in emscripten/build.sh in the "OPENMP PARALLELIZATION PATCHES" section.
Location: src/faster/R2Stretcher.cpp
Patched Loops:
- Line ~278: Channel resampler reset loop
#ifdef _OPENMP #pragma omp parallel for schedule(static) if(m_channels > 2) #endif for (int c = 0; c < int(m_channels); ++c) { if (m_channelData[c]->resampler) { m_channelData[c]->resampler->reset(); } }
Impact: Parallelizes resampler initialization across channels.
Location: src/faster/StretcherProcess.cpp
Patched Loops:
- Channel data operations
- Buffer processing loops
Impact: Parallelizes sample processing for multi-channel audio.
Location: src/finer/R3Stretcher.cpp
Patched Loops:
- Constructor channel initialization (~line 113)
- Study/Process channel loops (~lines 679, 702, 764, etc.)
- Reset and configuration loops
Impact: Parallelizes high-quality stretching across channels.
Location: src/finer/R3LiveShifter.cpp
Patched Loops:
- Buffer management loops
- Ring buffer operations
- Channel processing in real-time mode
Impact: Reduces latency in live pitch shifting.
All patches use #ifdef _OPENMP guards:
#ifdef _OPENMP
#pragma omp parallel for schedule(static) if(m_channels > 2)
#endif
for (int c = 0; c < m_channels; ++c) {
// loop body
}This ensures:
- Code compiles without OpenMP
- Only parallelizes when beneficial (> 2 channels)
- Safe fallback if threads unavailable
- Static scheduling for balanced workloads (all channels similar)
- Dynamic scheduling considered for unbalanced processing
- Channel buffer initialization
- Independent per-channel processing
- Resampler reset (before processing)
- Shared state modifications
- Accumulation/reductions without locks
- I/O operations
The patches are applied automatically during:
npm run build:emcc
# or
bash emscripten/build.sh- Copy rubberband source to temp directory
- Apply existing compatibility patches
- Apply OpenMP patches (NEW)
- Compile all sources with
-fopenmp - Link with
libomp.a
- Multi-channel audio (> 2 channels)
- Large buffer sizes (> 10ms of audio)
- Complex processing (high quality mode)
| Channels | Expected Speedup |
|---|---|
| Mono (1) | None (overhead) |
| Stereo (2) | Minimal |
| Quad (4) | 2-3x |
| 5.1 (6) | 3-4x |
| 7.1 (8) | 4-6x |
- Web Workers have overhead
- Small buffers don't benefit
- Memory bandwidth bound operations limited
To verify OpenMP is working in rubberband:
- Build with debug info:
emscripten/build.sh 2>&1 | grep -E "(OpenMP|parallel)"- Check generated JS for thread usage:
grep -c "pthread" public/hyphon_native.js- Runtime verification:
// In browser console
Module.getNumThreads(); // Should return > 1No speedup observed:
- Check
m_channels > 2condition - Verify pthread pool initialized
- Buffer size may be too small
Audio glitches:
- Thread contention on shared resources
- Reduce
PTHREAD_POOL_SIZE - Disable OpenMP for problematic loops
Build errors:
- Ensure
libomp.aexists inemscripten/ - Verify Emscripten SDK version >= 3.1.0
To disable OpenMP patches temporarily:
# In build.sh, comment out:
# --- OPENMP PARALLELIZATION PATCHES ---
# ... patch commands ...- Granular Control: Add runtime switch for OpenMP
- Benchmark Mode: Compare JS vs WASM performance
- Adaptive Scheduling: Choose schedule based on buffer size
- More Loops: Identify additional parallelizable regions