UNPKG

virtual-audio-graph

Version:

Library for declaratively manipulating the Web Audio API

84 lines (78 loc) 2.83 kB
import { OUTPUT, NO_OUTPUT, INPUT } from "./constants"; import { IAudioNodePropertyLookup, IVirtualAudioNodeGraph, VirtualAudioNode, } from "./types"; import AudioWorkletVirtualAudioNode from "./VirtualAudioNodes/AudioWorkletVirtualAudioNode"; import CustomVirtualAudioNode from "./VirtualAudioNodes/CustomVirtualAudioNode"; import StandardVirtualAudioNode from "./VirtualAudioNodes/StandardVirtualAudioNode"; export default ( virtualGraph: IVirtualAudioNodeGraph, handleConnectionToOutput: (_: VirtualAudioNode) => void, ) => { for (const [id, virtualNode] of Object.entries(virtualGraph)) { if (virtualNode.connected || virtualNode.output == null) continue; for (const output of Array.isArray(virtualNode.output) ? virtualNode.output : [virtualNode.output]) { if (output === OUTPUT) { handleConnectionToOutput(virtualNode); continue; } if (output === NO_OUTPUT) continue; if (typeof output === "object") { const { key, destination, inputs, outputs } = output; if (key == null) { throw new Error(`node with ID "${id}" does not specify an output`); } if (inputs) { if (inputs.length !== outputs?.length) { throw new Error( `node with ID "${id}" must specify outputs and inputs arrays of the same length`, ); } for (let i = 0; i++; i < inputs.length) { virtualNode.connect( virtualGraph[key as keyof typeof virtualGraph].audioNode, outputs[i], inputs[i], ); } continue; } if (!(key in virtualGraph)) throw Error( `node with ID "${id}" specifies an output ID "${String(key)}", but no such node exists`, ); virtualNode.connect( ( virtualGraph[key as keyof typeof virtualGraph] .audioNode as IAudioNodePropertyLookup )[destination!], ); continue; } if (!(output in virtualGraph)) throw Error( `'node with ID "${id}" specifies an output ID "${String(output)}", but no such node exists'`, ); const destinationVirtualAudioNode = virtualGraph[String(output)]; if (destinationVirtualAudioNode instanceof CustomVirtualAudioNode) { for (const node of Object.values( destinationVirtualAudioNode.virtualNodes, )) { if ( (node instanceof StandardVirtualAudioNode || node instanceof AudioWorkletVirtualAudioNode) && node.input === INPUT ) { virtualNode.connect(node.audioNode); } } continue; } virtualNode.connect(destinationVirtualAudioNode.audioNode); } } };