Manage Web Audio API nodes declaratively with JavaScript using the virtual-audio-graph library
A declarative Web Audio API library inspired by React's virtual DOM approach.
import createVirtualAudioGraph, {
oscillator,
gain,
OUTPUT
} from 'virtual-audio-graph'
// Create instance
const virtualAudioGraph = createVirtualAudioGraph()
// Update the audio graph
virtualAudioGraph.update({
0: gain(OUTPUT, { gain: 0.5 }),
1: oscillator(0, {
frequency: 440,
stopTime: virtualAudioGraph.currentTime + 1
})
})
const customOsc = createNode(({
frequency,
startTime,
stopTime
}) => ({
0: gain(OUTPUT, {
gain: [
['setValueAtTime', 0, startTime],
['linearRampToValueAtTime', 1, startTime + 0.1],
['linearRampToValueAtTime', 0, stopTime]
]
}),
1: oscillator(0, { frequency, startTime, stopTime })
}))
virtualAudioGraph.update({
0: customOsc(OUTPUT, {
frequency: 440,
startTime: currentTime,
stopTime: currentTime + 1
})
})
{}createVirtualAudioGraph({audioContext?, output?}) - Create a new virtual audio graph instancecreateNode(fn) - Create a custom virtual audio nodecreateWorkletNode(name) - Create an AudioWorklet nodevirtualAudioGraph.update(graphDefinition) - Update the audio graphvirtualAudioGraph.currentTime - Get current audio context timevirtualAudioGraph.getAudioNodeById(id) - Get AudioNode by IDanalyser - AnalyserNodebiquadFilter - BiquadFilterNode bufferSource - AudioBufferSourceNodechannelMerger - ChannelMergerNodechannelSplitter - ChannelSplitterNodeconvolver - ConvolverNodedelay - DelayNodedynamicsCompressor - DynamicsCompressorNodegain - GainNodemediaElementSource - MediaElementAudioSourceNodemediaStreamDestination - MediaStreamAudioDestinationNodemediaStreamSource - MediaStreamAudioSourceNodeoscillator - OscillatorNodepanner - PannerNodestereoPanner - StereoPannerNodewaveShaper - WaveShaperNodeOUTPUT - Connect node to graph outputNO_OUTPUT - Node has no output connectionCommon parameters that can be passed to node constructors:
startTime - When to start the nodestopTime - When to stop the nodegain - Gain value (for GainNode)frequency - Frequency value (for OscillatorNode)detune - Detune value in centstype - Oscillator type ('sine', 'square', 'sawtooth', 'triangle')delayTime - Delay time in secondsmaxDelayTime - Maximum delay timebuffer - AudioBuffer for BufferSourceNodeplaybackRate - Playback rate for BufferSourceNodeParameters can be:
['setValueAtTime', value, time]To stop all audio and remove all nodes, update with an empty graph:
virtualAudioGraph.update({})
const { currentTime } = virtualAudioGraph
virtualAudioGraph.update({
0: gain(OUTPUT, {
gain: [
['setValueAtTime', 0, currentTime],
['linearRampToValueAtTime', 0.5, currentTime + 0.1],
['exponentialRampToValueAtTime', 0.01, currentTime + 2]
]
}),
1: oscillator(0, {
frequency: [
['setValueAtTime', 440, currentTime],
['linearRampToValueAtTime', 880, currentTime + 2]
],
stopTime: currentTime + 2
})
})
const { currentTime } = virtualAudioGraph
virtualAudioGraph.update({
0: stereoPanner(OUTPUT, {
pan: [
['setValueAtTime', -1, currentTime],
['linearRampToValueAtTime', 1, currentTime + 2]
]
}),
1: oscillator(0, {
frequency: 440,
stopTime: currentTime + 2
})
})
// Load audio file
const response = await fetch('sound.wav')
const arrayBuffer = await response.arrayBuffer()
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer)
// Play with effects
virtualAudioGraph.update({
0: gain(OUTPUT, { gain: 0.7 }),
1: delay(0, { delayTime: 0.3 }),
2: bufferSource([0, 1], {
buffer: audioBuffer,
playbackRate: 1.2,
startTime: virtualAudioGraph.currentTime
})
})
// Stop playback after 3 seconds
setTimeout(() => {
virtualAudioGraph.update({})
}, 3000)
Add this context to your project via the
ctxs command line integration: