iblokz-audio
v0.1.0
Published
Web Audio API utilities and engine for building reactive audio applications
Maintainers
Readme
iblokz-audio
A lightweight, functional JavaScript library providing Web Audio API utilities for building reactive audio applications, synthesizers, and audio engines.
Part of the iblokz family of functional utilities, designed to work seamlessly with iblokz-state for reactive audio applications.
Features
- 🎹 Synthesizer Components - VCO (oscillator), VCA (amplifier), VCF (filter), ADSR envelope
- 🎛️ Audio Effects - LFO (low-frequency oscillator), Reverb
- 🎵 Sample Playback - Sampler for audio file playback
- 🔗 Node Management - Connect, disconnect, chain, and reroute audio nodes
- 🎼 Musical Utilities - Note-to-frequency conversion
- 🔒 Functional API - Clean, functional programming patterns
- 📦 Zero Dependencies - No runtime dependencies, pure Web Audio API
- 📦 ESM-first - Modern ES modules with CommonJS build for compatibility
- ✅ Well-tested - Comprehensive test coverage (coming soon)
Installation
Requirements: Node.js ≥ 18.12.0
npm install iblokz-audio
# or
pnpm install iblokz-audioUsage
This library is published as ESM-first with a CommonJS build for compatibility.
ESM (Recommended)
import * as a from 'iblokz-audio';
// or
import {vco, vca, adsr, connect, start, noteOn, noteOff} from 'iblokz-audio';CommonJS (Node.js compatibility)
const a = require('iblokz-audio');Basic Example
import {vco, vca, adsr, connect, start, noteOn, noteOff, context} from 'iblokz-audio';
// Create a simple oscillator
const vco = a.vco({ type: 'sine', freq: 440 });
const vca = a.vca({ gain: 0.5 });
const adsr = a.adsr({ attack: 0.1, release: 0.2 });
// Connect nodes: vco -> adsr -> vca -> destination
connect(vco, adsr);
connect(adsr, vca);
connect(vca, context.destination);
// Start the oscillator
start(vco);
// Trigger note on/off
noteOn(adsr, 0.7); // velocity 0.7
setTimeout(() => noteOff(adsr), 500);Creating a Synthesizer Voice
import {vco, vcf, adsr, vca, connect, start, noteOn, noteOff, update, noteToFrequency, context} from 'iblokz-audio';
// Create a complete voice with filter and effects
const voice = {
vco1: vco({ type: 'sawtooth', freq: 440 }),
vco2: vco({ type: 'square', freq: 440, detune: 7 }),
vcf: vcf({ type: 'lowpass', cutoff: 0.5, resonance: 0.3 }),
adsr1: adsr({ attack: 0.1, decay: 0.2, sustain: 0.7, release: 0.3 }),
adsr2: adsr({ attack: 0.1, decay: 0.2, sustain: 0.7, release: 0.3 }),
vca: vca({ gain: 0.3 })
};
// Connect: VCOs -> ADSRs -> VCF -> VCA -> destination
connect(voice.vco1, voice.adsr1);
connect(voice.vco2, voice.adsr2);
connect(voice.adsr1, voice.vcf);
connect(voice.adsr2, voice.vcf);
connect(voice.vcf, voice.vca);
connect(voice.vca, context.destination);
// Play a note
const note = 'C4';
const freq = noteToFrequency(note);
update(voice.vco1, { freq });
update(voice.vco2, { freq });
start(voice.vco1);
start(voice.vco2);
noteOn(voice.adsr1, 0.8);
noteOn(voice.adsr2, 0.8);Using Effects
import {create, lfo, vco, connect, start, context} from 'iblokz-audio';
// Create reverb effect
const reverb = create('reverb', {
seconds: 3,
decay: 2,
wet: 0.3,
dry: 0.7
});
// Create LFO for modulation
const lfoNode = lfo({
type: 'sine',
frequency: 2, // 2 Hz
gain: 10
});
// Connect source -> reverb -> destination
const osc = vco({ type: 'sine', freq: 440 });
connect(osc, reverb.input);
connect(reverb.output, context.destination);
// Start LFO and connect to modulate filter cutoff
start(lfoNode);
// lfoNode.output can be connected to modulate other parametersSample Playback
import {connect, start, context, sampler} from 'iblokz-audio';
// Create a sampler instance
const sample = sampler.create('/path/to/sample.wav', null, { gain: 0.8 });
// When buffer is loaded, play it
sample.source.buffer.then(() => {
connect(sample, context.destination);
start(sample.source);
});
// Clone for polyphonic playback
const clone = sampler.clone(sample, { gain: 0.5 });
connect(clone, context.destination);
start(clone.source);Reactive Audio Engine (with iblokz-state)
import { init, dispatch } from 'iblokz-state';
import {vca, connect, update, context} from 'iblokz-audio';
// Initialize state
const state$ = init({
voices: {},
volume: 0.5
});
// Create global volume control
const globalVolume = vca({ gain: 0.5 });
connect(globalVolume, context.destination);
// React to state changes
state$.subscribe(state => {
// Update global volume
update(globalVolume, { gain: state.volume });
// Handle note on/off
Object.keys(state.voices).forEach(note => {
if (!state.voices[note]) {
// Note off
// ... cleanup voice
}
});
});
// Dispatch note on
dispatch(state => ({
...state,
voices: { ...state.voices, 'C4': { velocity: 0.8 } }
}));API Overview
Core Functions
context- Web Audio API context instancecreate(type, prefs, ctx)- Create an audio nodeupdate(node, prefs)- Update node preferencesconnect(node1, node2)- Connect two nodesdisconnect(node1, node2)- Disconnect nodesreroute(node1, node2)- Reroute node to new destinationchain(...nodes)- Chain multiple nodesstart(node, ...args)- Start a nodestop(node, ...args)- Stop a nodenoteToFrequency(note)- Convert note name to frequency
Factory Functions
vco(prefs)- Voltage Controlled Oscillatorvca(prefs)- Voltage Controlled Amplifiervcf(prefs)- Voltage Controlled Filteradsr(prefs)- ADSR Envelope Generatorlfo(prefs)- Low-Frequency OscillatornoteOn(adsr, velocity, time)- Trigger note onnoteOff(adsr, time)- Trigger note off
Node Types
VCO (Oscillator)
import {vco} from 'iblokz-audio';
const osc = vco({
type: 'sine' | 'square' | 'sawtooth' | 'triangle',
freq: 440, // Frequency in Hz
detune: 0 // Detune in cents
});VCA (Gain)
import {vca} from 'iblokz-audio';
const amp = vca({
gain: 0.5 // Gain level (0-1)
});VCF (Filter)
import {vcf} from 'iblokz-audio';
const filter = vcf({
type: 'lowpass' | 'highpass' | 'bandpass' | ...,
cutoff: 0.5, // Cutoff (0-1, mapped to frequency)
resonance: 0.3 // Resonance (0-1)
});ADSR (Envelope)
import {adsr} from 'iblokz-audio';
const envelope = adsr({
volume: 0.41, // Maximum volume
attack: 0.31, // Attack time (seconds)
decay: 0.16, // Decay time (seconds)
sustain: 0.8, // Sustain level (0-1)
release: 0.21 // Release time (seconds)
});LFO (Low-Frequency Oscillator)
import {lfo} from 'iblokz-audio';
const modulator = lfo({
type: 'sine' | 'square' | 'sawtooth' | 'triangle',
frequency: 5, // LFO frequency in Hz
gain: 15 // LFO amplitude
});Reverb
import {create} from 'iblokz-audio';
const reverb = create('reverb', {
seconds: 3, // Reverb duration
decay: 2, // Decay factor
wet: 0.3, // Wet signal level (0-1)
dry: 0.7 // Dry signal level (0-1)
});Architecture
The library is organized into modules:
lib/core.js- Core Web Audio API utilitieslib/controls/adsr.js- ADSR envelope generatorlib/effects/lfo.js- Low-frequency oscillatorlib/effects/reverb.js- Reverb effectlib/sources/sampler.js- Audio sample player
Use Cases
This library is designed for:
- 🎹 Synthesizers - Building software synthesizers and virtual instruments
- 🎛️ DAWs - Digital audio workstation applications
- 🎵 Loop Stations - Audio looping and sequencing
- 🎤 Samplers - Sample-based instruments (MPC-style)
- 🎧 Audio Engines - Reactive audio processing systems
- 🎼 Music Applications - Any web-based music application
Reference Projects
This library was extracted from and is used in:
- jam-station - Groovebox, DAW, and live rig software
- js-loop-station - RC505-style loop station
- xAmplR - Akai MPC-inspired sampler
Development
# Install dependencies
pnpm install
# Build CommonJS bundle
pnpm build
# Run tests
pnpm test
# Run linter
pnpm run lint
# Generate documentation
pnpm run docsDocumentation
For detailed API documentation, see API.md.
To generate the API documentation locally:
npm run docsContributing
Contributions are welcome! Please read CONTRIBUTING.md for details.
- Fork the repository
- Create your feature branch (
git checkout -b feat/amazing-feature) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feat/amazing-feature) - Open a Pull Request
License
MIT © iblokz
Links
- GitHub Repository - Source code
- npm Package - Published package
- Issues - Bug reports & features
- Changelog - Version history
