Skip to content

GrainPlayer

Granular synthesis lets you independently control pitch and playback speed -- something impossible with traditional audio playback. Drag the waveform to set the read position, adjust grain size for texture variation, and add jitter for organic randomness.

Granular synthesis — pitch and speed are independent.

Click Play to load waveform
1.00x
0 semitones
100ms
50ms
0%

How It Works

The createGrainPlayer() function reads tiny overlapping slices of audio (called grains) and plays them back continuously. Because each grain is independently pitch-shifted, the overall pitch can change without affecting how fast the buffer is being read -- and vice versa.

Key API

typescript
import { createGrainPlayer, createSound } from 'ez-web-audio'

const sound = await createSound('/audio/sample.mp3')
const grain = await createGrainPlayer(sound.audioBuffer, {
  grainSize: 0.1, // seconds per grain
  overlap: 0.05, // grain crossfade overlap in seconds
  jitter: 0, // position randomization (0-1)
  loop: true,
})

grain.play()
grain.pitch = 7 // up a perfect fifth (semitones) -- speed unchanged
grain.position = 0.5 // jump to middle of buffer
grain.grainSize = 0.2 // larger grains = smoother texture

pitch is measured in semitones: 12 = one octave up, -12 = one octave down, 7 = a perfect fifth.

Interactive Controls

ControlWhat It Does
Waveform canvasClick or drag to set the grain read position
PitchShifts pitch in semitones without changing speed
SpeedAdvances the read position faster or slower without changing pitch
Grain SizeLarger = smoother; smaller = more granular artifacts
OverlapCrossfade between grains for smoother texture
JitterRandomizes grain start position -- adds organic movement

Cleanup

typescript
grain.stop()
grain.dispose() // Stops all scheduled grains and releases the buffer reference

Further Reading