jaudiojs is a JavaScript/Node.js library for beat making, sound synthesis, mixing, mastering, and processing existing audio files. It ships with drum machines, step sequencers, melodic synths, samplers, a vocal-mixing chain, a one-call full-beat builder, and MIDI import — all through a simple, consistent, fully synchronous API and with zero required dependencies.
It is a faithful JavaScript port of the Python jaudiopy library: every class and function shape mirrors the Python original (renamed to normal JS camelCase conventions), so anything you already know from jaudiopy transfers mechanically to jaudiojs.
const { AudioFile, BeatBuilder } = require('jaudiojs');
// One-call full beat
const bb = new BeatBuilder({ style: 'trap_808', bpm: 140, key: 'E' });
bb.buildAndSave('my_beat.wav', { durationMinutes: 2.5 });
// Process an existing audio file
const song = AudioFile.load('song.wav');
song.addEffect('reverb', 'song_reverb.wav', { roomSize: 0.7, mix: 0.4 });Every call in jaudiojs — including loading audio from a URL — is synchronous, exactly like the Python original. No async/await anywhere in this library.
· Synthesis – sineWave, squareWave, sawWave, triangleWave, ADSR envelopes (envelopeAdsr, applyEnvelope), and note-name-to-frequency resolution (noteFreq).
· Drum Machine – drums ships kick (including 808/sub/acoustic/punchy variants), snare, hi-hat (closed/open/trap/pedal), rimshot, ride, crash, clap, tom, cowbell, shaker, tambourine, conga, clave, woodblock, and triangle — each independently tunable.
· Melodic Instruments – bassSynth, pluckSynth, padSynth, pianoSynth, and a glide-enabled bass808Line for trap-style 808 basslines.
· Sequencing & Arrangement – StepSequencer and MelodySequencer render X/x/. pattern strings (with swing) into audio; Song arranges sections into a full track.
· Mixing – Mixer and AdvancedMixer with Track/Bus support volume, pan, mute, and solo across many simultaneous tracks.
· Effects Rack – filters (lowpass/highpass/EQ band/shelves), distortion, bitcrush, delay, reverb, chorus, tremolo, vibrato, phaser, autopan, wah, exciter, saturation, compressor, limiter, noise gate, de-esser, sidechain ducking, Haas stereo widening, and a loudness maximizer — all in effects.
· Mastering – masterChain, masterChainAdvanced, and masterWithPreset (with MASTER_PRESETS like balanced, warm, bright, loud_edm, vocal_pop) turn a raw stereo mix into a finished master in one call.
· Beat Builder – BeatBuilder generates a complete, styled beat (drums, bass, chords, arrangement) from a handful of options; buildMany renders several specs in parallel across real OS processes.
· Audio File I/O – AudioFile, saveWavMono/saveWavStereo, loadWav, and loadAudio read/write 16-bit PCM WAV natively, with optional ffmpeg support for other formats and optional curl/PowerShell support for loading from http(s):// URLs.
· Sampler & Vocals – Sampler for pitch-shifted playback and chopping of loaded samples; vocalChain and mixVocalWithBeat for mixing vocals over an instrumental.
· MIDI Import – loadMidiNotes reads tempo and note on/off events from a MIDI file with a small built-in parser (no external MIDI dependency).
· Bit-Identical RNG with Python – seedRandom/Random is a direct port of CPython's MT19937, so seeded noise generation produces the exact same output in both languages.
· Local Playback – playBuffer/playStereo try the optional speaker package first, then fall back to a system audio tool (afplay/paplay/aplay/ffplay/PowerShell).
npm install jaudiojsThe core library (local files, synthesis, effects, mixing, mastering, the beat builder) has zero required dependencies. Two optional pieces unlock extra features, exactly like jaudiopy's own optional dependencies:
ffmpegonPATH— for reading/writing non-WAV formats (mp3/ogg/flac/...).curlonPATH(or PowerShell on Windows) — for loading audio from anhttp(s)://URL. Local files and in-memory bytes never need this.speaker(optional peer dependency) — for native local playback viaplayBuffer/playStereo; without it, playback falls back to a system tool.
Without them you still get the full library minus those specific features — you'll get a clear error naming what to install only if you actually hit a non-WAV file, a URL, or playback with no system tool available.
const { drums, StepSequencer } = require('jaudiojs');
const kit = drums.buildKit({
K: ['kick', '808'],
S: ['snare', 'fat'],
H: ['hihat', 'trap'],
});
const seq = new StepSequencer({ bpm: 140 });
const track = seq.renderKit(
{ K: 'X...x...X...x...', S: '....X.......X...', H: 'X.X.X.X.X.X.X.X.' },
{
K: { X: kit.K, x: [kit.K, 0.5] },
S: { X: kit.S },
H: { X: kit.H, x: [kit.H, 0.4] },
},
);const { Sampler } = require('jaudiojs');
const sampler = Sampler.load('piano_note_C4.wav', { baseNote: 'C', baseOctave: 4 });
const note = sampler.playNote('D#', 4, 1.0);
const loop = sampler.loopTo(8.0);
const chops = sampler.chop(8);const { mixVocalWithBeat } = require('jaudiojs');
const [finalLeft, finalRight] = mixVocalWithBeat(beatLeft, beatRight, vocalBuffer, { vocalAt: 8.0 });const { masterWithPreset } = require('jaudiojs');
const [left, right] = masterWithPreset(rawLeft, rawRight, {
preset: 'loud_edm', targetCrestDb: 7.0, haasMix: 0.4,
});const { listStyles, listProgressions } = require('jaudiojs');
console.log(listStyles());
console.log(listProgressions());examples/ contains four full, runnable beats:
| File | What it builds |
|---|---|
examples/1/heavyGangstaBassBeatExample.js |
A hand-built 1-minute dark trap/gangsta beat — full library walkthrough (drums, drone, stab, 808, sidechain, bus mixing, mastering-preset reasoning, seamless loop crossfading). |
examples/2/melancholicBeatExample.js |
An 85 BPM piano beat with sidechained chords. |
examples/3/beatbuilderExample.js |
The one-call BeatBuilder shortcut. |
examples/4/trap808BeatExample.js |
A hihat-roll-heavy 140 BPM trap beat with a glide 808 bass. |
Run any of them with:
node examples/1/heavyGangstaBassBeatExample.jsor via the matching npm script (npm run example:1, example:2, example:3, example:4).
JavaScript has no keyword-argument syntax, so fn(x, freq=800, q=0.9) from Python becomes a trailing options object in jaudiojs: fn(x, { freq: 800, q: 0.9 }). A few other mechanical rules carry over the same way:
- Python
snake_case→ JScamelCasefor every function, method, and variable name. - Python
PascalCaseclasses stayPascalCase(AudioBuffer,StepSequencer,AdvancedMixer,BeatBuilder, ...). - A Python function returning a
tuple(e.g.(left, right)) returns a JS array you destructure the same way:const [left, right] = .... len(buf)/buf.samples→buf.length/buf.samples(aFloat64Array).buf.to_list()→buf.toArray().
Everything else — RNG, buildMany parallelism, and every I/O call being synchronous — is a bit-for-bit or behavior-for-behavior match with the Python original.
npm testBug reports and feature requests are welcome via GitHub Issues. Pull requests should maintain the existing code style and include tests where appropriate.
· Original Python library (jaudiopy): https://github.com/JCode-JCode/jaudiopy
· GitHub repository (jaudiojs):
· npm page: https://www.npmjs.com/package/jaudiojs
This project is licensed under the Apache License 2.0 – see the LICENSE file for details.
Designed and built with love by J Code
