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

webaudio-node

v0.6.1

Published

Full-featured Web Audio API for Node.js with WASM and SIMD optimizations

Downloads

35

Readme

Web Audio Node

CI codecov npm version License: ISC Node.js Version

Web Audio API for Node.js with WASM and SIMD optimizations

High-performance, browser-compatible Web Audio API for Node.js. Perfect for audio processing, sound generation, game audio, and music production.

⭐ Features

Web Audio API Support

  • Core audio nodes (Oscillator, Gain, BiquadFilter, BufferSource)
  • AudioParam automation with scheduling
  • OfflineAudioContext for fast non-realtime rendering
  • AudioContext for real-time playback
  • 5 audio formats via WASM decoders (MP3, WAV, FLAC, OGG, AAC) - see WASM Audio Decoders
  • High-quality resampling - Speex resampler with SIMD (same as Firefox uses)
  • Automatic sample rate detection - matches system audio device

🚀 High Performance

  • WASM with SIMD optimizations - beats Rust implementation in 90% of benchmarks (55/61)
  • ~2,600x faster than realtime offline rendering
  • Fast resampling - Speex quality level 1 (200-850x realtime for common sample rates)
  • Sample-accurate timing - all audio timing managed in WASM using sample counters
  • Zero JavaScript overhead in audio rendering - JS only handles I/O through SDL

🎮 Perfect for Games

  • Procedural sound effect generation
  • Mix multiple audio sources
  • Low-latency playback with SDL2

📦 Installation

npm install webaudio-node

Requirements

  • Node.js 20+
  • No build step required - uses pre-compiled WASM

🎵 CLI Usage

Play audio files directly from the command line:

# Play any supported audio file
npx webaudio-node music.mp3

# Or after global install
npm install -g webaudio-node
webaudio-node sound.wav

Supported formats: MP3, WAV, FLAC, OGG, AAC

🎤 Microphone Effects

Transform your voice in real-time with built-in effects:

# Add reverb to your microphone
webaudio-node --reverb

# Auto-tune your voice (vocoder-style effect)
webaudio-node --auto-tune

# Show all options
webaudio-node --help

Press Ctrl+C to stop the effect and close the microphone.

🚀 Quick Start

Simple Beep

import { AudioContext } from 'webaudio-node';

const ctx = new AudioContext();

// Create 440Hz oscillator
const osc = ctx.createOscillator();
osc.frequency.value = 440;
osc.connect(ctx.destination);

// Play for 1 second
await ctx.resume();
osc.start();
setTimeout(() => {
    osc.stop();
    ctx.close();
}, 1000);

Play MP3 File

import { AudioContext } from 'webaudio-node';
import { readFileSync } from 'fs';

const ctx = new AudioContext({ sampleRate: 48000 });
const audioData = readFileSync('./music.mp3');

// Decode MP3
const buffer = await ctx.decodeAudioData(audioData.buffer);

// Play
const source = ctx.createBufferSource();
source.buffer = buffer;
source.connect(ctx.destination);
source.start();

await ctx.resume();

Procedural Sound Effect (Ultra-Fast!)

import { OfflineAudioContext } from 'webaudio-node';

// Generate laser sound offline
const offlineCtx = new OfflineAudioContext({
    numberOfChannels: 2,
    length: 14400,
    sampleRate: 48000
});

const osc = offlineCtx.createOscillator();
osc.type = 'sawtooth';
osc.frequency.setValueAtTime(800, 0);
osc.frequency.exponentialRampToValueAtTime(200, 0.3);

const gain = offlineCtx.createGain();
gain.gain.setValueAtTime(0.5, 0);
gain.gain.exponentialRampToValueAtTime(0.01, 0.3);

osc.connect(gain);
gain.connect(offlineCtx.destination);
osc.start(0);

// Renders in ~1ms (14,400x faster than realtime!)
const laserBuffer = await offlineCtx.startRendering();

📚 API Reference

AudioContext

Real-time audio playback with chunk-ahead buffering.

const ctx = new AudioContext({
    sampleRate: 48000, // Default: 44100
    numberOfChannels: 2 // Default: 2 (stereo)
});

await ctx.resume(); // Start audio
await ctx.suspend(); // Pause audio
await ctx.close(); // Stop and cleanup

Note: Real-time AudioContext uses chunk-ahead buffering (1-2 second latency), which is perfect for background music and non-interactive audio.

OfflineAudioContext

Non-realtime rendering for ultra-fast audio processing.

const offlineCtx = new OfflineAudioContext({
    numberOfChannels: 2,
    length: 48000, // samples
    sampleRate: 48000
});

const buffer = await offlineCtx.startRendering();

Performance: Renders ~50,000x faster than realtime.

Audio Nodes

Source Nodes:

  • createOscillator() - Sine, square, sawtooth, triangle waveforms
  • createBufferSource() - Play audio buffers
  • createGain() - Volume control

Processing:

  • createBiquadFilter() - Lowpass, highpass, bandpass, notch filters

Supported Node Types

16/17 applicable Web Audio API nodes implemented (94% coverage)

| Node | AudioContext | OfflineAudioContext | | ---------------------- | ------------ | ------------------- | | AudioDestinationNode | ✅ | ✅ | | AudioBufferSourceNode | ✅ | ✅ | | OscillatorNode | ✅ | ✅ | | ConstantSourceNode | ✅ | ✅ | | GainNode | ✅ | ✅ | | BiquadFilterNode | ✅ | ✅ | | IIRFilterNode | ✅ | ✅ | | DelayNode | ✅ | ✅ | | WaveShaperNode | ✅ | ✅ | | ConvolverNode | ✅ | ✅ | | DynamicsCompressorNode | ✅ | ✅ | | PannerNode | ✅ | ✅ | | StereoPannerNode | ✅ | ✅ | | ChannelSplitterNode | ✅ | ✅ | | ChannelMergerNode | ✅ | ✅ | | AnalyserNode | ✅ | ✅ |

Not applicable to Node.js: MediaElement/MediaStream nodes (browser-only), ScriptProcessorNode (deprecated)

AudioParam Automation

All AudioParams support automation:

const osc = ctx.createOscillator();

// Instant change
osc.frequency.value = 880;

// Scheduled changes
osc.frequency.setValueAtTime(440, 0);
osc.frequency.linearRampToValueAtTime(880, 1.0);
osc.frequency.exponentialRampToValueAtTime(220, 2.0);

Decoding Audio Files

import { readFileSync } from 'fs';

const ctx = new AudioContext();
const audioData = readFileSync('./audio.mp3');

// Decode MP3/WAV/OGG
const buffer = await ctx.decodeAudioData(audioData.buffer);

console.log(buffer.duration); // seconds
console.log(buffer.numberOfChannels); // 1 or 2
console.log(buffer.sampleRate); // Hz

// Get audio data
const channelData = buffer.getChannelData(0);

Note: Audio decoding is currently synchronous (blocks the event loop) but very fast with WASM. Most files decode in milliseconds. For non-blocking decoding in the future, see Threading Plan.

📖 Examples

Layered Music Playback

import { AudioContext } from 'webaudio-node';
import { readFileSync } from 'fs';

const ctx = new AudioContext({ sampleRate: 48000 });
const audioData = readFileSync('./music.mp3');
const buffer = await ctx.decodeAudioData(audioData.buffer);

// Create master gain
const masterGain = ctx.createGain();
masterGain.gain.value = 0.25;
masterGain.connect(ctx.destination);

// Play 5 instances with 1-second delays
for (let i = 0; i < 5; i++) {
    const source = ctx.createBufferSource();
    source.buffer = buffer;

    const instanceGain = ctx.createGain();
    instanceGain.gain.value = 1.0;

    source.connect(instanceGain);
    instanceGain.connect(masterGain);

    const startTime = ctx.currentTime + i;
    source.start(startTime);
}

await ctx.resume();

Filtered Oscillator

import { OfflineAudioContext } from 'webaudio-node';
import { writeFileSync } from 'fs';

const ctx = new OfflineAudioContext({
    numberOfChannels: 2,
    length: 48000 * 3, // 3 seconds
    sampleRate: 48000
});

// Create filtered sawtooth
const osc = ctx.createOscillator();
osc.type = 'sawtooth';
osc.frequency.value = 110; // A2

const filter = ctx.createBiquadFilter();
filter.type = 'lowpass';
filter.frequency.value = 2000;
filter.Q.value = 5;

// Sweep filter
filter.frequency.setValueAtTime(200, 0);
filter.frequency.exponentialRampToValueAtTime(8000, 3);

const gain = ctx.createGain();
gain.gain.value = 0.3;

osc.connect(filter);
filter.connect(gain);
gain.connect(ctx.destination);
osc.start(0);

const rendered = await ctx.startRendering();
// Write to file...

Game Sound Effects Generator

import { OfflineAudioContext } from 'webaudio-node';

async function generateLaserSound() {
    const ctx = new OfflineAudioContext({
        numberOfChannels: 2,
        length: 14400,
        sampleRate: 48000
    });

    const osc = ctx.createOscillator();
    osc.type = 'sawtooth';
    osc.frequency.setValueAtTime(600 + Math.random() * 400, 0);
    osc.frequency.exponentialRampToValueAtTime(100 + Math.random() * 200, 0.3);

    const gain = ctx.createGain();
    gain.gain.setValueAtTime(0.3, 0);
    gain.gain.exponentialRampToValueAtTime(0.01, 0.3);

    osc.connect(gain);
    gain.connect(ctx.destination);
    osc.start(0);

    return await ctx.startRendering();
}

// Generate 100 variations in ~100ms
const sounds = await Promise.all(
    Array(100)
        .fill(0)
        .map(() => generateLaserSound())
);

⚡ Performance

webaudio-node delivers excellent performance for audio workloads. See detailed benchmarks for comprehensive comparisons.

Offline Rendering Speed:

| Duration | Render Time | Speed vs Realtime | | -------- | ----------- | ----------------- | | 1s | ~0.38ms | ~2,600x | | 5s | ~1.9ms | ~2,600x | | 10s | ~3.8ms | ~2,600x |

Why so fast? WASM with SIMD optimizations processes 4 audio samples in parallel.

🏗️ Architecture

WASM Backend

Audio graph rendering uses WebAssembly compiled from optimized C++:

┌─────────────────┐
│  JavaScript API │  (Node creation, connections, I/O via SDL)
└────────┬────────┘
         │
┌────────▼────────┐
│  WASM Engine    │  (Graph rendering, SIMD mixing, timing)
│                 │  • Sample-accurate timing with current_sample counters
│                 │  • All scheduling handled in WASM
│                 │  • Unified binary: graph + nodes + decoders
└────────┬────────┘
         │
┌────────▼────────┐
│  SDL2 Output    │  (Audio device via @kmamal/sdl)
└─────────────────┘

Key features:

  • Single unified WASM binary (dist/webaudio.wasm) contains all audio processing
  • All audio timing managed in WASM using sample-accurate current_sample counters
  • JavaScript only handles I/O through SDL - no timing logic in JS
  • SIMD optimizations (4-8x parallel processing)
  • Proper gain node mixing - all inputs mixed together per Web Audio spec
  • Sample-accurate BufferSourceNode scheduling

See docs/architecture.md for architectural details.

🔧 Development

Building from Source

WASM modules are pre-compiled and included in the npm package. To rebuild from source:

# Install Emscripten SDK
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh

# Build WASM (includes all audio decoders)
cd webaudio-node
npm run build:wasm

Available Scripts

# Testing
npm test                 # Run test suite
npm run test:coverage    # Run tests with coverage report

# Linting & Formatting
npm run lint            # Check code style
npm run lint:fix        # Auto-fix linting issues
npm run format          # Format code with Prettier
npm run format:check    # Check formatting

# Benchmarks
npm run benchmark       # Run performance benchmarks
npm run benchmark:docs  # Generate benchmark documentation

🧪 Testing

Comprehensive Web Audio API test suite:

npm test

Tests cover:

  • All audio nodes
  • AudioParam automation
  • Audio graph connections
  • Rendering accuracy
  • Stereo/mono support

Test results: 61/61 tests passing ✅

📁 Project Structure

webaudio-node/
├── src/
│   ├── wasm/              # C++ source for WASM
│   ├── wasm-integration/  # WASM wrapper classes
│   └── javascript/        # JavaScript nodes & AudioParam
├── test/
│   ├── api-suite.js       # Comprehensive API tests
│   └── samples/           # Test audio files
├── docs/
│   └── threading.md       # Architecture documentation
└── scripts/
    └── build-wasm.mjs     # WASM build script

🖥️ Platform Support

| Platform | Status | Notes | | -------------- | ------ | ------------------ | | macOS ARM64 | ✅ | SIMD optimizations | | macOS x86-64 | ✅ | SIMD optimizations | | Linux ARM64 | ✅ | SIMD optimizations | | Linux x86-64 | ✅ | SIMD optimizations | | Windows x86-64 | ✅ | Requires SDL2 |

🔄 Comparison with Other Libraries

vs node-web-audio-api (Rust)

node-web-audio-api is an excellent, well-maintained Rust implementation. Both libraries offer high-performance audio processing for Node.js.

Key differences:

  • Performance: webaudio-node is faster overall in most workloads (90% win rate - see detailed benchmarks)
  • Resampling: Speex quality 1 (fast, good quality) vs advanced resampling
  • Node Coverage: 16/17 applicable nodes (94%) implemented
  • Installation: Pre-compiled WASM (no build toolchain required)

Both libraries are production-ready - choose based on your specific needs!

vs web-audio-engine

  • ✅ Much faster (WASM vs pure JS)
  • ✅ Better Web Audio API compliance
  • ✅ Real-time playback support
  • ✅ Comprehensive node coverage

🛣️ Roadmap

Current: 94% Web Audio API compliance with WASM backend

Future:

  • Worker Thread rendering for lower latency
  • AudioWorklet support
  • Additional WebCodecs integration

See docs/threading.md for Worker Thread implementation plan.

📜 License

MIT License - see LICENSE

🙏 Credits


Made with ❤️ for game developers, music producers, and audio enthusiasts

🎮 🎵 🔊