Integration Guide
Complete guide to using DSonic in your projects
Integration Guide
Complete guide to using DSonic in your projects
Overview
DSonic is a Web Audio drum synthesizer with two primary use cases:
- Strudel Integration - Use DSonic as a sound source in Strudel live-coding patterns
- Standalone Usage - Use DSonic directly in any web application via the Web Audio API
Architecture
DSonic provides two synthesis systems:
| System | Description | Sound Names |
|---|---|---|
| Voice-based | Two-layer (oscillator + noise) with waveguide resonator | dsonic, dsonic_kick, dsonic_snare, etc. |
| Engine-based | 12 specialized algorithms optimized for specific drum types | dsonic_akick, dsonic_hsnare, dsonic_fmperc, etc. |
Prerequisites
For Strudel Integration
- Familiarity with Strudel pattern syntax (strudel.cc/learn)
- Understanding of Strudel's audio architecture
- Modern browser with Web Audio API support
For Standalone Usage
- Node.js 18+ and npm (for npm installation)
- ES modules-compatible bundler (Vite, webpack, esbuild, etc.)
- Basic understanding of Web Audio API concepts (AudioContext, AudioNode)
- TypeScript support recommended (types are included)
Strudel Integration: CDN Script
CDN Script Tag Easy
Load DSonic directly in the browser without a build step. Best for quick prototyping.
Basic Setup
Add DSonic after Strudel's scripts in your HTML:
<!-- Load Strudel REPL -->
<script src="https://unpkg.com/@strudel/repl@latest"></script>
<!-- Load DSonic -->
<script type="module">
import { registerDSonic } from 'https://unpkg.com/dsonic@latest/dist/dsonic.js';
// Wait for Strudel to initialize, then register DSonic
setTimeout(() => {
registerDSonic();
}, 1000);
</script>
<!-- Strudel editor component -->
<strudel-editor>
s("dsonic_kick").freq(55).decay(0.3)
</strudel-editor>Complete Example
<!DOCTYPE html>
<html>
<head>
<title>DSonic + Strudel</title>
</head>
<body>
<script src="https://unpkg.com/@strudel/repl@latest"></script>
<strudel-editor id="editor">
// DSonic drum pattern
stack(
s("dsonic_akick").freq(50).decay(0.4),
s("dsonic_hsnare").struct("~ x").decay(0.15),
s("dsonic_hhat*4").decay(0.05)
)
</strudel-editor>
<script type="module">
import { registerDSonic } from 'https://unpkg.com/dsonic@latest/dist/dsonic.js';
// Poll for Strudel's registerSound function
const waitForStrudel = () => {
if (typeof registerSound === 'function') {
registerDSonic();
console.log('DSonic ready!');
} else {
setTimeout(waitForStrudel, 100);
}
};
waitForStrudel();
</script>
</body>
</html>dsonic@0.1.0) to prevent breaking changes.
Strudel Integration: npm Package
npm Installation Intermediate
Use with a bundler for optimal bundle size and type safety. Best for production applications.
Installation
npm install dsonic @strudel/core @strudel/webaudioVite Configuration
// vite.config.js
import { defineConfig } from 'vite';
export default defineConfig({
build: { target: 'es2020' },
optimizeDeps: {
include: ['dsonic', '@strudel/core', '@strudel/webaudio'],
},
});Main Script
// src/main.js
import { registerDSonic } from 'dsonic';
import { repl } from '@strudel/repl';
const editor = repl({ id: 'editor', defaultOutput: 'speakers' });
editor.scheduler.on('ready', () => {
registerDSonic();
});Strudel Integration: Custom REPL
Custom UI with @strudel/web Advanced
Build your own interface without Strudel's default editor. Full control over the UI.
Minimal Custom Player
import { getAudioContext, initAudioOnFirstClick } from '@strudel/webaudio';
import { evaluate, Scheduler } from '@strudel/core';
import { registerDSonic } from 'dsonic';
initAudioOnFirstClick();
const scheduler = new Scheduler({ getAudioContext, interval: 0.05, ahead: 0.15 });
registerDSonic();
async function playPattern(code) {
const { pattern } = await evaluate(code);
scheduler.setPattern(pattern);
scheduler.start();
}Strudel Pattern Examples
Basic Drum Kit
// Four-on-the-floor pattern
stack(
s("dsonic_akick").freq(50).decay(0.35),
s("dsonic_hsnare").struct("~ x").decay(0.15),
s("dsonic_hhat*4").decay(0.05),
s("dsonic_hclap").struct("~ ~ ~ x").decay(0.2)
)Available Sound Names
| Voice-based | Engine-based |
|---|---|
dsonic | dsonic_akick |
dsonic_kick | dsonic_membrane |
dsonic_snare | dsonic_hsnare |
dsonic_hihat | dsonic_hclap |
dsonic_openhat | dsonic_hhat |
dsonic_clap | dsonic_hcymbal |
dsonic_tom | dsonic_htom |
dsonic_ride | dsonic_hrim |
dsonic_crash | dsonic_shaker |
dsonic_rimshot | dsonic_fold |
dsonic_noise | dsonic_impact |
dsonic_fmperc |
Standalone Usage: Setup
Use DSonic directly without Strudel for custom applications, games, or any Web Audio project.
npm Installation
npm install dsonicTypeScript Configuration
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler"
}
}Standalone Usage: API
DrumSynth (Voice-based)
import { DrumSynth, getTemplateParams, setAudioContext } from 'dsonic';
const audioContext = new AudioContext();
setAudioContext(audioContext);
const synth = new DrumSynth(audioContext);
const kickParams = getTemplateParams('kick');
const { node, stop } = synth.trigger(audioContext.currentTime, kickParams);DrumSynth Methods
| Method | Description |
|---|---|
trigger(time, params) | Trigger a voice. Returns { node, stop } |
setMasterGain(gain) | Set master output level (0-1) |
setWaveguide(params) | Configure shared waveguide resonator |
stopAll() | Stop all playing voices |
getOutput() | Get the output AudioNode for routing |
Standalone Usage: Engines
Engine-based synthesis provides 12 specialized drum algorithms:
Using createEngine()
import { createEngine, getAudioContext } from 'dsonic';
const ctx = getAudioContext();
const kick = createEngine(ctx, 'analog_kick', {
bodyPitch: 50,
bodyDecay: 0.35,
pitchEnvAmt: 36,
});
kick.getOutput().connect(ctx.destination);
kick.trigger(ctx.currentTime);
setTimeout(() => kick.dispose(), 1000);Engine Types
| Type | Class | Use Case |
|---|---|---|
'analog_kick' | AnalogKickEngine | 808/909-style kicks |
'membrane' | DualMembraneEngine | Physical snare |
'hybrid_snare' | HybridSnareEngine | Analog body + noise |
'clap' | ClapEngine | Multi-hit handclaps |
'hat' | HatEngine | Metallic hi-hats |
'cymbal' | CymbalEngine | Crashes, rides |
'tom' | TomCongaEngine | Toms, congas |
'rim' | RimClaveEngine | Rimshots, claves |
'shaker' | ShakerEngine | Granular shakers |
'fold' | FoldWavetableEngine | Waveshaping drums |
'impact' | ImpactEngine | Multi-layer percussion |
'fm' | FMPercEngine | 4-operator FM |
Configuration
Audio Context Management
import { getAudioContext, setAudioContext } from 'dsonic';
const myContext = new AudioContext({ sampleRate: 48000 });
setAudioContext(myContext);Waveguide Configuration
import { setWaveguide } from 'dsonic';
setWaveguide({
tune: 0.5,
decay: 0.6,
body: 0.4,
mode: 'tube'
});Troubleshooting
No Sound Output
document.getElementById('play').onclick = async () => {
const ctx = getAudioContext();
if (ctx.state === 'suspended') await ctx.resume();
};registerSound Not Found
Wait for Strudel to initialize before registering DSonic:
function waitForStrudel(callback) {
if (typeof registerSound === 'function') callback();
else setTimeout(() => waitForStrudel(callback), 100);
}
waitForStrudel(() => registerDSonic());Memory Leaks
Always dispose engines after use:
const engine = createEngine(ctx, 'analog_kick', params);
engine.trigger(ctx.currentTime);
setTimeout(() => engine.dispose(), 1000);Getting Help
- GitHub Issues - Report bugs or request features
- Strudel Documentation - Learn Strudel patterns
- Parameter Reference - Full parameter documentation