npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@soundtouchjs/phase-vocoder-worklet

v2.0.3

Published

AudioWorklet integration for the SoundTouchJS phase vocoder time-stretch algorithm

Readme

@soundtouchjs/phase-vocoder-worklet

An AudioWorklet integration that uses the phase vocoder time-stretch algorithm from @soundtouchjs/stretch-phase-vocoder. Provides PhaseVocoderNode as a drop-in replacement for SoundTouchNode when smoother time-stretching at extreme ratios is required.

I accept cash if you like what's been done.

Part of the SoundTouchJS monorepo — for more information and so much more.

Installation

npm install @soundtouchjs/phase-vocoder-worklet @soundtouchjs/stretch-phase-vocoder

When to use this package

  • Playback at extreme ratios (< 0.5× or > 2×) where the default WSOLA algorithm produces audible artifacts.
  • Smooth slow-motion or fast-forward effects where "phasiness" is acceptable.
  • You want the same AudioWorkletNode API as SoundTouchNode with a different internal stretch algorithm.

For moderate ratios (0.5–2×) the default @soundtouchjs/audio-worklet typically sounds better.

Setup

Resolving processorUrl

Vite

import processorUrl from '@soundtouchjs/phase-vocoder-worklet/processor?url';

webpack 5

const processorUrl = new URL(
  '@soundtouchjs/phase-vocoder-worklet/processor',
  import.meta.url,
).href;

Static / CDN

Copy .dist/phase-vocoder-processor.js to your public directory and reference it by path:

const processorUrl = '/phase-vocoder-processor.js';

Usage

import { PhaseVocoderNode } from '@soundtouchjs/phase-vocoder-worklet';

const audioCtx = new AudioContext();
await PhaseVocoderNode.register(audioCtx, processorUrl);

const node = new PhaseVocoderNode({
  context: audioCtx,
  fftSize: 2048,      // optional, default 2048
  overlapFactor: 4,   // optional, default 4
});

node.pitch.value = 1.5;        // pitch up 50 %
node.pitchSemitones.value = 3; // or shift by semitones
node.playbackRate.value = 0.5; // slow down 2×

node.connect(audioCtx.destination);

// Connect your source:
sourceNode.connect(node);

Offline processing

Use processOffline() when you want the same phase-vocoder pipeline in an OfflineAudioContext (no live audio device needed):

import { processOffline } from '@soundtouchjs/phase-vocoder-worklet';

const processed = await processOffline({
  input: audioBuffer,
  processorUrl,
  playbackRate: 0.5,
  pitchSemitones: 3,
  fftSize: 1024,
  overlapFactor: 8,
});

API

Top-level exports:

| Export | Description | |--------|-------------| | PhaseVocoderNode | Main-thread AudioWorkletNode wrapper | | PROCESSOR_NAME | Processor registration id | | processOffline(options) | Offline rendering helper using PhaseVocoderNode |

PhaseVocoderNode

Extends AudioWorkletNode. Same API as SoundTouchNode with additional fftSize / overlapFactor options.

Static methods

| Method | Description | |--------|-------------| | PhaseVocoderNode.register(context, processorUrl) | Registers the processor module. Must be called before constructing nodes. | | PhaseVocoderNode.registerStrategyModule(context, moduleUrl) | Loads an interpolation strategy plugin into worklet scope. | | PhaseVocoderNode.processorName | The registered processor identifier string. |

Constructor options

| Option | Type | Default | Description | |--------|------|---------|-------------| | context | BaseAudioContext | required | AudioContext or OfflineAudioContext | | fftSize | 512 \| 1024 \| 2048 \| 4096 | 2048 | FFT frame size — larger = better frequency resolution, higher latency | | overlapFactor | 2 \| 4 \| 8 | 4 | Overlap factor — higher = smoother output, more computation | | outputChannelCount | 1 \| 2 | 2 | Output channel count (set to 1 for mono destinations) | | sampleBufferType | 'circular' \| 'fifo' | 'circular' | Internal buffer strategy | | interpolationStrategy | RateTransposerInterpolationStrategy | 'lanczos' | Initial rate-transposer interpolation strategy |

AudioParams

| Param | Default | Range | Description | |-------|---------|-------|-------------| | pitch | 1.0 | 0.1–8.0 | Pitch multiplier (k-rate) | | pitchSemitones | 0 | -24–24 | Pitch shift in semitones, combined with pitch (k-rate) | | playbackRate | 1.0 | 0.1–8.0 | Playback rate multiplier — set this to match the source node's playbackRate (k-rate) |

Methods

| Method | Description | |--------|-------------| | setInterpolationStrategy(strategy) | Switches interpolation strategy at runtime. | | setInterpolationStrategyParams(params) | Updates parameters for the active strategy. | | setStretchParameters(params) | No-op for the phase vocoder (accepted for API parity with SoundTouchNode). |

Processor observability

The processor posts metrics every 100 render blocks. Access them via the metrics getter or the metrics CustomEvent:

// Getter
const m = node.metrics; // ProcessorMetrics | null

// Event
node.addEventListener('metrics', (e) => {
  const { framesBuffered, underrunCount, blockCount } = (e as CustomEvent<ProcessorMetrics>).detail;
  console.log('underruns:', underrunCount);
});

ProcessorMetrics shape:

| Field | Description | |-------|-------------| | framesBuffered | Output frames available at the last render block | | underrunCount | Cumulative render blocks with fewer output frames than requested | | blockCount | Total render blocks processed | | timestamp | performance.now() when the metrics arrived on the main thread |

Trade-offs vs SoundTouchNode

| | SoundTouchNode (WSOLA) | PhaseVocoderNode | |--|--|--| | Quality at extreme ratios | Artifacts above 2× | Smooth at all ratios | | Transient preservation | Better (time-domain) | Worse (frequency smearing) | | Computation | Lower | Higher (FFT per hop) | | Startup latency | Lower | fftSize samples | | Artifacts | Clicks / repeats | "Phasiness" / smearing |

License

MPL-2.0 — see LICENSE for details.