Skip to content

Latest commit

 

History

History
112 lines (78 loc) · 4.24 KB

File metadata and controls

112 lines (78 loc) · 4.24 KB

@soundtouchjs/core

Core audio processing library for real-time pitch shifting, tempo adjustment, and rate transposition using the Web Audio API. A TypeScript rewrite of the SoundTouch audio processing library.

Installation

npm install @soundtouchjs/core

Usage

PitchShifter (ScriptProcessorNode)

The simplest way to get started. PitchShifter wraps a ScriptProcessorNode and handles buffering, playback tracking, and parameter control.

import { PitchShifter } from '@soundtouchjs/core';

const audioCtx = new AudioContext();
const gainNode = audioCtx.createGain();
gainNode.connect(audioCtx.destination);

const response = await fetch('/audio.mp3');
const buffer = await response.arrayBuffer();
const audioBuffer = await audioCtx.decodeAudioData(buffer);

const shifter = new PitchShifter(audioCtx, audioBuffer, 16384);
shifter.tempo = 1.2;
shifter.pitch = 0.9;
shifter.pitchSemitones = -2;

shifter.on('play', (detail) => {
  console.log(detail.formattedTimePlayed); // "1:23"
  console.log(detail.percentagePlayed); // 42.5
});

// Connect to start playback
shifter.connect(gainNode);

// Disconnect to pause
shifter.disconnect();

Note: ScriptProcessorNode is deprecated in the Web Audio spec. For new projects, consider using @soundtouchjs/audio-worklet which provides an AudioWorklet-based implementation.

Low-level API

All internal components are exported for advanced use cases:

import {
  SoundTouch,
  SimpleFilter,
  WebAudioBufferSource,
  FifoSampleBuffer,
} from '@soundtouchjs/core';

const st = new SoundTouch();
st.pitch = 1.5;
st.tempo = 0.8;

const source = new WebAudioBufferSource(audioBuffer);
const filter = new SimpleFilter(source, st);

// Pull processed samples
const outputBuffer = new Float32Array(4096);
const framesRead = filter.extract(outputBuffer, 2048);

Key classes

Export Description
SoundTouch Main processing engine — set pitch, tempo, rate, or pitchSemitones
PitchShifter High-level wrapper using ScriptProcessorNode with playback events
SimpleFilter Pulls samples through a SoundTouch pipe from a source
WebAudioBufferSource Adapter from AudioBuffer to the internal sample source interface
FifoSampleBuffer Resizable interleaved sample buffer (ES2024 ArrayBuffer)
getWebAudioNode Creates a ScriptProcessorNode wired to a SimpleFilter
Stretch Time-stretch processor (used internally by SoundTouch)
RateTransposer Sample rate transposer (used internally by SoundTouch)

What's changed in v0.4

  • Monorepo: Now published as @soundtouchjs/core from an Nx monorepo (was soundtouchjs)
  • TypeScript: Full rewrite — strict mode, zero any, complete type exports
  • ESM only: Pure ES modules targeting ES2024 (import/export, no CommonJS)
  • ES2024 buffers: FifoSampleBuffer uses resizable ArrayBuffer for zero-allocation growth
  • Optimized internals: Scratch buffer reuse in SimpleFilter, dirty-flag overlap buffers in Stretch
  • Zero runtime dependencies

License

LGPL-2.1 — see LICENSE for details.

Key switching and pitch control

Changing the musical key of playback is handled by the pitchSemitones parameter. Each integer step corresponds to one semitone (half-step) on the chromatic scale. For example:

  • pitchSemitones = 2 shifts the key up a whole step
  • pitchSemitones = -3 shifts down a minor third

The effective pitch is calculated as:

pitch * 2^(pitchSemitones / 12)

This lets you combine continuous pitch control (pitch) with discrete key changes (pitchSemitones).

For most musical applications, set pitchSemitones to the desired interval and leave pitch at 1.0 unless you want fine-tuning within a semitone.

See @soundtouchjs/audio-worklet for AudioWorklet-based usage.