granular
Granular — Granular synthesis engine. Slices a sample buffer into tiny grains and re-synthesises them with controllable position, density, scatter, and pitch.
Quick Start
granular({ url: './sample.wav', grainSize: 0.08, density: 12 })Parameters
| Name | Type | Default | Range/Options | Description |
|---|---|---|---|---|
url | string | — | — | 音声ファイル URL (CORS 必須) |
grainSize | number | 0.08 | 0.01–0.5 s | グレインの長さ |
density | number | 12 | 0.5–100 grains/s | 1秒あたりのグレイン数 |
scatter | number | 0.3 | 0–1 | タイミングの散布量 0–1 |
position | number | 0.5 | 0–1 | バッファ内の再生位置 0–1 |
positionVar | number | 0.1 | 0–1 | 再生位置の揺らぎ 0–1 |
pitch | number | 0 | -24–24 semitone | ピッチシフト 半音単位 |
gain | number | 0.7 | 0–1 | 出力ゲイン |
How it works
On each play() call, granular schedules multiple BufferSourceNode triggers
over the note duration. Each grain:
- starts at a position in the buffer determined by
position±positionVar - has a duration of
grainSizeseconds - is windowed with a Hann-style amplitude envelope to avoid clicks
- is spaced
1 / densityseconds apart, with optionalscatterjitter
Examples
Ambient cloud texture
function* song(ctx) { const key = scales(8, 'E3:dorian') const g = granular({ url: './pad.wav', grainSize: 0.18, density: 20, scatter: 0.8, position: 0.4, positionVar: 0.3, gain: 0.6, }) chain(g, reverb({ size: 1.2, mix: 0.6 })) yield cast(g, key, seq(8, '\{0,4\},~,~,~,~,~,~,~'), ctx)}Slow position sweep over time
function* song(ctx) { const pos = (ctx.cycle % 32) / 32 // scan 0→1 over 32 cycles const g = granular({ url: './drone.wav', grainSize: 0.12, density: 16, position: pos, gain: 0.5 }) yield cast(g, scales(4, 'C3:minor'), seq(4, '0,~,~,~'), ctx)}Combined with stutter
const g = chain( granular({ url: './loop.wav', density: 8, scatter: 0.5 }), stutter({ rate: 16, duty: 0.4, mix: 0.6 }), reverb({ mix: 0.4 }),)