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

bellowsjs

v0.1.7

Published

A browser-native audio engine for synthesis, samples, sequencing, analysis, and I/O. One clock, one kernel, seeded everywhere.

Readme

bellowsjs

A browser-native audio engine for synthesis, samples, sequencing, analysis, and I/O. One clock, one DSP kernel in an AudioWorklet, and a layered API that goes from one line of code down to raw sample-loop DSP. Every random decision is seeded and reproducible: same seed, same piece, forever.

The name: a bellows is the air mover of the forge. Every forge needs one.

import { play } from 'bellowsjs';
play('pluck', 'C4');

Why

The Web Audio API is a good set of parts and a bad instrument. A browser music project of any ambition ends up stitching together five or six packages that do not share a clock, a random source, or an AudioContext. BELLOWS collapses that stack into one engine designed from the kernel up:

  • Timing lives on the audio thread. Musical logic compiles to timestamped events; the kernel splits its render blocks at event boundaries, so notes land sample-accurately no matter how busy the main thread is.
  • No garbage at note rate. Voices are pooled and reused inside the kernel. Steady-state playback allocates nothing on the audio path.
  • Offline is realtime. The same kernel renders live through the worklet and offline through a plain loop, driven by the same message stream. Renders are deterministic enough to diff against golden references in CI, on Node, with no browser.
  • Musical types are first class. Notes, degrees, chords, scales, tunings, bars, and swing are library types with exact semantics, including under tempo curves (beat-to-seconds over a bpm ramp is a closed-form integral, not an approximation).
  • 12-EDO is a default, never an assumption. Pitch flows through a tuning layer: any EDO, just intonation ratios, cents tables, Scala .scl/.kbm import.
  • Seeded everywhere. Every stochastic choice flows from named, forkable PRNG streams. Nothing in the library calls Math.random.

Install

npm install bellowsjs

Or from a CDN in a plain HTML page, no build step:

<script type="module">
  import { play } from 'https://unpkg.com/bellowsjs/dist/bellows.js';
  document.querySelector('#go').onclick = () => play('kick', 'C2');
</script>

The AudioWorklet kernel ships inlined and loads through a blob URL, so there is no second file to deploy. Hosts whose CSP blocks blob: scripts can point the loader at the packaged bellowsjs/worklet.js instead.

Three tiers

Tier 1, immediate:

import { play, instrument } from 'bellowsjs';

play('pluck', 'C4');

const piano = await instrument('sf2:./fonts/gm.sf2#0:0');
piano.note('E3', { dur: '8n', vel: 0.7 });

Tier 2, the workbench:

import { Bellows } from 'bellowsjs';

const b = await Bellows.boot({ seed: 'forge-01' });

const lead = b.voice('fm', { algorithm: 3, feedback: 0.4 });
const bass = b.voice('va', { shape: 1, cutoff: 400, resonance: 0.5 });

const verb = b.bus(['fdn'], { level: 0.4 });
lead.fx('tapeDelay').send(verb, 0.5);

const scale = b.scale('D dorian');
const rhythm = b.euclid(16, 7, 2);
const melody = b.rng('melody');

b.clock.at('16n', (t, step) => {
  if (rhythm[step % 16]) {
    lead.note(scale.degreeToMidi(melody.int(7), 4), { at: t, dur: '16n' });
  }
  if (step % 4 === 0) {
    bass.note(scale.degreeToMidi(0, 2), { at: t, dur: '8n' });
  }
});

b.rampBpm(96, '8m');
b.start();

Tier 3, the kernel. Custom engines and effects implement small contracts and become addressable by id like the built-ins, in realtime and offline both:

b.defEffect({
  id: 'crush',
  label: 'bitcrusher',
  params: [{ name: 'bits', min: 1, max: 16, default: 8 }],
  create(sampleRate, params) {
    let bits = params.bits ?? 8;
    return {
      process(l, r, from, to) {
        const q = Math.pow(2, bits - 1);
        for (let i = from; i < to; i++) {
          l[i] = Math.round(l[i] * q) / q;
          r[i] = Math.round(r[i] * q) / q;
        }
      },
      setParam(name, value) { if (name === 'bits') bits = value; },
      reset() {},
    };
  },
});

Offline is the same graph:

const audio = await b.render({ bars: 16 });
const wav = audio.wav(24); // ArrayBuffer, ready to download

What ships

Synthesis: virtual analog (tabulated-BLEP oscillators, worst alias measured at -85 dB through the musical range and -73 dB at the top of the band, ladder and SVF filters, per-voice drift), FM (2/4/6 operators, DX-style algorithm routing), additive, wavetable (mipmapped, position scan), granular (64-grain clouds), extended Karplus-Strong, waveguide string and tube, modal banks (bar, membrane, bell, glass, wood), west coast (wavefolder into a vactrol low-pass gate), formant vocal synthesis, five drum engines, noise synth, and a DDSP-style harmonic-plus-noise engine with a frame-driven control input.

Samples: a sampler engine with velocity layers, crossfades, round robins, and loop-seam crossfading; an SF2 parser implementing the generator resolution model of the spec; an SFZ parser covering the opcodes the popular free libraries actually use, with #include and #define.

Theory and tuning: thirty plus scales, chord parsing and detection, roman numerals in both directions, nearest-motion voice leading, negative harmony, seeded functional-harmony progressions; tunings as objects (EDO, just intonation, cents, Scala import).

Sequencing: a transport with exact tempo-curve integration, meter changes, and swing; Euclidean patterns (true Bjorklund), Markov chains of any order with chord-tone gravity, L-systems, elementary cellular automata, arpeggiators, and a small step-indexed pattern combinator layer.

Effects: clean/tape/multitap delays, an 8-line FDN reverb (Householder feedback, modulated coprime lines), the Dattorro plate with the 1997 constants, compressor with lookahead and program-dependent release, true-peak limiter, gate, transient shaper, 6-band parametric EQ, saturator with 4x oversampling, chorus, flanger, phaser, tremolo, autopan, ring mod, Hilbert-pair frequency shifter, and a spectral suite (phase-vocoder pitch shift with identity phase locking, freeze, blur, robot, whisper, denoise, offline time stretch).

Analysis: YIN and MPM pitch detection, spectral-flux onset detection, tempo estimation, chroma and key estimation, spectral descriptors, MFCC, and an EBU R128 loudness meter (momentary, short-term, gated integrated, LRA, 4x oversampled true peak) with K-weighting derived per sample rate.

I/O: WAV encode/decode at 8/16/24/32 bits, standard MIDI file read/write, Web MIDI with MPE zones where the platform has it, WebCodecs Opus export where available, WAV everywhere.

Determinism and testing

The DSP core has zero browser dependencies, which is why the library carries more than a thousand behavioral tests that run in plain Node: filters are tested by measured frequency response, oscillators by measured alias suppression, reverbs by decay time, the loudness meter against the BS.1770 reference points, and whole pieces by golden-render comparison. renderOffline produces the same output on every run of the same seed.

Browser support

AudioWorklet is required (Chrome 66+, Firefox 76+, Safari 14.1+). Web MIDI is Chromium and Firefox only. WebCodecs Opus export is feature-detected with WAV as the universal fallback. See docs/ENGINEERING.md in the repository for the full capability matrix.

Development

git clone https://github.com/virgilvox/bellowsjs
cd bellowsjs
npm install
npm test              # library test suite
npm run dev           # the workbench app (Vue), live against library source
npm run build         # library build including the worklet bundle

The workbench app doubles as the documentation: a generative bench showing every engine swappable mid-piece, and a code mode with about thirty runnable, editable examples covering the entire API.

License

Apache-2.0. See LICENSE.