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:

PackagenpmDescription
@soundtouchjs/corenpm install @soundtouchjs/coreCore processing library — SoundTouch, buffers, and the interpolation registry
@soundtouchjs/audio-workletnpm install @soundtouchjs/audio-workletAudioWorklet implementation with AudioParam-based controls, offline rendering, and processor metrics
@soundtouchjs/stretch-phase-vocodernpm install @soundtouchjs/stretch-phase-vocoderPhase vocoder time-stretch algorithm — implements StretchPipe, usable standalone or as a SoundTouch stretch stage
@soundtouchjs/phase-vocoder-workletnpm install @soundtouchjs/phase-vocoder-workletAudioWorklet implementation using the phase vocoder for smoother extreme-ratio time-stretching
@soundtouchjs/formant-correction-workletnpm install @soundtouchjs/formant-correction-workletAudioWorklet implementation with LPC-based formant preservation for natural-sounding vocal pitch shifts
@soundtouchjs/worklet-basenpm install @soundtouchjs/worklet-baseAbstract base class for building custom AudioWorklet processors on top of the SoundTouch engine
@soundtouchjs/interpolation-strategy-lanczosnpm install @soundtouchjs/interpolation-strategy-lanczosLanczos interpolation strategy plugin (default strategy id: lanczos)
@soundtouchjs/interpolation-strategy-linearnpm install @soundtouchjs/interpolation-strategy-linearLinear interpolation strategy plugin (strategy id: linear)
@soundtouchjs/interpolation-strategy-hannnpm install @soundtouchjs/interpolation-strategy-hannHann interpolation strategy plugin (strategy id: hann)
@soundtouchjs/interpolation-strategy-blackmannpm install @soundtouchjs/interpolation-strategy-blackmanBlackman interpolation strategy plugin (strategy id: blackman)
@soundtouchjs/interpolation-strategy-kaisernpm install @soundtouchjs/interpolation-strategy-kaiserKaiser 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

Quick start

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-worklet for rendering AudioBuffer without a live audio device.
  • Processor Observability: Expanded SoundTouchNode.metrics and metrics CustomEvent for detailed monitoring.
  • Tooling Updates: Pre-commit hooks now include linting; added pnpm coverage:summary for 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/core and @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 by AbstractSamplePipe), FilterSupport, SimpleFilter, WebAudioBufferSource, PitchShifter, getWebAudioNode
  • Removed types: SamplePipe, PlayEventDetail, SourcePositionCallback
  • SoundTouch constructor now takes a named options object: new SoundTouch({ sampleRate, sampleBufferType, ... }) (was new SoundTouch())
  • Interpolation strategy IDs renamed: lanczos8lanczos, hann8hann, blackman8blackman, kaiser8kaiser

@soundtouchjs/audio-worklet

  • SoundTouchNode constructor now takes a named options object with a required context property: new SoundTouchNode({ context: audioCtx }) (was new SoundTouchNode(audioCtx))
  • tempo AudioParam removed — tempo is now controlled via the source node's playbackRate mirrored to stNode.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.

Contributors