node-web-audio-api 0.18.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/TODOS.md +140 -12
- package/index.mjs +10 -5
- package/js/AnalyserNode.js +262 -48
- package/js/AudioBuffer.js +244 -0
- package/js/AudioBufferSourceNode.js +265 -41
- package/js/AudioContext.js +271 -28
- package/js/AudioDestinationNode.js +42 -100
- package/js/AudioListener.js +219 -0
- package/js/AudioNode.js +323 -0
- package/js/AudioParam.js +252 -39
- package/js/AudioScheduledSourceNode.js +105 -0
- package/js/BaseAudioContext.js +419 -0
- package/js/BiquadFilterNode.js +221 -29
- package/js/ChannelMergerNode.js +96 -22
- package/js/ChannelSplitterNode.js +96 -22
- package/js/ConstantSourceNode.js +92 -26
- package/js/ConvolverNode.js +161 -29
- package/js/DelayNode.js +115 -21
- package/js/DynamicsCompressorNode.js +198 -27
- package/js/GainNode.js +107 -21
- package/js/IIRFilterNode.js +139 -23
- package/js/MediaStreamAudioSourceNode.js +83 -24
- package/js/OfflineAudioContext.js +182 -34
- package/js/OscillatorNode.js +195 -32
- package/js/PannerNode.js +461 -56
- package/js/PeriodicWave.js +67 -3
- package/js/StereoPannerNode.js +107 -21
- package/js/WaveShaperNode.js +147 -29
- package/js/lib/cast.js +19 -0
- package/js/lib/errors.js +10 -55
- package/js/lib/events.js +20 -0
- package/js/lib/symbols.js +5 -0
- package/js/lib/utils.js +12 -12
- package/js/monkey-patch.js +32 -30
- package/node-web-audio-api.darwin-arm64.node +0 -0
- package/node-web-audio-api.darwin-x64.node +0 -0
- package/node-web-audio-api.linux-arm-gnueabihf.node +0 -0
- package/node-web-audio-api.linux-arm64-gnu.node +0 -0
- package/node-web-audio-api.linux-x64-gnu.node +0 -0
- package/node-web-audio-api.win32-arm64-msvc.node +0 -0
- package/node-web-audio-api.win32-x64-msvc.node +0 -0
- package/package.json +7 -4
- package/run-wpt.md +27 -0
- package/run-wpt.sh +5 -0
- package/js/AudioNode.mixin.js +0 -132
- package/js/AudioScheduledSourceNode.mixin.js +0 -67
- package/js/BaseAudioContext.mixin.js +0 -154
- package/js/EventTarget.mixin.js +0 -60
package/js/AudioContext.js
CHANGED
|
@@ -1,60 +1,303 @@
|
|
|
1
|
-
|
|
1
|
+
const conversions = require("webidl-conversions");
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
throwSanitizedError,
|
|
5
|
+
} = require('./lib/errors.js');
|
|
6
|
+
const {
|
|
7
|
+
isFunction,
|
|
8
|
+
kEnumerableProperty
|
|
9
|
+
} = require('./lib/utils.js');
|
|
10
|
+
const {
|
|
11
|
+
kNapiObj,
|
|
12
|
+
} = require('./lib/symbols.js');
|
|
13
|
+
const {
|
|
14
|
+
bridgeEventTarget,
|
|
15
|
+
} = require('./lib/events.js');
|
|
2
16
|
|
|
3
|
-
|
|
4
|
-
const kKeepAwakeId = Symbol('keepAwakeId');
|
|
17
|
+
let contextId = 0;
|
|
5
18
|
|
|
6
|
-
module.exports = function(
|
|
7
|
-
const {
|
|
8
|
-
MediaStreamAudioSourceNode,
|
|
9
|
-
} = bindings;
|
|
19
|
+
module.exports = function(jsExport, nativeBinding) {
|
|
10
20
|
|
|
11
|
-
|
|
12
|
-
|
|
21
|
+
class AudioContext extends jsExport.BaseAudioContext {
|
|
22
|
+
#sinkId = '';
|
|
13
23
|
|
|
14
|
-
class AudioContext extends BaseAudioContext {
|
|
15
|
-
// class AudioContext extends NativeAudioContext {
|
|
16
24
|
constructor(options = {}) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
25
|
+
if (typeof options !== 'object') {
|
|
26
|
+
throw new TypeError(`Failed to construct 'AudioContext': The provided value is not of type 'AudioContextOptions'`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let targetOptions = {};
|
|
30
|
+
|
|
31
|
+
if (options.latencyHint !== undefined) {
|
|
32
|
+
if (['balanced', 'interactive', 'playback'].includes(options.latencyHint)) {
|
|
33
|
+
targetOptions.latencyHint = conversions['DOMString'](options.latencyHint);
|
|
34
|
+
} else {
|
|
35
|
+
targetOptions.latencyHint = conversions['double'](options.latencyHint, {
|
|
36
|
+
context: `Failed to construct 'AudioContext': Failed to read the 'sinkId' property from AudioNodeOptions: The provided value (${options.latencyHint})`,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
targetOptions.latencyHint = 'interactive';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (options.sampleRate !== undefined) {
|
|
44
|
+
targetOptions.sampleRate = conversions['float'](options.sampleRate, {
|
|
45
|
+
context: `Failed to construct 'AudioContext': Failed to read the 'sinkId' property from AudioNodeOptions: The provided value (${options.sampleRate})`,
|
|
46
|
+
});
|
|
47
|
+
} else {
|
|
48
|
+
targetOptions.sampleRate = null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (options.sinkId !== undefined) {
|
|
52
|
+
const sinkId = options.sinkId;
|
|
53
|
+
|
|
54
|
+
if (typeof options.sinkId === 'object') {
|
|
55
|
+
// https://webaudio.github.io/web-audio-api/#enumdef-audiosinktype
|
|
56
|
+
if (!('type' in options.sinkId) || options.sinkId.type !== 'none') {
|
|
57
|
+
throw TypeError(`Failed to construct 'AudioContext': Failed to read the 'sinkId' property from AudioNodeOptions: Failed to read the 'type' property from 'AudioSinkOptions': The provided value (${sinkId.type}) is not a valid enum value of type AudioSinkType.`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
targetOptions.sinkId = 'none';
|
|
61
|
+
} else {
|
|
62
|
+
targetOptions.sinkId = conversions['DOMString'](sinkId, {
|
|
63
|
+
context: `Failed to construct 'AudioContext': Failed to read the 'sinkId' property from AudioNodeOptions: Failed to read the 'type' property from 'AudioSinkOptions': The provided value (${sinkId})`,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
targetOptions.sinkId = '';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let napiObj;
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
napiObj = new nativeBinding.AudioContext(targetOptions);
|
|
74
|
+
} catch (err) {
|
|
75
|
+
throwSanitizedError(err);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
super({ [kNapiObj]: napiObj });
|
|
79
|
+
|
|
80
|
+
if (options.sinkId !== undefined) {
|
|
81
|
+
this.#sinkId = options.sinkId;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Bridge Rust native event to Node EventTarget
|
|
85
|
+
bridgeEventTarget(this);
|
|
21
86
|
|
|
87
|
+
// @todo - check if this is still required
|
|
22
88
|
// prevent garbage collection and process exit
|
|
23
89
|
const id = contextId++;
|
|
24
90
|
// store in process to prevent garbage collection
|
|
25
|
-
const
|
|
26
|
-
process
|
|
27
|
-
|
|
28
|
-
|
|
91
|
+
const kAudioContextId = Symbol(`node-web-audio-api:audio-context-${id}`);
|
|
92
|
+
Object.defineProperty(process, kAudioContextId, {
|
|
93
|
+
__proto__: null,
|
|
94
|
+
enumerable: false,
|
|
95
|
+
configurable: true,
|
|
96
|
+
value: this,
|
|
97
|
+
});
|
|
29
98
|
// keep process awake until context is closed
|
|
30
99
|
const keepAwakeId = setInterval(() => {}, 10 * 1000);
|
|
31
|
-
this[kKeepAwakeId] = keepAwakeId;
|
|
32
100
|
|
|
33
101
|
// clear on close
|
|
34
102
|
this.addEventListener('statechange', () => {
|
|
35
103
|
if (this.state === 'closed') {
|
|
36
104
|
// allow to garbage collect the context and to the close the process
|
|
37
|
-
delete process[
|
|
38
|
-
clearTimeout(
|
|
105
|
+
delete process[kAudioContextId];
|
|
106
|
+
clearTimeout(keepAwakeId);
|
|
39
107
|
}
|
|
40
108
|
});
|
|
41
109
|
}
|
|
42
110
|
|
|
43
|
-
|
|
111
|
+
get baseLatency() {
|
|
112
|
+
if (!(this instanceof AudioContext)) {
|
|
113
|
+
throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'AudioContext\'');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return this[kNapiObj].baseLatency;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
get outputLatency() {
|
|
120
|
+
if (!(this instanceof AudioContext)) {
|
|
121
|
+
throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'AudioContext\'');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return this[kNapiObj].outputLatency;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
get sinkId() {
|
|
128
|
+
if (!(this instanceof AudioContext)) {
|
|
129
|
+
throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'AudioContext\'');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return this.#sinkId;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
get renderCapacity() {
|
|
136
|
+
if (!(this instanceof AudioContext)) {
|
|
137
|
+
throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'AudioContext\'');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
throw new Error(`AudioContext::renderCapacity is not yet implemented`);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
get onsinkchange() {
|
|
144
|
+
if (!(this instanceof AudioContext)) {
|
|
145
|
+
throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'AudioContext\'');
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return this._sinkchange || null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
set onsinkchange(value) {
|
|
152
|
+
if (!(this instanceof AudioContext)) {
|
|
153
|
+
throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'AudioContext\'');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (isFunction(value) || value === null) {
|
|
157
|
+
this._sinkchange = value;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
getOutputTimestamp() {
|
|
162
|
+
if (!(this instanceof AudioContext)) {
|
|
163
|
+
throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'AudioContext\'');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
throw new Error(`AudioContext::getOutputTimestamp is not yet implemented`);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async resume() {
|
|
170
|
+
if (!(this instanceof AudioContext)) {
|
|
171
|
+
throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'AudioContext\'');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
await this[kNapiObj].resume();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async suspend() {
|
|
178
|
+
if (!(this instanceof AudioContext)) {
|
|
179
|
+
throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'AudioContext\'');
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
await this[kNapiObj].suspend();
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async close() {
|
|
186
|
+
if (!(this instanceof AudioContext)) {
|
|
187
|
+
throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'AudioContext\'');
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
await this[kNapiObj].close();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async setSinkId(sinkId) {
|
|
194
|
+
if (!(this instanceof AudioContext)) {
|
|
195
|
+
throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'AudioContext\'');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (arguments.length < 1) {
|
|
199
|
+
throw new TypeError(`Failed to execute 'setSinkId' on 'AudioContext': 1 argument required, but only ${arguments.length} present`);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
let targetSinkId = '';
|
|
203
|
+
|
|
204
|
+
if (typeof sinkId === 'object') {
|
|
205
|
+
if (!('type' in sinkId) || sinkId.type !== 'none') {
|
|
206
|
+
throw new TypeError(`Failed to execute 'setSinkId' on 'AudioContext': Failed to read the 'type' property from 'AudioSinkOptions': The provided value '${sinkId.type}' is not a valid enum value of type AudioSinkType.`);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
targetSinkId = 'none';
|
|
210
|
+
} else {
|
|
211
|
+
targetSinkId = conversions['DOMString'](sinkId, {
|
|
212
|
+
context: `Failed to execute 'setSinkId' on 'AudioContext': Failed to read the 'type' property from 'AudioSinkOptions': The provided value '${sinkId.type}'`,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
this.#sinkId = sinkId;
|
|
217
|
+
|
|
44
218
|
try {
|
|
45
|
-
|
|
46
|
-
return Promise.resolve(undefined);
|
|
219
|
+
this[kNapiObj].setSinkId(targetSinkId);
|
|
47
220
|
} catch (err) {
|
|
48
|
-
|
|
221
|
+
throwSanitizedError(err);
|
|
49
222
|
}
|
|
50
223
|
}
|
|
51
224
|
|
|
52
225
|
// online context only AudioNodes
|
|
53
226
|
createMediaStreamSource(mediaStream) {
|
|
54
|
-
|
|
55
|
-
|
|
227
|
+
if (!(this instanceof AudioContext)) {
|
|
228
|
+
throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'AudioContext\'');
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (arguments.length < 1) {
|
|
232
|
+
throw new TypeError(`Failed to execute 'createMediaStreamSource' on 'AudioContext': 1 argument required, but only ${arguments.length} present`);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const options = {
|
|
236
|
+
mediaStream,
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
return new jsExport.MediaStreamAudioSourceNode(this, options);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
createMediaElementSource() {
|
|
243
|
+
if (!(this instanceof AudioContext)) {
|
|
244
|
+
throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'AudioContext\'');
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
throw new Error(`AudioContext::createMediaElementSource() is not yet implemented, cf. https://github.com/ircam-ismm/node-web-audio-api/issues/91 for more information`);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
createMediaStreamTrackSource() {
|
|
251
|
+
if (!(this instanceof AudioContext)) {
|
|
252
|
+
throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'AudioContext\'');
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
throw new Error(`AudioContext::createMediaStreamTrackSource() is not yet implemented, cf. https://github.com/ircam-ismm/node-web-audio-api/issues/91 for more information`);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
createMediaStreamDestination() {
|
|
259
|
+
if (!(this instanceof AudioContext)) {
|
|
260
|
+
throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'AudioContext\'');
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
throw new Error(`AudioContext::createMediaStreamDestination() is not yet implemented, cf. https://github.com/ircam-ismm/node-web-audio-api/issues/91 for more information`);
|
|
56
264
|
}
|
|
57
265
|
}
|
|
58
266
|
|
|
267
|
+
Object.defineProperties(AudioContext, {
|
|
268
|
+
length: {
|
|
269
|
+
__proto__: null,
|
|
270
|
+
writable: false,
|
|
271
|
+
enumerable: false,
|
|
272
|
+
configurable: true,
|
|
273
|
+
value: 0,
|
|
274
|
+
},
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
Object.defineProperties(AudioContext.prototype, {
|
|
278
|
+
[Symbol.toStringTag]: {
|
|
279
|
+
__proto__: null,
|
|
280
|
+
writable: false,
|
|
281
|
+
enumerable: false,
|
|
282
|
+
configurable: true,
|
|
283
|
+
value: 'AudioContext',
|
|
284
|
+
},
|
|
285
|
+
|
|
286
|
+
baseLatency: kEnumerableProperty,
|
|
287
|
+
outputLatency: kEnumerableProperty,
|
|
288
|
+
sinkId: kEnumerableProperty,
|
|
289
|
+
renderCapacity: kEnumerableProperty,
|
|
290
|
+
onsinkchange: kEnumerableProperty,
|
|
291
|
+
getOutputTimestamp: kEnumerableProperty,
|
|
292
|
+
resume: kEnumerableProperty,
|
|
293
|
+
suspend: kEnumerableProperty,
|
|
294
|
+
close: kEnumerableProperty,
|
|
295
|
+
setSinkId: kEnumerableProperty,
|
|
296
|
+
createMediaStreamSource: kEnumerableProperty,
|
|
297
|
+
createMediaElementSource: kEnumerableProperty,
|
|
298
|
+
createMediaStreamTrackSource: kEnumerableProperty,
|
|
299
|
+
createMediaStreamDestination: kEnumerableProperty,
|
|
300
|
+
});
|
|
301
|
+
|
|
59
302
|
return AudioContext;
|
|
60
303
|
};
|
|
@@ -1,111 +1,53 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
// the native destination instance.
|
|
1
|
+
const { kNapiObj } = require('./lib/symbols.js');
|
|
2
|
+
const { kEnumerableProperty } = require('./lib/utils.js');
|
|
3
|
+
const AudioNode = require('./AudioNode.js');
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
// AudioNode interface
|
|
16
|
-
get context() {
|
|
17
|
-
return this[kNativeAudioDestinationNode].context;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
get numberOfInputs() {
|
|
21
|
-
return this[kNativeAudioDestinationNode].numberOfInputs;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
get numberOfOutputs() {
|
|
25
|
-
return this[kNativeAudioDestinationNode].numberOfOutputs;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
get channelCount() {
|
|
29
|
-
return this[kNativeAudioDestinationNode].channelCount;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
get channelCountMode() {
|
|
33
|
-
return this[kNativeAudioDestinationNode].channelCountMode;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
get channelInterpretation() {
|
|
37
|
-
return this[kNativeAudioDestinationNode].channelInterpretation;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// setters
|
|
41
|
-
|
|
42
|
-
set channelCount(value) {
|
|
43
|
-
try {
|
|
44
|
-
this[kNativeAudioDestinationNode].channelCount = value;
|
|
45
|
-
} catch (err) {
|
|
46
|
-
throwSanitizedError(err);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
set channelCountMode(value) {
|
|
51
|
-
try {
|
|
52
|
-
this[kNativeAudioDestinationNode].channelCountMode = value;
|
|
53
|
-
} catch (err) {
|
|
54
|
-
throwSanitizedError(err);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
set channelInterpretation(value) {
|
|
59
|
-
try {
|
|
60
|
-
this[kNativeAudioDestinationNode].channelInterpretation = value;
|
|
61
|
-
} catch (err) {
|
|
62
|
-
throwSanitizedError(err);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// methods - connect / disconnect
|
|
67
|
-
|
|
68
|
-
connect(...args) {
|
|
69
|
-
// unwrap raw audio params from facade
|
|
70
|
-
if (args[0] instanceof AudioParam) {
|
|
71
|
-
args[0] = args[0][kNativeAudioParam];
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// unwrap raw audio destination from facade
|
|
75
|
-
if (args[0] instanceof AudioDestinationNode) {
|
|
76
|
-
args[0] = args[0][kNativeAudioDestinationNode];
|
|
5
|
+
class AudioDestinationNode extends AudioNode {
|
|
6
|
+
constructor(context, options) {
|
|
7
|
+
// Make constructor "private"
|
|
8
|
+
if (
|
|
9
|
+
(typeof options !== 'object')
|
|
10
|
+
|| !(kNapiObj in options)
|
|
11
|
+
|| options[kNapiObj]['Symbol.toStringTag'] !== 'AudioDestinationNode'
|
|
12
|
+
) {
|
|
13
|
+
throw new TypeError('Illegal constructor');
|
|
77
14
|
}
|
|
78
15
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
throwSanitizedError(err);
|
|
83
|
-
}
|
|
16
|
+
super(context, {
|
|
17
|
+
[kNapiObj]: options[kNapiObj],
|
|
18
|
+
});
|
|
84
19
|
}
|
|
85
20
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
args[0] = args[0][kNativeAudioParam];
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// unwrap raw audio destination from facade
|
|
93
|
-
if (args[0] instanceof AudioDestinationNode) {
|
|
94
|
-
args[0] = args[0][kNativeAudioDestinationNode];
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
try {
|
|
98
|
-
return this[kNativeAudioDestinationNode].disconnect(...args);
|
|
99
|
-
} catch (err) {
|
|
100
|
-
throwSanitizedError(err);
|
|
21
|
+
get maxChannelCount() {
|
|
22
|
+
if (!(this instanceof AudioDestinationNode)) {
|
|
23
|
+
throw new TypeError("Invalid Invocation: Value of 'this' must be of type 'AudioDestinationNode'");
|
|
101
24
|
}
|
|
102
|
-
}
|
|
103
25
|
|
|
104
|
-
|
|
105
|
-
return this[kNativeAudioDestinationNode].maxChannelCount;
|
|
26
|
+
return this[kNapiObj].maxChannelCount;
|
|
106
27
|
}
|
|
107
28
|
}
|
|
108
29
|
|
|
109
|
-
|
|
110
|
-
|
|
30
|
+
Object.defineProperties(AudioDestinationNode, {
|
|
31
|
+
length: {
|
|
32
|
+
__proto__: null,
|
|
33
|
+
writable: false,
|
|
34
|
+
enumerable: false,
|
|
35
|
+
configurable: true,
|
|
36
|
+
value: 0,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
Object.defineProperties(AudioDestinationNode.prototype, {
|
|
41
|
+
[Symbol.toStringTag]: {
|
|
42
|
+
__proto__: null,
|
|
43
|
+
writable: false,
|
|
44
|
+
enumerable: false,
|
|
45
|
+
configurable: true,
|
|
46
|
+
value: 'AudioDestinationNode',
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
maxChannelCount: kEnumerableProperty,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
module.exports = AudioDestinationNode;
|
|
111
53
|
|