Granular Synthesis
by soulwire
HTML
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Babel + JSX
const context = new AudioContext()
class Granulizer {
speed = 1
rate = 1.0
jitter = 0
detune = 0
grainSize = 0.1
constructor(context, buffer) {
this.currentTime = 0
this.update = this.update.bind(this)
this.context = context
this.buffer = buffer
this.compressor = context.createDynamicsCompressor()
this.compressor.connect(context.destination)
this.convolver = context.createConvolver()
this.convolver.connect(this.compressor)
//this.convolver.buffer = buffer
//this.convolver.buffer = this.createRandomBuffer(0.5)
this.convolver.buffer = this.createPartialBuffer(buffer, 5)
this.master = this.convolver
}
createPartialBuffer(source, duration) {
const buffer = context.createBuffer(2, duration * this.context.sampleRate, this.context.sampleRate)
const inL = source.getChannelData(0)
const inR = source.getChannelData(1)
const outL = buffer.getChannelData(0)
const outR = buffer.getChannelData(1)
for (let i = 0; i < buffer.length; i++) {
outL[i] = inL[i]
outR[i] = inR[i]
}
return buffer
}
createRandomBuffer(duration) {
const buffer = context.createBuffer(2, duration * this.context.sampleRate, this.context.sampleRate)
const left = buffer.getChannelData(0)
const right = buffer.getChannelData(1)
for (let i = 0; i < buffer.length; i++) {
left[i] = Math.random() * 2 - 1
right[i] = Math.random() * 2 - 1
}
return buffer
}
start() {
this.lastUpdateTime = this.context.currentTime
this.update()
}
stop() {
cancelAnimationFrame(this.frameRequest)
}
update() {
const delta = this.context.currentTime - this.lastUpdateTime
if (delta > 0) {
this.currentTime += delta * this.speed
if (this.currentTime > this.buffer.duration) {
this.currentTime -= this.buffer.duration
} else if (this.currentTime < 0) {
this.currentTime += this.buffer.duration
}
const source =...