feat!: Add worklet ecosystem, offline rendering, and processor metrics; drop legacy ScriptProcessorNode API#65
Merged
Merged
Conversation
…s\n\n- Rename all strategy IDs (hann8, blackman8, kaiser8, lanczos8) to (hann, blackman, kaiser, lanczos)\n- Standardize on zeroCrossings for kernel width param\n- Update all code, tests, and docs for new naming and parameter conventions\n- Remove deprecated lanczos8-strategy.mdx and update navigation\n- Add and update kitchen sink playgrounds for all strategies
…controls BREAKING CHANGE: PitchShifter, SimpleFilter, WebAudioBufferSource, getWebAudioNode, and FilterSupport are no longer exported from @soundtouchjs/core. SoundTouch no longer exposes rate, tempo, virtualRate, or virtualTempo. SoundTouchNode no longer exposes tempo or rate AudioParams. Remove PitchShifter, SimpleFilter, WebAudioBufferSource, getWebAudioNode, FilterSupport, minsSecs, and noop — all solely supported the deprecated ScriptProcessorNode path. AudioWorklet is supported in all targeted browsers including iOS Safari 14.5+. Simplify SoundTouch to pitch-only public control: remove rate, tempo, virtualRate, virtualTempo, rateChange, and tempoChange setters. Internal _rate and _tempo are now always derived from virtualPitch. Remove tempo and rate AudioParams from SoundTouchNode. Playback speed is controlled exclusively by mirroring playbackRate on both the source node and SoundTouchNode. Add CLAUDE.md with mandatory code change requirements: JSDoc, tests, and documentation gates, plus Conventional Commits table and project conventions. Update all READMEs, Storybook stories, and .mdx docs to reflect the current public API and remove all references to removed symbols. Consolidate three duplicate root-level .mdx files into their beginner-friendly core/ versions.
…t conventions Add Commands and Architecture sections documenting Nx task commands, the SoundTouch processing pipeline, AudioWorklet pattern, worklet processor bundling, interpolation strategy plugin system, test setup, and Nx auto-detection rules. Correct the test command from pnpm --filter to pnpm nx test, add feat!/BREAKING CHANGE commit row, and document required files for new worklet packages. fix(audio-worklet): Add outputChannelCount option to SoundTouchNode Add optional outputChannelCount?: 1 | 2 to SoundTouchNodeConstructorOptions so callers can connect SoundTouchNode to mono destinations without creating a separate ChannelMergerNode. Defaults to 2 (stereo). Document the existing mono input fallback in processor.ts with inline comments. Add tests for all three cases (default, 1, 2) and add an explicit mono output processor test.
Add StretchParameters interface (sequenceMs, seekWindowMs, overlapMs, quickSeek) and setStretchParameters() method to Stretch and SoundTouch for fine-grained control of the WSOLA time-stretch algorithm at runtime. Add public overlapMs getter/setter and quickSeek getter to Stretch, making the previously-hidden timing internals accessible without replacing all parameters at once. Add SetStretchParametersMessage to the processor message union so SoundTouchNode.setStretchParameters() can queue updates to the render thread.
…dering Add processOffline() helper that renders an AudioBuffer through SoundTouch in an OfflineAudioContext without requiring a live audio device. Accepts pitch, pitchSemitones, playbackRate, interpolationStrategy, stretchParameters, and sampleBufferType options. Output length is estimated as ceil(input.length / playbackRate).
Processor posts framesBuffered, underrunCount, and blockCount to the main thread every 100 render blocks. SoundTouchNode stores the latest snapshot as ProcessorMetrics, exposes it via a metrics getter, and dispatches a metrics CustomEvent for event-driven monitoring.
…olution Documents how to resolve processorModuleUrl in Vite, webpack 5, and static hosting setups, plus OfflineAudioContext usage and common first-time mistakes (registration order, CORS, relative paths, autoplay).
Introduces StretchPipe as a structural interface for the time-stretch stage, implemented by the existing Stretch class. SoundTouchOptions gains a stretchFactory callback so callers can substitute a custom stage (e.g. a phase vocoder) without subclassing. Also fixes stale @cxing/ scopes and missing packages in nx.json release.projects.
Adds two new packages: - @soundtouchjs/stretch-phase-vocoder: FFT-based StretchPipe implementation using radix-2 Cooley-Tukey FFT, Hann-windowed overlap-add synthesis, and per-bin phase accumulation. Includes createPhaseVocoderFactory for drop-in use with SoundTouchOptions.stretchFactory. - @soundtouchjs/phase-vocoder-worklet: AudioWorklet integration wrapping PhaseVocoderNode (mirrors SoundTouchNode API) and PhaseVocoderProcessor (uses SoundTouch with the phase vocoder stretchFactory). Adds fftSize and overlapFactor constructor options. Full metrics observability support.
Adds @soundtouchjs/formant-correction-worklet — an AudioWorkletNode that applies SoundTouch pitch-shifting with LPC-based formant preservation. Use FormantCorrectionNode instead of SoundTouchNode when pitching vocals without the chipmunk/giant timbre shift. Key additions: - lpc.ts: autocorrelate, levinsonDurbin, applyAnalysisFilter, applySynthesisFilter (LPC order 16, 512-sample Hamming window) - formant-correction-processor.ts: per-block LPC correction with formantStrength AudioParam blend (0 = raw, 1 = corrected) - FormantCorrectionNode.ts: AudioWorkletNode with pitch, pitchSemitones, playbackRate, and formantStrength AudioParams; metrics getter/event - Storybook playground with formantStrength slider and A/B toggle - Full Vitest test suite (37 tests), README, and Storybook MDX docs
…grounds Add StretchParametersPlayground with live sliders for sequenceMs, seekWindowMs, overlapMs, and a quickSeek toggle — all wired to SoundTouchNode.setStretchParameters() and applied immediately to the running audio graph during playback. Add ProcessOfflinePlayground that fetches a track, renders it through processOffline() in an OfflineAudioContext, then plays the resulting AudioBuffer. Shows render time, output duration, and live code sample reflecting current parameter values. Also fix a pre-existing MDX parse failure in getting-started.mdx caused by smart/curly quotes throughout the file that prevented the Storybook 9 acorn indexer from parsing the compiled MDX output.
- Wire ProcessorMetrics event listener into AudioWorkletPlayground,
StretchParametersPlayground, FormantCorrectionPlayground, and
PhaseVocoderPlayground; metrics panel is always visible, defaulting to 0
- Fix Storybook static build: change processor/installer imports from
?url to ?worker&url so Vite bundles each dependency inline
- Add worker: { format: 'es' } and publicDir to storybook vite.config.mts
- Add .github/workflows/storybook-pages.yml for GitHub Pages deployment
- Restructure CI: merge test + coverage-summary into single validation job
- Raise @soundtouchjs/core coverage thresholds to branches: 85, functions: 95
- Add interpolationStrategyRegistry tests to reach 85.75% branch coverage
- Migrate ESLint config from .eslintrc.cjs to per-package .eslintrc.json
- Add static-storybook to .gitignore
- Add processOffline() to phase-vocoder-worklet and formant-correction-worklet - Add outputRms and outputPeak to ProcessorMetrics for all worklet packages - Update demo metrics panel to display outputRms and outputPeak - Update PhaseVocoderPlayground to surface expanded metrics - Update Storybook and README docs for offline rendering and observability APIs - Fix nx release changelog rules and semverBump for non-code commit types
Coverage checkResult: ✅ passed Generated: 2026-05-14T21:37:12.644Z
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
This PR introduces a major expansion of the SoundTouchJS worklet ecosystem and cleans up the core API by removing the long-deprecated ScriptProcessorNode path. Targets v2.0.0.
ScriptProcessorNode API removed
PitchShifter,SimpleFilter,WebAudioBufferSource,getWebAudioNode,FilterSupport,minsSecs, andnoopare no longer exported from@soundtouchjs/core.SoundTouchno longer exposesrate,tempo,virtualRate,virtualTempo, or their change setters — these are now derived internally fromvirtualPitch.SoundTouchNodeno longer hastempoorrateAudioParams; playback speed is controlled by mirroringplaybackRateon both the source node andSoundTouchNode.AudioWorklet is supported in all targeted browsers including iOS Safari 14.5+. The deprecated ScriptProcessorNode path has no replacement path within this library.
License
Upgraded from LGPL-2.1 to LGPL-3.0. Review compliance obligations if you redistribute.
Interpolation strategy IDs renamed
Strategy IDs
hann8,blackman8,kaiser8, andlanczos8are nowhann,blackman,kaiser, andlanczos. The kernel width parameter is now consistentlyzeroCrossingsacross all strategies.New Packages
@soundtouchjs/stretch-phase-vocoder@soundtouchjs/core@soundtouchjs/phase-vocoder-worklet@soundtouchjs/formant-correction-worklet@soundtouchjs/interpolation-strategy-hann@soundtouchjs/interpolation-strategy-blackman@soundtouchjs/interpolation-strategy-kaiserFeatures
@soundtouchjs/core: AddStretchPipeinterface andstretchFactoryoption, allowing the WSOLA stretch stage to be swapped out at construction time. Expose WSOLA timing parameters (sequenceMs,seekWindowMs,overlapMs).processOffline(): All three worklet packages now export aprocessOffline()helper for non-real-time rendering viaOfflineAudioContext.ProcessorMetricsnow includesoutputRmsandoutputPeak(per 128-frame block, both channels) alongside the existingframesBuffered,underrunCount,blockCount, andtimestampfields.Refactoring
CI / Tooling
nx.jsonrelease config: added explicitchangelogproperties to allconventionalCommits.typesentries so changelog generation is not silently governed by the angular preset defaults.typecheckandlint.