fix: properly clear all internal buffers to prevent audio artifacts after seeking #34
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem
When reusing SoundTouch instances after seeking (calling
clear()), audio artifacts (buzz, pops, crackling) would persist for 1-2 seconds. This made it impractical to reuse instances, forcing developers to recreate SoundTouch objects on every seek, which causes GC pressure in real-time audio applications.Root Cause
The
clear()method had three issues:FifoSampleBuffer.clear() only reset pointers, not the actual Float32Array data. Stale audio samples remained in memory and bled into subsequent processing.
RateTransposer had no
clear()method. The interpolation state (prevSampleL,prevSampleR,slopeCount) persisted, causing discontinuities when processing resumed.Stretch.clearMidBuffer() had two problems:
midBufferwhenmidBufferDirtywas truerefMidBuffer(correlation reference buffer), causing the WSOLA algorithm to find incorrect overlap positionsSolution
FifoSampleBuffer.js
RateTransposer.js
Stretch.js
Why midBuffer = null instead of fill(0)?
Setting midBuffer = null triggers the initialization block in process():
This ensures midBuffer is populated with actual audio samples from the new position, rather than zeros. When midBuffer contains zeros, the cross-correlation calculations produce arbitrary results, leading to incorrect overlap positions and audio artifacts.
Testing
Tested in a multi-track audio player with pitch shifting:
Breaking Changes
None. This is a bug fix that makes clear() work as expected.