-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathVirtualAudioGraph.ts
74 lines (60 loc) · 2.21 KB
/
VirtualAudioGraph.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import connectAudioNodes from "./connectAudioNodes";
import { IVirtualAudioNodeGraph, VirtualAudioNode } from "./types";
import { entries, equals, values } from "./utils";
export default class VirtualAudioGraph {
private virtualNodes: IVirtualAudioNodeGraph = {};
constructor(
public readonly audioContext: AudioContext | OfflineAudioContext,
private readonly output: AudioDestinationNode,
) {}
public getAudioNodeById(id: number | string): AudioNode | void {
return this.virtualNodes[id]?.audioNode;
}
public update(newGraph: IVirtualAudioNodeGraph): this {
if (newGraph.hasOwnProperty("output")) {
throw new Error('"output" is not a valid id');
}
for (const [id, virtualAudioNode] of entries(this.virtualNodes)) {
if (newGraph.hasOwnProperty(id)) continue;
virtualAudioNode.disconnectAndDestroy();
this.disconnectParents(virtualAudioNode);
delete this.virtualNodes[id];
}
for (const key of Object.keys(newGraph)) {
const newVirtualAudioNode = newGraph[key];
const virtualAudioNode = this.virtualNodes[key];
if (virtualAudioNode == null) {
this.virtualNodes[key] = newVirtualAudioNode.initialize(
this.audioContext,
);
continue;
}
if (virtualAudioNode.cannotUpdateInPlace(newVirtualAudioNode)) {
virtualAudioNode.disconnectAndDestroy();
this.disconnectParents(virtualAudioNode);
this.virtualNodes[key] = newVirtualAudioNode.initialize(
this.audioContext,
);
continue;
}
if (!equals(newVirtualAudioNode.output, virtualAudioNode.output)) {
virtualAudioNode.disconnect();
this.disconnectParents(virtualAudioNode);
virtualAudioNode.output = newVirtualAudioNode.output;
}
virtualAudioNode.update(newVirtualAudioNode.params, this.audioContext);
}
connectAudioNodes(this.virtualNodes, (vNode: VirtualAudioNode) =>
vNode.connect(this.output),
);
return this;
}
public get currentTime(): number {
return this.audioContext.currentTime;
}
private disconnectParents(vNode: VirtualAudioNode): void {
for (const node of values(this.virtualNodes)) {
node.disconnect(vNode);
}
}
}