SoundTouchJS
May 15, 2026 · View on GitHub
A real-time audio processing library for pitch shifting and playback speed control using the Web Audio API. Converted, expanded, and maintained by Cutter, based on the original SoundTouch C++ library by Olli Parviainen.
I accept cash if you like what's been done.
Monorepo
This project is an Nx monorepo managed with pnpm workspaces. It publishes eleven packages:
| Package | npm | Description |
|---|---|---|
@soundtouchjs/core | npm install @soundtouchjs/core | Core processing library — SoundTouch, buffers, and the interpolation registry |
@soundtouchjs/audio-worklet | npm install @soundtouchjs/audio-worklet | AudioWorklet implementation with AudioParam-based controls, offline rendering, and processor metrics |
@soundtouchjs/stretch-phase-vocoder | npm install @soundtouchjs/stretch-phase-vocoder | Phase vocoder time-stretch algorithm — implements StretchPipe, usable standalone or as a SoundTouch stretch stage |
@soundtouchjs/phase-vocoder-worklet | npm install @soundtouchjs/phase-vocoder-worklet | AudioWorklet implementation using the phase vocoder for smoother extreme-ratio time-stretching |
@soundtouchjs/formant-correction-worklet | npm install @soundtouchjs/formant-correction-worklet | AudioWorklet implementation with LPC-based formant preservation for natural-sounding vocal pitch shifts |
@soundtouchjs/worklet-base | npm install @soundtouchjs/worklet-base | Abstract base class for building custom AudioWorklet processors on top of the SoundTouch engine |
@soundtouchjs/interpolation-strategy-lanczos | npm install @soundtouchjs/interpolation-strategy-lanczos | Lanczos interpolation strategy plugin (default strategy id: lanczos) |
@soundtouchjs/interpolation-strategy-linear | npm install @soundtouchjs/interpolation-strategy-linear | Linear interpolation strategy plugin (strategy id: linear) |
@soundtouchjs/interpolation-strategy-hann | npm install @soundtouchjs/interpolation-strategy-hann | Hann interpolation strategy plugin (strategy id: hann) |
@soundtouchjs/interpolation-strategy-blackman | npm install @soundtouchjs/interpolation-strategy-blackman | Blackman interpolation strategy plugin (strategy id: blackman) |
@soundtouchjs/interpolation-strategy-kaiser | npm install @soundtouchjs/interpolation-strategy-kaiser | Kaiser interpolation strategy plugin (strategy id: kaiser) |
A development demo app is included for testing both packages in a browser.
If you are new to Web Audio, start with the demo guide: apps/demo/README.md.
Documentation
- Storybook docs home: https://cutterscrossing.com/SoundTouchJS/?path=/docs/introduction--docs
- Core package API and concepts: packages/core/README.md
- Core API reference index: https://cutterscrossing.com/SoundTouchJS/?path=/docs/core-soundtouch--docs
- AudioWorklet package API and setup: packages/audio-worklet/README.md
- AudioWorklet API reference index: https://cutterscrossing.com/SoundTouchJS/?path=/docs/audio-worklet-soundtouchnode--docs
- SoundTouchNode reference: https://cutterscrossing.com/SoundTouchJS/?path=/docs/audio-worklet-soundtouchnode--docs
- Interpolation strategy plugins: packages/interpolation-strategy-lanczos/README.md, packages/interpolation-strategy-linear/README.md, packages/interpolation-strategy-hann/README.md, packages/interpolation-strategy-blackman/README.md, packages/interpolation-strategy-kaiser/README.md
- Phase vocoder (time-stretch algorithm): packages/stretch-phase-vocoder/README.md
- Phase vocoder AudioWorklet: packages/phase-vocoder-worklet/README.md
- Formant correction AudioWorklet: packages/formant-correction-worklet/README.md
- Custom worklet processor base class: packages/worklet-base/README.md
- Beginner Web Audio + demo architecture guide: https://cutterscrossing.com/SoundTouchJS/?path=/docs/getting-started--docs
Quick start
AudioWorklet (recommended)
The @soundtouchjs/audio-worklet package runs processing on the audio rendering thread via AudioWorkletProcessor, replacing the deprecated ScriptProcessorNode.
import { SoundTouchNode } from '@soundtouchjs/audio-worklet';
const audioCtx = new AudioContext();
await SoundTouchNode.register(audioCtx, '/soundtouch-processor.js');
const stNode = new SoundTouchNode({ context: audioCtx });
stNode.connect(audioCtx.destination);
const source = audioCtx.createBufferSource();
source.buffer = audioBuffer;
source.connect(stNode);
// To change playback speed, set both source and stNode to the same value
source.playbackRate.value = 1.2;
stNode.playbackRate.value = 1.2;
stNode.pitch.value = 0.9;
source.start();
SoundTouchNode exposes three AudioParams: pitch, pitchSemitones, and playbackRate. Playback speed is controlled via playbackRate — see the audio-worklet README for how the mirror pattern works.
Interpolation defaults to lanczos in both core and audio-worklet flows. Strategies such as linear, hann, blackman, and kaiser must be registered before use.
See each package's README for full API documentation.
Development
Prerequisites
Setup
pnpm install
Commands
pnpm build # Build all projects
pnpm test # Run all tests
pnpm coverage:summary # Run package coverage and write consolidated report to .coverage-reports/
pnpm typecheck # Typecheck all projects
pnpm dev # Start demo dev server (Vite on port 8080)
pnpm prettier # Format all files
pnpm nx storybook storybook # Start Storybook docs server
Individual project commands via Nx:
pnpm nx build core # Build @soundtouchjs/core
pnpm nx build audio-worklet # Build @soundtouchjs/audio-worklet
pnpm nx build @soundtouchjs/interpolation-strategy-lanczos
pnpm nx build @soundtouchjs/interpolation-strategy-linear
pnpm nx build @soundtouchjs/interpolation-strategy-hann
pnpm nx build @soundtouchjs/interpolation-strategy-blackman
pnpm nx build @soundtouchjs/interpolation-strategy-kaiser
pnpm nx test core # Run core tests
pnpm nx test audio-worklet # Run audio-worklet tests
pnpm nx dev demo # Dev server with HMR
Running the demo
pnpm dev
Opens a browser at http://localhost:8080 with sliders for pitch, key, playback speed, and volume. The demo uses @soundtouchjs/audio-worklet under the hood.
For a beginner-oriented walkthrough of the signal graph, playback modes, loop behavior, and parameter cause/effect, see apps/demo/README.md.
Music: "Actionable" from Bensound.com. This is a limited use license — refer to their licensing for details.
What's changed
The latest release builds on the modernization of v0.4 with significant new features, tooling updates, and expanded package offerings:
- Storybook Enhancements: Added live processor metrics display and new playgrounds for interpolation strategies, phase vocoder, and formant correction.
- New Packages:
@soundtouchjs/formant-correction-worklet: AudioWorklet with LPC-based formant preservation.@soundtouchjs/stretch-phase-vocoder: Phase vocoder time-stretch algorithm.- Interpolation strategy plugins:
lanczos,linear,hann,blackman,kaiser.
- Offline Rendering: Enhanced
processOffline()in@soundtouchjs/audio-workletfor renderingAudioBufferwithout a live audio device. - Processor Observability: Expanded
SoundTouchNode.metricsandmetricsCustomEvent for detailed monitoring. - Tooling Updates: Pre-commit hooks now include linting; added
pnpm coverage:summaryfor consolidated coverage reports. - Licensing Update: With significant rewrites, we have now moved off of the LGPL to the MPL-2.0 — see LICENSE for details.
- Breaking Changes: Removed deprecated APIs and types in
@soundtouchjs/coreand@soundtouchjs/audio-worklet. See the respective package READMEs for migration details.
Breaking changes
If you are upgrading from an earlier version, the following APIs were removed:
@soundtouchjs/core
- Removed exports:
AbstractFifoSamplePipe(replaced byAbstractSamplePipe),FilterSupport,SimpleFilter,WebAudioBufferSource,PitchShifter,getWebAudioNode - Removed types:
SamplePipe,PlayEventDetail,SourcePositionCallback SoundTouchconstructor now takes a named options object:new SoundTouch({ sampleRate, sampleBufferType, ... })(wasnew SoundTouch())- Interpolation strategy IDs renamed:
lanczos8→lanczos,hann8→hann,blackman8→blackman,kaiser8→kaiser
@soundtouchjs/audio-worklet
SoundTouchNodeconstructor now takes a named options object with a requiredcontextproperty:new SoundTouchNode({ context: audioCtx })(wasnew SoundTouchNode(audioCtx))tempoAudioParam removed — tempo is now controlled via the source node'splaybackRatemirrored tostNode.playbackRate(see audio-worklet README for the pattern)
Contributing
Fork the repo, work in a branch, submit a Pull Request. Commits follow Conventional Commits with sentence-case subjects.
For pull requests, CI also runs pnpm coverage:summary, gates on its result, and publishes .coverage-reports/summary.md in the PR Checks job summary.
License
MPL-2.0 — see LICENSE for details.
In case you are interested
The original SoundTouch library was written in C++ by Olli Parviainen. It was first ported to JavaScript by Ryan Berdeen, then further adapted by Jakub Fiala, Adrian Holovaty, and others. This project was converted to ES2015+ and has been expanded and maintained by Steve 'Cutter' Blades.