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.
Files changed (49) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/TODOS.md +140 -12
  3. package/index.mjs +10 -5
  4. package/js/AnalyserNode.js +262 -48
  5. package/js/AudioBuffer.js +244 -0
  6. package/js/AudioBufferSourceNode.js +265 -41
  7. package/js/AudioContext.js +271 -28
  8. package/js/AudioDestinationNode.js +42 -100
  9. package/js/AudioListener.js +219 -0
  10. package/js/AudioNode.js +323 -0
  11. package/js/AudioParam.js +252 -39
  12. package/js/AudioScheduledSourceNode.js +105 -0
  13. package/js/BaseAudioContext.js +419 -0
  14. package/js/BiquadFilterNode.js +221 -29
  15. package/js/ChannelMergerNode.js +96 -22
  16. package/js/ChannelSplitterNode.js +96 -22
  17. package/js/ConstantSourceNode.js +92 -26
  18. package/js/ConvolverNode.js +161 -29
  19. package/js/DelayNode.js +115 -21
  20. package/js/DynamicsCompressorNode.js +198 -27
  21. package/js/GainNode.js +107 -21
  22. package/js/IIRFilterNode.js +139 -23
  23. package/js/MediaStreamAudioSourceNode.js +83 -24
  24. package/js/OfflineAudioContext.js +182 -34
  25. package/js/OscillatorNode.js +195 -32
  26. package/js/PannerNode.js +461 -56
  27. package/js/PeriodicWave.js +67 -3
  28. package/js/StereoPannerNode.js +107 -21
  29. package/js/WaveShaperNode.js +147 -29
  30. package/js/lib/cast.js +19 -0
  31. package/js/lib/errors.js +10 -55
  32. package/js/lib/events.js +20 -0
  33. package/js/lib/symbols.js +5 -0
  34. package/js/lib/utils.js +12 -12
  35. package/js/monkey-patch.js +32 -30
  36. package/node-web-audio-api.darwin-arm64.node +0 -0
  37. package/node-web-audio-api.darwin-x64.node +0 -0
  38. package/node-web-audio-api.linux-arm-gnueabihf.node +0 -0
  39. package/node-web-audio-api.linux-arm64-gnu.node +0 -0
  40. package/node-web-audio-api.linux-x64-gnu.node +0 -0
  41. package/node-web-audio-api.win32-arm64-msvc.node +0 -0
  42. package/node-web-audio-api.win32-x64-msvc.node +0 -0
  43. package/package.json +7 -4
  44. package/run-wpt.md +27 -0
  45. package/run-wpt.sh +5 -0
  46. package/js/AudioNode.mixin.js +0 -132
  47. package/js/AudioScheduledSourceNode.mixin.js +0 -67
  48. package/js/BaseAudioContext.mixin.js +0 -154
  49. package/js/EventTarget.mixin.js +0 -60
@@ -0,0 +1,419 @@
1
+ // -------------------------------------------------------------------------- //
2
+ // -------------------------------------------------------------------------- //
3
+ // //
4
+ // //
5
+ // //
6
+ // ██╗ ██╗ █████╗ ██████╗ ███╗ ██╗██╗███╗ ██╗ ██████╗ //
7
+ // ██║ ██║██╔══██╗██╔══██╗████╗ ██║██║████╗ ██║██╔════╝ //
8
+ // ██║ █╗ ██║███████║██████╔╝██╔██╗ ██║██║██╔██╗ ██║██║ ███╗ //
9
+ // ██║███╗██║██╔══██║██╔══██╗██║╚██╗██║██║██║╚██╗██║██║ ██║ //
10
+ // ╚███╔███╔╝██║ ██║██║ ██║██║ ╚████║██║██║ ╚████║╚██████╔╝ //
11
+ // ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═══╝ ╚═════╝ //
12
+ // //
13
+ // //
14
+ // - This file has been generated --------------------------- //
15
+ // //
16
+ // //
17
+ // -------------------------------------------------------------------------- //
18
+ // -------------------------------------------------------------------------- //
19
+
20
+ const {
21
+ isFunction,
22
+ kEnumerableProperty,
23
+ kHiddenProperty,
24
+ } = require('./lib/utils.js');
25
+ const {
26
+ kNapiObj,
27
+ } = require('./lib/symbols.js');
28
+
29
+ module.exports = (jsExport, _nativeBinding) => {
30
+ class BaseAudioContext extends EventTarget {
31
+ #listener = null;
32
+ #destination = null;
33
+
34
+ constructor(options) {
35
+ // Make constructor "private"
36
+ if (
37
+ (typeof options !== 'object') ||
38
+ !(kNapiObj in options)
39
+ ) {
40
+ throw new TypeError('Illegal constructor');
41
+ }
42
+
43
+ super();
44
+
45
+ Object.defineProperty(this, kNapiObj, {
46
+ value: options[kNapiObj],
47
+ ...kHiddenProperty,
48
+ });
49
+
50
+ this.#listener = null; // lazily instanciated
51
+ this.#destination = new jsExport.AudioDestinationNode(this, {
52
+ [kNapiObj]: this[kNapiObj].destination,
53
+ });
54
+ }
55
+
56
+ get listener() {
57
+ if (!(this instanceof BaseAudioContext)) {
58
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
59
+ }
60
+
61
+ if (this.#listener === null) {
62
+ this.#listener = new jsExport.AudioListener({
63
+ [kNapiObj]: this[kNapiObj].listener,
64
+ });
65
+ }
66
+
67
+ return this.#listener;
68
+ }
69
+
70
+ get destination() {
71
+ if (!(this instanceof BaseAudioContext)) {
72
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
73
+ }
74
+
75
+ return this.#destination;
76
+ }
77
+
78
+ get sampleRate() {
79
+ if (!(this instanceof BaseAudioContext)) {
80
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
81
+ }
82
+
83
+ return this[kNapiObj].sampleRate;
84
+ }
85
+
86
+ get currentTime() {
87
+ if (!(this instanceof BaseAudioContext)) {
88
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
89
+ }
90
+
91
+ return this[kNapiObj].currentTime;
92
+ }
93
+
94
+ get state() {
95
+ if (!(this instanceof BaseAudioContext)) {
96
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
97
+ }
98
+
99
+ return this[kNapiObj].state;
100
+ }
101
+
102
+ // renderQuantumSize
103
+ // audioWorklet
104
+
105
+ get onstatechange() {
106
+ if (!(this instanceof BaseAudioContext)) {
107
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
108
+ }
109
+
110
+ return this._statechange || null;
111
+ }
112
+
113
+ set onstatechange(value) {
114
+ if (!(this instanceof BaseAudioContext)) {
115
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
116
+ }
117
+
118
+ if (isFunction(value) || value === null) {
119
+ this._statechange = value;
120
+ }
121
+ }
122
+
123
+ // This is not exactly what the spec says, but if we reject the promise
124
+ // when decodeErrorCallback is present the program will crash in an
125
+ // unexpected manner
126
+ // cf. https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-decodeaudiodata
127
+ async decodeAudioData(arrayBuffer, decodeSuccessCallback = undefined, decodeErrorCallback = undefined) {
128
+ if (!(this instanceof BaseAudioContext)) {
129
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
130
+ }
131
+
132
+ if (arguments.length < 1) {
133
+ throw new TypeError(`Failed to execute 'decodeAudioData' on 'BaseAudioContext': 1 argument required, but only ${arguments.length} present`);
134
+ }
135
+
136
+ if (!(arrayBuffer instanceof ArrayBuffer)) {
137
+ throw new TypeError('Failed to execute "decodeAudioData": parameter 1 is not of type "ArrayBuffer"');
138
+ }
139
+
140
+ try {
141
+ const nativeAudioBuffer = await this[kNapiObj].decodeAudioData(arrayBuffer);
142
+ const audioBuffer = new jsExport.AudioBuffer({
143
+ [kNapiObj]: nativeAudioBuffer,
144
+ });
145
+
146
+ if (isFunction(decodeSuccessCallback)) {
147
+ decodeSuccessCallback(audioBuffer);
148
+ } else {
149
+ return audioBuffer;
150
+ }
151
+ } catch (err) {
152
+ const error = new DOMException(`Failed to execute 'decodeAudioData': ${err.message}`, 'EncodingError');
153
+
154
+ if (isFunction(decodeErrorCallback)) {
155
+ decodeErrorCallback(error);
156
+ } else {
157
+ throw error;
158
+ }
159
+ }
160
+ }
161
+
162
+ createBuffer(numberOfChannels, length, sampleRate) {
163
+ if (!(this instanceof BaseAudioContext)) {
164
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
165
+ }
166
+
167
+ if (arguments.length < 3) {
168
+ throw new TypeError(`Failed to execute 'createBuffer' on 'BaseAudioContext': 3 argument required, but only ${arguments.length} present`);
169
+ }
170
+
171
+ const options = {};
172
+
173
+ if (numberOfChannels !== undefined) {
174
+ options.numberOfChannels = numberOfChannels;
175
+ }
176
+
177
+ if (length !== undefined) {
178
+ options.length = length;
179
+ }
180
+
181
+ if (sampleRate !== undefined) {
182
+ options.sampleRate = sampleRate;
183
+ }
184
+
185
+ return new jsExport.AudioBuffer(options);
186
+ }
187
+
188
+ createPeriodicWave(real, imag) {
189
+ if (!(this instanceof BaseAudioContext)) {
190
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
191
+ }
192
+
193
+ if (arguments.length < 2) {
194
+ throw new TypeError(`Failed to execute 'createPeriodicWave' on 'BaseAudioContext': 2 argument required, but only ${arguments.length} present`);
195
+ }
196
+
197
+ const options = {};
198
+
199
+ if (real !== undefined) {
200
+ options.real = real;
201
+ }
202
+
203
+ if (imag !== undefined) {
204
+ options.imag = imag;
205
+ }
206
+
207
+ return new jsExport.PeriodicWave(this, options);
208
+ }
209
+
210
+ // --------------------------------------------------------------------
211
+ // Factory Methods (use the patched AudioNodes)
212
+ // --------------------------------------------------------------------
213
+ createAnalyser() {
214
+ if (!(this instanceof BaseAudioContext)) {
215
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
216
+ }
217
+
218
+ const options = {};
219
+
220
+ return new jsExport.AnalyserNode(this, options);
221
+ }
222
+
223
+ createBufferSource() {
224
+ if (!(this instanceof BaseAudioContext)) {
225
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
226
+ }
227
+
228
+ const options = {};
229
+
230
+ return new jsExport.AudioBufferSourceNode(this, options);
231
+ }
232
+
233
+ createBiquadFilter() {
234
+ if (!(this instanceof BaseAudioContext)) {
235
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
236
+ }
237
+
238
+ const options = {};
239
+
240
+ return new jsExport.BiquadFilterNode(this, options);
241
+ }
242
+
243
+ createChannelMerger(numberOfInputs = 6) {
244
+ if (!(this instanceof BaseAudioContext)) {
245
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
246
+ }
247
+
248
+ const options = {
249
+ numberOfInputs,
250
+ };
251
+
252
+ return new jsExport.ChannelMergerNode(this, options);
253
+ }
254
+
255
+ createChannelSplitter(numberOfOutputs = 6) {
256
+ if (!(this instanceof BaseAudioContext)) {
257
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
258
+ }
259
+
260
+ const options = {
261
+ numberOfOutputs,
262
+ };
263
+
264
+ return new jsExport.ChannelSplitterNode(this, options);
265
+ }
266
+
267
+ createConstantSource() {
268
+ if (!(this instanceof BaseAudioContext)) {
269
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
270
+ }
271
+
272
+ const options = {};
273
+
274
+ return new jsExport.ConstantSourceNode(this, options);
275
+ }
276
+
277
+ createConvolver() {
278
+ if (!(this instanceof BaseAudioContext)) {
279
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
280
+ }
281
+
282
+ const options = {};
283
+
284
+ return new jsExport.ConvolverNode(this, options);
285
+ }
286
+
287
+ createDelay(maxDelayTime = 1.0) {
288
+ if (!(this instanceof BaseAudioContext)) {
289
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
290
+ }
291
+
292
+ const options = {
293
+ maxDelayTime,
294
+ };
295
+
296
+ return new jsExport.DelayNode(this, options);
297
+ }
298
+
299
+ createDynamicsCompressor() {
300
+ if (!(this instanceof BaseAudioContext)) {
301
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
302
+ }
303
+
304
+ const options = {};
305
+
306
+ return new jsExport.DynamicsCompressorNode(this, options);
307
+ }
308
+
309
+ createGain() {
310
+ if (!(this instanceof BaseAudioContext)) {
311
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
312
+ }
313
+
314
+ const options = {};
315
+
316
+ return new jsExport.GainNode(this, options);
317
+ }
318
+
319
+ createIIRFilter(feedforward, feedback) {
320
+ if (!(this instanceof BaseAudioContext)) {
321
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
322
+ }
323
+
324
+ const options = {
325
+ feedforward,
326
+ feedback,
327
+ };
328
+
329
+ return new jsExport.IIRFilterNode(this, options);
330
+ }
331
+
332
+ createOscillator() {
333
+ if (!(this instanceof BaseAudioContext)) {
334
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
335
+ }
336
+
337
+ const options = {};
338
+
339
+ return new jsExport.OscillatorNode(this, options);
340
+ }
341
+
342
+ createPanner() {
343
+ if (!(this instanceof BaseAudioContext)) {
344
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
345
+ }
346
+
347
+ const options = {};
348
+
349
+ return new jsExport.PannerNode(this, options);
350
+ }
351
+
352
+ createStereoPanner() {
353
+ if (!(this instanceof BaseAudioContext)) {
354
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
355
+ }
356
+
357
+ const options = {};
358
+
359
+ return new jsExport.StereoPannerNode(this, options);
360
+ }
361
+
362
+ createWaveShaper() {
363
+ if (!(this instanceof BaseAudioContext)) {
364
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BaseAudioContext\'');
365
+ }
366
+
367
+ const options = {};
368
+
369
+ return new jsExport.WaveShaperNode(this, options);
370
+ }
371
+
372
+ }
373
+
374
+ Object.defineProperties(BaseAudioContext, {
375
+ length: {
376
+ __proto__: null,
377
+ writable: false,
378
+ enumerable: false,
379
+ configurable: true,
380
+ value: 0,
381
+ },
382
+ });
383
+
384
+ Object.defineProperties(BaseAudioContext.prototype, {
385
+ [Symbol.toStringTag]: {
386
+ __proto__: null,
387
+ writable: false,
388
+ enumerable: false,
389
+ configurable: true,
390
+ value: 'BaseAudioContext',
391
+ },
392
+ createAnalyser: kEnumerableProperty,
393
+ createBufferSource: kEnumerableProperty,
394
+ createBiquadFilter: kEnumerableProperty,
395
+ createChannelMerger: kEnumerableProperty,
396
+ createChannelSplitter: kEnumerableProperty,
397
+ createConstantSource: kEnumerableProperty,
398
+ createConvolver: kEnumerableProperty,
399
+ createDelay: kEnumerableProperty,
400
+ createDynamicsCompressor: kEnumerableProperty,
401
+ createGain: kEnumerableProperty,
402
+ createIIRFilter: kEnumerableProperty,
403
+ createOscillator: kEnumerableProperty,
404
+ createPanner: kEnumerableProperty,
405
+ createStereoPanner: kEnumerableProperty,
406
+ createWaveShaper: kEnumerableProperty,
407
+ listener: kEnumerableProperty,
408
+ destination: kEnumerableProperty,
409
+ sampleRate: kEnumerableProperty,
410
+ currentTime: kEnumerableProperty,
411
+ state: kEnumerableProperty,
412
+ onstatechange: kEnumerableProperty,
413
+ decodeAudioData: kEnumerableProperty,
414
+ createBuffer: kEnumerableProperty,
415
+ createPeriodicWave: kEnumerableProperty,
416
+ });
417
+
418
+ return BaseAudioContext;
419
+ };
@@ -17,54 +17,223 @@
17
17
  // -------------------------------------------------------------------------- //
18
18
  // -------------------------------------------------------------------------- //
19
19
 
20
- // eslint-disable-next-line no-unused-vars
21
- const { throwSanitizedError } = require('./lib/errors.js');
22
- // eslint-disable-next-line no-unused-vars
23
- const { AudioParam } = require('./AudioParam.js');
24
- const EventTargetMixin = require('./EventTarget.mixin.js');
25
- const AudioNodeMixin = require('./AudioNode.mixin.js');
20
+ /* eslint-disable no-unused-vars */
21
+ const conversions = require('webidl-conversions');
22
+ const {
23
+ toSanitizedSequence,
24
+ } = require('./lib/cast.js');
25
+ const {
26
+ isFunction,
27
+ kEnumerableProperty,
28
+ } = require('./lib/utils.js');
29
+ const {
30
+ throwSanitizedError,
31
+ } = require('./lib/errors.js');
32
+ const {
33
+ kNapiObj,
34
+ kAudioBuffer,
35
+ } = require('./lib/symbols.js');
36
+ const {
37
+ bridgeEventTarget,
38
+ } = require('./lib/events.js');
39
+ /* eslint-enable no-unused-vars */
26
40
 
41
+ const AudioNode = require('./AudioNode.js');
27
42
 
28
- module.exports = (NativeBiquadFilterNode) => {
43
+ module.exports = (jsExport, nativeBinding) => {
44
+ class BiquadFilterNode extends AudioNode {
29
45
 
30
- const EventTarget = EventTargetMixin(NativeBiquadFilterNode);
31
- const AudioNode = AudioNodeMixin(EventTarget);
46
+ #frequency = null;
47
+ #detune = null;
48
+ #Q = null;
49
+ #gain = null;
32
50
 
33
- class BiquadFilterNode extends AudioNode {
34
51
  constructor(context, options) {
35
- if (options !== undefined && typeof options !== 'object') {
36
- throw new TypeError("Failed to construct 'BiquadFilterNode': argument 2 is not of type 'BiquadFilterOptions'")
52
+
53
+ if (arguments.length < 1) {
54
+ throw new TypeError(`Failed to construct 'BiquadFilterNode': 1 argument required, but only ${arguments.length} present`);
55
+ }
56
+
57
+ if (!(context instanceof jsExport.BaseAudioContext)) {
58
+ throw new TypeError(`Failed to construct 'BiquadFilterNode': argument 1 is not of type BaseAudioContext`);
59
+ }
60
+
61
+ // parsed version of the option to be passed to NAPI
62
+ const parsedOptions = {};
63
+
64
+ if (options && typeof options !== 'object') {
65
+ throw new TypeError('Failed to construct \'BiquadFilterNode\': argument 2 is not of type \'BiquadFilterOptions\'');
66
+ }
67
+
68
+ if (options && options.type !== undefined) {
69
+ if (!['lowpass', 'highpass', 'bandpass', 'lowshelf', 'highshelf', 'peaking', 'notch', 'allpass'].includes(options.type)) {
70
+ throw new TypeError(`Failed to construct 'BiquadFilterNode': Failed to read the 'type' property from BiquadFilterOptions: The provided value '${options.type}' is not a valid enum value of type BiquadFilterType`);
71
+ }
72
+
73
+ parsedOptions.type = conversions['DOMString'](options.type, {
74
+ context: `Failed to construct 'BiquadFilterNode': Failed to read the 'type' property from BiquadFilterOptions: The provided value '${options.type}'`,
75
+ });
76
+ } else {
77
+ parsedOptions.type = 'lowpass';
78
+ }
79
+
80
+ if (options && options.Q !== undefined) {
81
+ parsedOptions.Q = conversions['float'](options.Q, {
82
+ context: `Failed to construct 'BiquadFilterNode': Failed to read the 'Q' property from BiquadFilterOptions: The provided value (${options.Q}})`,
83
+ });
84
+ } else {
85
+ parsedOptions.Q = 1;
86
+ }
87
+
88
+ if (options && options.detune !== undefined) {
89
+ parsedOptions.detune = conversions['float'](options.detune, {
90
+ context: `Failed to construct 'BiquadFilterNode': Failed to read the 'detune' property from BiquadFilterOptions: The provided value (${options.detune}})`,
91
+ });
92
+ } else {
93
+ parsedOptions.detune = 0;
94
+ }
95
+
96
+ if (options && options.frequency !== undefined) {
97
+ parsedOptions.frequency = conversions['float'](options.frequency, {
98
+ context: `Failed to construct 'BiquadFilterNode': Failed to read the 'frequency' property from BiquadFilterOptions: The provided value (${options.frequency}})`,
99
+ });
100
+ } else {
101
+ parsedOptions.frequency = 350;
37
102
  }
38
103
 
39
- super(context, options);
104
+ if (options && options.gain !== undefined) {
105
+ parsedOptions.gain = conversions['float'](options.gain, {
106
+ context: `Failed to construct 'BiquadFilterNode': Failed to read the 'gain' property from BiquadFilterOptions: The provided value (${options.gain}})`,
107
+ });
108
+ } else {
109
+ parsedOptions.gain = 0;
110
+ }
111
+
112
+ if (options && options.channelCount !== undefined) {
113
+ parsedOptions.channelCount = conversions['unsigned long'](options.channelCount, {
114
+ enforceRange: true,
115
+ context: `Failed to construct 'BiquadFilterNode': Failed to read the 'channelCount' property from BiquadFilterOptions: The provided value '${options.channelCount}'`,
116
+ });
117
+ }
118
+
119
+ if (options && options.channelCountMode !== undefined) {
120
+ parsedOptions.channelCountMode = conversions['DOMString'](options.channelCountMode, {
121
+ context: `Failed to construct 'BiquadFilterNode': Failed to read the 'channelCount' property from BiquadFilterOptions: The provided value '${options.channelCountMode}'`,
122
+ });
123
+ }
40
124
 
41
- this.frequency = new AudioParam(this.frequency);
42
- this.detune = new AudioParam(this.detune);
43
- this.Q = new AudioParam(this.Q);
44
- this.gain = new AudioParam(this.gain);
125
+ if (options && options.channelInterpretation !== undefined) {
126
+ parsedOptions.channelInterpretation = conversions['DOMString'](options.channelInterpretation, {
127
+ context: `Failed to construct 'BiquadFilterNode': Failed to read the 'channelInterpretation' property from BiquadFilterOptions: The provided value '${options.channelInterpretation}'`,
128
+ });
129
+ }
130
+
131
+ let napiObj;
132
+
133
+ try {
134
+ napiObj = new nativeBinding.BiquadFilterNode(context[kNapiObj], parsedOptions);
135
+ } catch (err) {
136
+ throwSanitizedError(err);
137
+ }
138
+
139
+ super(context, {
140
+ [kNapiObj]: napiObj,
141
+ });
142
+
143
+ this.#frequency = new jsExport.AudioParam({
144
+ [kNapiObj]: this[kNapiObj].frequency,
145
+ });
146
+ this.#detune = new jsExport.AudioParam({
147
+ [kNapiObj]: this[kNapiObj].detune,
148
+ });
149
+ this.#Q = new jsExport.AudioParam({
150
+ [kNapiObj]: this[kNapiObj].Q,
151
+ });
152
+ this.#gain = new jsExport.AudioParam({
153
+ [kNapiObj]: this[kNapiObj].gain,
154
+ });
45
155
  }
46
156
 
47
- // getters
157
+ get frequency() {
158
+ if (!(this instanceof BiquadFilterNode)) {
159
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BiquadFilterNode\'');
160
+ }
48
161
 
49
- get type() {
50
- return super.type;
162
+ return this.#frequency;
51
163
  }
52
164
 
53
- // setters
165
+ get detune() {
166
+ if (!(this instanceof BiquadFilterNode)) {
167
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BiquadFilterNode\'');
168
+ }
169
+
170
+ return this.#detune;
171
+ }
172
+
173
+ get Q() {
174
+ if (!(this instanceof BiquadFilterNode)) {
175
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BiquadFilterNode\'');
176
+ }
177
+
178
+ return this.#Q;
179
+ }
180
+
181
+ get gain() {
182
+ if (!(this instanceof BiquadFilterNode)) {
183
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BiquadFilterNode\'');
184
+ }
185
+
186
+ return this.#gain;
187
+ }
188
+
189
+ get type() {
190
+ if (!(this instanceof BiquadFilterNode)) {
191
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BiquadFilterNode\'');
192
+ }
193
+
194
+ return this[kNapiObj].type;
195
+ }
54
196
 
55
197
  set type(value) {
198
+ if (!(this instanceof BiquadFilterNode)) {
199
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BiquadFilterNode\'');
200
+ }
201
+
202
+ if (!['lowpass', 'highpass', 'bandpass', 'lowshelf', 'highshelf', 'peaking', 'notch', 'allpass'].includes(value)) {
203
+ console.warn(`Failed to set the 'type' property on 'BiquadFilterNode': Value '${value}' is not a valid 'BiquadFilterType' enum value`);
204
+ return;
205
+ }
206
+
56
207
  try {
57
- super.type = value;
208
+ this[kNapiObj].type = value;
58
209
  } catch (err) {
59
210
  throwSanitizedError(err);
60
211
  }
61
212
  }
62
213
 
63
- // methods
64
-
65
- getFrequencyResponse(...args) {
214
+ getFrequencyResponse(frequencyHz, magResponse, phaseResponse) {
215
+ if (!(this instanceof BiquadFilterNode)) {
216
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BiquadFilterNode\'');
217
+ }
218
+
219
+ if (arguments.length < 3) {
220
+ throw new TypeError(`Failed to execute 'getFrequencyResponse' on 'BiquadFilterNode': 3 argument required, but only ${arguments.length} present`);
221
+ }
222
+
223
+ if (!(frequencyHz instanceof Float32Array)) {
224
+ throw new TypeError(`Failed to execute 'getFrequencyResponse' on 'BiquadFilterNode': Parameter 1 is not of type 'Float32Array'`);
225
+ }
226
+
227
+ if (!(magResponse instanceof Float32Array)) {
228
+ throw new TypeError(`Failed to execute 'getFrequencyResponse' on 'BiquadFilterNode': Parameter 2 is not of type 'Float32Array'`);
229
+ }
230
+
231
+ if (!(phaseResponse instanceof Float32Array)) {
232
+ throw new TypeError(`Failed to execute 'getFrequencyResponse' on 'BiquadFilterNode': Parameter 3 is not of type 'Float32Array'`);
233
+ }
234
+
66
235
  try {
67
- return super.getFrequencyResponse(...args);
236
+ return this[kNapiObj].getFrequencyResponse(frequencyHz, magResponse, phaseResponse);
68
237
  } catch (err) {
69
238
  throwSanitizedError(err);
70
239
  }
@@ -72,8 +241,31 @@ module.exports = (NativeBiquadFilterNode) => {
72
241
 
73
242
  }
74
243
 
75
- return BiquadFilterNode;
76
- };
244
+ Object.defineProperties(BiquadFilterNode, {
245
+ length: {
246
+ __proto__: null,
247
+ writable: false,
248
+ enumerable: false,
249
+ configurable: true,
250
+ value: 1,
251
+ },
252
+ });
77
253
 
254
+ Object.defineProperties(BiquadFilterNode.prototype, {
255
+ [Symbol.toStringTag]: {
256
+ __proto__: null,
257
+ writable: false,
258
+ enumerable: false,
259
+ configurable: true,
260
+ value: 'BiquadFilterNode',
261
+ },
262
+ frequency: kEnumerableProperty,
263
+ detune: kEnumerableProperty,
264
+ Q: kEnumerableProperty,
265
+ gain: kEnumerableProperty,
266
+ type: kEnumerableProperty,
267
+ getFrequencyResponse: kEnumerableProperty,
268
+ });
78
269
 
79
-
270
+ return BiquadFilterNode;
271
+ };