-
Notifications
You must be signed in to change notification settings - Fork 36
/
audio-destination-node.ts
152 lines (119 loc) · 5.3 KB
/
audio-destination-node.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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import { Injector } from '@angular/core';
import { INDEX_SIZE_ERROR_FACTORY_PROVIDER, IndexSizeErrorFactory } from '../factories/index-size-error';
import { INVALID_STATE_ERROR_FACTORY_PROVIDER, InvalidStateErrorFactory } from '../factories/invalid-state-error';
import { AUDIO_NODE_RENDERER_STORE } from '../globals';
import { isAudioNode } from '../guards/audio-node';
import { getNativeContext } from '../helpers/get-native-context';
import { isOfflineAudioContext } from '../helpers/is-offline-audio-context';
import { IAudioDestinationNode, IAudioNode, IAudioParam, IMinimalBaseAudioContext } from '../interfaces';
import { AudioDestinationNodeRenderer } from '../renderers/audio-destination-node';
import { AudioNode } from './audio-node';
const injector = Injector.create({
providers: [
INDEX_SIZE_ERROR_FACTORY_PROVIDER,
INVALID_STATE_ERROR_FACTORY_PROVIDER
]
});
const indexSizeErrorFactory = injector.get(IndexSizeErrorFactory);
const invalidStateErrorFactory = injector.get(InvalidStateErrorFactory);
export class AudioDestinationNode implements IAudioDestinationNode {
private _audioNode: IAudioNode;
private _isOfflineAudioContext: boolean;
private _maxChannelCount: number;
constructor (context: IMinimalBaseAudioContext, channelCount: number) {
const nativeContext = getNativeContext(context);
const nativeNode = nativeContext.destination;
/*
* @todo Transpiling super access inside the channelCount/channelCountMode property accessors down to ES5 does not work. That's why
* the audioNode is stored as a private property and all its methods and properties get proxied.
*/
this._audioNode = new AudioNode(context, nativeNode, channelCount, this);
this._isOfflineAudioContext = isOfflineAudioContext(nativeContext);
const maxChannelCount = nativeNode.maxChannelCount;
// Bug #47: The AudioDestinationNode in Edge and Safari do not initialize the maxChannelCount property correctly.
if (maxChannelCount === 0) {
if (this._isOfflineAudioContext) {
nativeNode.channelCount = channelCount;
nativeNode.channelCountMode = 'explicit';
}
this._maxChannelCount = channelCount;
} else {
this._maxChannelCount = nativeNode.maxChannelCount;
}
if (isOfflineAudioContext(nativeContext)) {
const audioDestinationNodeRenderer = new AudioDestinationNodeRenderer();
AUDIO_NODE_RENDERER_STORE.set(this, audioDestinationNodeRenderer);
}
}
public get channelCount () {
return this._audioNode.channelCount;
}
public set channelCount (value) {
// Bug #52: Chrome, Edge, Opera & Safari do not throw an exception at all.
// Bug #54: Firefox does throw an IndexSizeError.
if (this._isOfflineAudioContext) {
throw invalidStateErrorFactory.create();
}
// Bug #47: The AudioDestinationNode in Edge and Safari do not initialize the maxChannelCount property correctly.
if (value > this._maxChannelCount) {
throw indexSizeErrorFactory.create();
}
this._audioNode.channelCount = value;
}
public get channelCountMode () {
return this._audioNode.channelCountMode;
}
public set channelCountMode (value) {
// Bug #53: No browser does throw an exception yet.
if (this._isOfflineAudioContext) {
throw invalidStateErrorFactory.create();
}
this._audioNode.channelCountMode = value;
}
public get channelInterpretation () {
return this._audioNode.channelInterpretation;
}
public set channelInterpretation (value) {
this._audioNode.channelInterpretation = value;
}
public get context () {
return this._audioNode.context;
}
public get maxChannelCount () {
return this._maxChannelCount;
}
public get numberOfInputs () {
return this._audioNode.numberOfInputs;
}
public get numberOfOutputs () {
return this._audioNode.numberOfOutputs;
}
public addEventListener (
type: string,
listener: any, // @todo EventListenerOrEventListenerObject | null = null,
options?: boolean | AddEventListenerOptions
): void {
return this._audioNode.addEventListener(type, listener, options);
}
public dispatchEvent (evt: Event) {
return this._audioNode.dispatchEvent(evt);
}
public connect (destinationNode: IAudioNode, output?: number, input?: number): IAudioNode;
public connect (destinationParam: IAudioParam, output?: number): void;
public connect (destination: IAudioNode | IAudioParam, output = 0, input = 0): void | IAudioNode {
if (isAudioNode(destination)) {
return this._audioNode.connect(destination, output, input);
}
return this._audioNode.connect(destination, output);
}
public disconnect (destination?: IAudioNode): void {
return this._audioNode.disconnect(destination);
}
public removeEventListener (
type: string,
listener: any, // @todo EventListenerOrEventListenerObject | null = null,
options?: EventListenerOptions | boolean
): void {
return this._audioNode.removeEventListener(type, listener, options);
}
}