node-web-audio-api 0.18.0 → 0.20.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 (51) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/TODOS.md +134 -12
  3. package/index.mjs +17 -6
  4. package/js/AnalyserNode.js +259 -48
  5. package/js/AudioBuffer.js +243 -0
  6. package/js/AudioBufferSourceNode.js +259 -41
  7. package/js/AudioContext.js +294 -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 +120 -0
  13. package/js/BaseAudioContext.js +434 -0
  14. package/js/BiquadFilterNode.js +218 -29
  15. package/js/ChannelMergerNode.js +93 -22
  16. package/js/ChannelSplitterNode.js +93 -22
  17. package/js/ConstantSourceNode.js +86 -26
  18. package/js/ConvolverNode.js +158 -29
  19. package/js/DelayNode.js +112 -21
  20. package/js/DynamicsCompressorNode.js +195 -27
  21. package/js/Events.js +84 -0
  22. package/js/GainNode.js +104 -21
  23. package/js/IIRFilterNode.js +136 -23
  24. package/js/MediaStreamAudioSourceNode.js +80 -24
  25. package/js/OfflineAudioContext.js +198 -35
  26. package/js/OscillatorNode.js +189 -32
  27. package/js/PannerNode.js +458 -56
  28. package/js/PeriodicWave.js +67 -3
  29. package/js/ScriptProcessorNode.js +179 -0
  30. package/js/StereoPannerNode.js +104 -21
  31. package/js/WaveShaperNode.js +144 -29
  32. package/js/lib/cast.js +19 -0
  33. package/js/lib/errors.js +10 -55
  34. package/js/lib/events.js +10 -0
  35. package/js/lib/symbols.js +20 -0
  36. package/js/lib/utils.js +12 -12
  37. package/js/monkey-patch.js +40 -31
  38. package/node-web-audio-api.darwin-arm64.node +0 -0
  39. package/node-web-audio-api.darwin-x64.node +0 -0
  40. package/node-web-audio-api.linux-arm-gnueabihf.node +0 -0
  41. package/node-web-audio-api.linux-arm64-gnu.node +0 -0
  42. package/node-web-audio-api.linux-x64-gnu.node +0 -0
  43. package/node-web-audio-api.win32-arm64-msvc.node +0 -0
  44. package/node-web-audio-api.win32-x64-msvc.node +0 -0
  45. package/package.json +7 -4
  46. package/run-wpt.md +27 -0
  47. package/run-wpt.sh +5 -0
  48. package/js/AudioNode.mixin.js +0 -132
  49. package/js/AudioScheduledSourceNode.mixin.js +0 -67
  50. package/js/BaseAudioContext.mixin.js +0 -154
  51. package/js/EventTarget.mixin.js +0 -60
@@ -17,54 +17,220 @@
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
+ /* eslint-enable no-unused-vars */
26
37
 
38
+ const AudioNode = require('./AudioNode.js');
27
39
 
28
- module.exports = (NativeBiquadFilterNode) => {
40
+ module.exports = (jsExport, nativeBinding) => {
41
+ class BiquadFilterNode extends AudioNode {
29
42
 
30
- const EventTarget = EventTargetMixin(NativeBiquadFilterNode);
31
- const AudioNode = AudioNodeMixin(EventTarget);
43
+ #frequency = null;
44
+ #detune = null;
45
+ #Q = null;
46
+ #gain = null;
32
47
 
33
- class BiquadFilterNode extends AudioNode {
34
48
  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'")
49
+
50
+ if (arguments.length < 1) {
51
+ throw new TypeError(`Failed to construct 'BiquadFilterNode': 1 argument required, but only ${arguments.length} present`);
52
+ }
53
+
54
+ if (!(context instanceof jsExport.BaseAudioContext)) {
55
+ throw new TypeError(`Failed to construct 'BiquadFilterNode': argument 1 is not of type BaseAudioContext`);
56
+ }
57
+
58
+ // parsed version of the option to be passed to NAPI
59
+ const parsedOptions = {};
60
+
61
+ if (options && typeof options !== 'object') {
62
+ throw new TypeError('Failed to construct \'BiquadFilterNode\': argument 2 is not of type \'BiquadFilterOptions\'');
63
+ }
64
+
65
+ if (options && options.type !== undefined) {
66
+ if (!['lowpass', 'highpass', 'bandpass', 'lowshelf', 'highshelf', 'peaking', 'notch', 'allpass'].includes(options.type)) {
67
+ 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`);
68
+ }
69
+
70
+ parsedOptions.type = conversions['DOMString'](options.type, {
71
+ context: `Failed to construct 'BiquadFilterNode': Failed to read the 'type' property from BiquadFilterOptions: The provided value '${options.type}'`,
72
+ });
73
+ } else {
74
+ parsedOptions.type = 'lowpass';
75
+ }
76
+
77
+ if (options && options.Q !== undefined) {
78
+ parsedOptions.Q = conversions['float'](options.Q, {
79
+ context: `Failed to construct 'BiquadFilterNode': Failed to read the 'Q' property from BiquadFilterOptions: The provided value (${options.Q}})`,
80
+ });
81
+ } else {
82
+ parsedOptions.Q = 1;
83
+ }
84
+
85
+ if (options && options.detune !== undefined) {
86
+ parsedOptions.detune = conversions['float'](options.detune, {
87
+ context: `Failed to construct 'BiquadFilterNode': Failed to read the 'detune' property from BiquadFilterOptions: The provided value (${options.detune}})`,
88
+ });
89
+ } else {
90
+ parsedOptions.detune = 0;
91
+ }
92
+
93
+ if (options && options.frequency !== undefined) {
94
+ parsedOptions.frequency = conversions['float'](options.frequency, {
95
+ context: `Failed to construct 'BiquadFilterNode': Failed to read the 'frequency' property from BiquadFilterOptions: The provided value (${options.frequency}})`,
96
+ });
97
+ } else {
98
+ parsedOptions.frequency = 350;
37
99
  }
38
100
 
39
- super(context, options);
101
+ if (options && options.gain !== undefined) {
102
+ parsedOptions.gain = conversions['float'](options.gain, {
103
+ context: `Failed to construct 'BiquadFilterNode': Failed to read the 'gain' property from BiquadFilterOptions: The provided value (${options.gain}})`,
104
+ });
105
+ } else {
106
+ parsedOptions.gain = 0;
107
+ }
108
+
109
+ if (options && options.channelCount !== undefined) {
110
+ parsedOptions.channelCount = conversions['unsigned long'](options.channelCount, {
111
+ enforceRange: true,
112
+ context: `Failed to construct 'BiquadFilterNode': Failed to read the 'channelCount' property from BiquadFilterOptions: The provided value '${options.channelCount}'`,
113
+ });
114
+ }
115
+
116
+ if (options && options.channelCountMode !== undefined) {
117
+ parsedOptions.channelCountMode = conversions['DOMString'](options.channelCountMode, {
118
+ context: `Failed to construct 'BiquadFilterNode': Failed to read the 'channelCount' property from BiquadFilterOptions: The provided value '${options.channelCountMode}'`,
119
+ });
120
+ }
40
121
 
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);
122
+ if (options && options.channelInterpretation !== undefined) {
123
+ parsedOptions.channelInterpretation = conversions['DOMString'](options.channelInterpretation, {
124
+ context: `Failed to construct 'BiquadFilterNode': Failed to read the 'channelInterpretation' property from BiquadFilterOptions: The provided value '${options.channelInterpretation}'`,
125
+ });
126
+ }
127
+
128
+ let napiObj;
129
+
130
+ try {
131
+ napiObj = new nativeBinding.BiquadFilterNode(context[kNapiObj], parsedOptions);
132
+ } catch (err) {
133
+ throwSanitizedError(err);
134
+ }
135
+
136
+ super(context, {
137
+ [kNapiObj]: napiObj,
138
+ });
139
+
140
+ this.#frequency = new jsExport.AudioParam({
141
+ [kNapiObj]: this[kNapiObj].frequency,
142
+ });
143
+ this.#detune = new jsExport.AudioParam({
144
+ [kNapiObj]: this[kNapiObj].detune,
145
+ });
146
+ this.#Q = new jsExport.AudioParam({
147
+ [kNapiObj]: this[kNapiObj].Q,
148
+ });
149
+ this.#gain = new jsExport.AudioParam({
150
+ [kNapiObj]: this[kNapiObj].gain,
151
+ });
45
152
  }
46
153
 
47
- // getters
154
+ get frequency() {
155
+ if (!(this instanceof BiquadFilterNode)) {
156
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BiquadFilterNode\'');
157
+ }
48
158
 
49
- get type() {
50
- return super.type;
159
+ return this.#frequency;
51
160
  }
52
161
 
53
- // setters
162
+ get detune() {
163
+ if (!(this instanceof BiquadFilterNode)) {
164
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BiquadFilterNode\'');
165
+ }
166
+
167
+ return this.#detune;
168
+ }
169
+
170
+ get Q() {
171
+ if (!(this instanceof BiquadFilterNode)) {
172
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BiquadFilterNode\'');
173
+ }
174
+
175
+ return this.#Q;
176
+ }
177
+
178
+ get gain() {
179
+ if (!(this instanceof BiquadFilterNode)) {
180
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BiquadFilterNode\'');
181
+ }
182
+
183
+ return this.#gain;
184
+ }
185
+
186
+ get type() {
187
+ if (!(this instanceof BiquadFilterNode)) {
188
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BiquadFilterNode\'');
189
+ }
190
+
191
+ return this[kNapiObj].type;
192
+ }
54
193
 
55
194
  set type(value) {
195
+ if (!(this instanceof BiquadFilterNode)) {
196
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BiquadFilterNode\'');
197
+ }
198
+
199
+ if (!['lowpass', 'highpass', 'bandpass', 'lowshelf', 'highshelf', 'peaking', 'notch', 'allpass'].includes(value)) {
200
+ console.warn(`Failed to set the 'type' property on 'BiquadFilterNode': Value '${value}' is not a valid 'BiquadFilterType' enum value`);
201
+ return;
202
+ }
203
+
56
204
  try {
57
- super.type = value;
205
+ this[kNapiObj].type = value;
58
206
  } catch (err) {
59
207
  throwSanitizedError(err);
60
208
  }
61
209
  }
62
210
 
63
- // methods
64
-
65
- getFrequencyResponse(...args) {
211
+ getFrequencyResponse(frequencyHz, magResponse, phaseResponse) {
212
+ if (!(this instanceof BiquadFilterNode)) {
213
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'BiquadFilterNode\'');
214
+ }
215
+
216
+ if (arguments.length < 3) {
217
+ throw new TypeError(`Failed to execute 'getFrequencyResponse' on 'BiquadFilterNode': 3 argument required, but only ${arguments.length} present`);
218
+ }
219
+
220
+ if (!(frequencyHz instanceof Float32Array)) {
221
+ throw new TypeError(`Failed to execute 'getFrequencyResponse' on 'BiquadFilterNode': Parameter 1 is not of type 'Float32Array'`);
222
+ }
223
+
224
+ if (!(magResponse instanceof Float32Array)) {
225
+ throw new TypeError(`Failed to execute 'getFrequencyResponse' on 'BiquadFilterNode': Parameter 2 is not of type 'Float32Array'`);
226
+ }
227
+
228
+ if (!(phaseResponse instanceof Float32Array)) {
229
+ throw new TypeError(`Failed to execute 'getFrequencyResponse' on 'BiquadFilterNode': Parameter 3 is not of type 'Float32Array'`);
230
+ }
231
+
66
232
  try {
67
- return super.getFrequencyResponse(...args);
233
+ return this[kNapiObj].getFrequencyResponse(frequencyHz, magResponse, phaseResponse);
68
234
  } catch (err) {
69
235
  throwSanitizedError(err);
70
236
  }
@@ -72,8 +238,31 @@ module.exports = (NativeBiquadFilterNode) => {
72
238
 
73
239
  }
74
240
 
75
- return BiquadFilterNode;
76
- };
241
+ Object.defineProperties(BiquadFilterNode, {
242
+ length: {
243
+ __proto__: null,
244
+ writable: false,
245
+ enumerable: false,
246
+ configurable: true,
247
+ value: 1,
248
+ },
249
+ });
77
250
 
251
+ Object.defineProperties(BiquadFilterNode.prototype, {
252
+ [Symbol.toStringTag]: {
253
+ __proto__: null,
254
+ writable: false,
255
+ enumerable: false,
256
+ configurable: true,
257
+ value: 'BiquadFilterNode',
258
+ },
259
+ frequency: kEnumerableProperty,
260
+ detune: kEnumerableProperty,
261
+ Q: kEnumerableProperty,
262
+ gain: kEnumerableProperty,
263
+ type: kEnumerableProperty,
264
+ getFrequencyResponse: kEnumerableProperty,
265
+ });
78
266
 
79
-
267
+ return BiquadFilterNode;
268
+ };
@@ -17,39 +17,110 @@
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
+ /* eslint-enable no-unused-vars */
26
37
 
38
+ const AudioNode = require('./AudioNode.js');
27
39
 
28
- module.exports = (NativeChannelMergerNode) => {
29
-
30
- const EventTarget = EventTargetMixin(NativeChannelMergerNode);
31
- const AudioNode = AudioNodeMixin(EventTarget);
32
-
40
+ module.exports = (jsExport, nativeBinding) => {
33
41
  class ChannelMergerNode extends AudioNode {
42
+
34
43
  constructor(context, options) {
35
- if (options !== undefined && typeof options !== 'object') {
36
- throw new TypeError("Failed to construct 'ChannelMergerNode': argument 2 is not of type 'ChannelMergerOptions'")
44
+
45
+ if (arguments.length < 1) {
46
+ throw new TypeError(`Failed to construct 'ChannelMergerNode': 1 argument required, but only ${arguments.length} present`);
37
47
  }
38
48
 
39
- super(context, options);
49
+ if (!(context instanceof jsExport.BaseAudioContext)) {
50
+ throw new TypeError(`Failed to construct 'ChannelMergerNode': argument 1 is not of type BaseAudioContext`);
51
+ }
40
52
 
41
- }
53
+ // parsed version of the option to be passed to NAPI
54
+ const parsedOptions = {};
42
55
 
43
- // getters
56
+ if (options && typeof options !== 'object') {
57
+ throw new TypeError('Failed to construct \'ChannelMergerNode\': argument 2 is not of type \'ChannelMergerOptions\'');
58
+ }
44
59
 
45
- // setters
60
+ if (options && options.numberOfInputs !== undefined) {
61
+ parsedOptions.numberOfInputs = conversions['unsigned long'](options.numberOfInputs, {
62
+ enforceRange: true,
63
+ context: `Failed to construct 'ChannelMergerNode': Failed to read the 'numberOfInputs' property from ChannelMergerOptions: The provided value (${options.numberOfInputs}})`,
64
+ });
65
+ } else {
66
+ parsedOptions.numberOfInputs = 6;
67
+ }
68
+
69
+ if (options && options.channelCount !== undefined) {
70
+ parsedOptions.channelCount = conversions['unsigned long'](options.channelCount, {
71
+ enforceRange: true,
72
+ context: `Failed to construct 'ChannelMergerNode': Failed to read the 'channelCount' property from ChannelMergerOptions: The provided value '${options.channelCount}'`,
73
+ });
74
+ }
75
+
76
+ if (options && options.channelCountMode !== undefined) {
77
+ parsedOptions.channelCountMode = conversions['DOMString'](options.channelCountMode, {
78
+ context: `Failed to construct 'ChannelMergerNode': Failed to read the 'channelCount' property from ChannelMergerOptions: The provided value '${options.channelCountMode}'`,
79
+ });
80
+ }
81
+
82
+ if (options && options.channelInterpretation !== undefined) {
83
+ parsedOptions.channelInterpretation = conversions['DOMString'](options.channelInterpretation, {
84
+ context: `Failed to construct 'ChannelMergerNode': Failed to read the 'channelInterpretation' property from ChannelMergerOptions: The provided value '${options.channelInterpretation}'`,
85
+ });
86
+ }
87
+
88
+ let napiObj;
89
+
90
+ try {
91
+ napiObj = new nativeBinding.ChannelMergerNode(context[kNapiObj], parsedOptions);
92
+ } catch (err) {
93
+ throwSanitizedError(err);
94
+ }
95
+
96
+ super(context, {
97
+ [kNapiObj]: napiObj,
98
+ });
99
+
100
+ }
46
101
 
47
- // methods
48
-
49
102
  }
50
103
 
51
- return ChannelMergerNode;
52
- };
104
+ Object.defineProperties(ChannelMergerNode, {
105
+ length: {
106
+ __proto__: null,
107
+ writable: false,
108
+ enumerable: false,
109
+ configurable: true,
110
+ value: 1,
111
+ },
112
+ });
53
113
 
114
+ Object.defineProperties(ChannelMergerNode.prototype, {
115
+ [Symbol.toStringTag]: {
116
+ __proto__: null,
117
+ writable: false,
118
+ enumerable: false,
119
+ configurable: true,
120
+ value: 'ChannelMergerNode',
121
+ },
54
122
 
55
-
123
+ });
124
+
125
+ return ChannelMergerNode;
126
+ };
@@ -17,39 +17,110 @@
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
+ /* eslint-enable no-unused-vars */
26
37
 
38
+ const AudioNode = require('./AudioNode.js');
27
39
 
28
- module.exports = (NativeChannelSplitterNode) => {
29
-
30
- const EventTarget = EventTargetMixin(NativeChannelSplitterNode);
31
- const AudioNode = AudioNodeMixin(EventTarget);
32
-
40
+ module.exports = (jsExport, nativeBinding) => {
33
41
  class ChannelSplitterNode extends AudioNode {
42
+
34
43
  constructor(context, options) {
35
- if (options !== undefined && typeof options !== 'object') {
36
- throw new TypeError("Failed to construct 'ChannelSplitterNode': argument 2 is not of type 'ChannelSplitterOptions'")
44
+
45
+ if (arguments.length < 1) {
46
+ throw new TypeError(`Failed to construct 'ChannelSplitterNode': 1 argument required, but only ${arguments.length} present`);
37
47
  }
38
48
 
39
- super(context, options);
49
+ if (!(context instanceof jsExport.BaseAudioContext)) {
50
+ throw new TypeError(`Failed to construct 'ChannelSplitterNode': argument 1 is not of type BaseAudioContext`);
51
+ }
40
52
 
41
- }
53
+ // parsed version of the option to be passed to NAPI
54
+ const parsedOptions = {};
42
55
 
43
- // getters
56
+ if (options && typeof options !== 'object') {
57
+ throw new TypeError('Failed to construct \'ChannelSplitterNode\': argument 2 is not of type \'ChannelSplitterOptions\'');
58
+ }
44
59
 
45
- // setters
60
+ if (options && options.numberOfOutputs !== undefined) {
61
+ parsedOptions.numberOfOutputs = conversions['unsigned long'](options.numberOfOutputs, {
62
+ enforceRange: true,
63
+ context: `Failed to construct 'ChannelSplitterNode': Failed to read the 'numberOfOutputs' property from ChannelSplitterOptions: The provided value (${options.numberOfOutputs}})`,
64
+ });
65
+ } else {
66
+ parsedOptions.numberOfOutputs = 6;
67
+ }
68
+
69
+ if (options && options.channelCount !== undefined) {
70
+ parsedOptions.channelCount = conversions['unsigned long'](options.channelCount, {
71
+ enforceRange: true,
72
+ context: `Failed to construct 'ChannelSplitterNode': Failed to read the 'channelCount' property from ChannelSplitterOptions: The provided value '${options.channelCount}'`,
73
+ });
74
+ }
75
+
76
+ if (options && options.channelCountMode !== undefined) {
77
+ parsedOptions.channelCountMode = conversions['DOMString'](options.channelCountMode, {
78
+ context: `Failed to construct 'ChannelSplitterNode': Failed to read the 'channelCount' property from ChannelSplitterOptions: The provided value '${options.channelCountMode}'`,
79
+ });
80
+ }
81
+
82
+ if (options && options.channelInterpretation !== undefined) {
83
+ parsedOptions.channelInterpretation = conversions['DOMString'](options.channelInterpretation, {
84
+ context: `Failed to construct 'ChannelSplitterNode': Failed to read the 'channelInterpretation' property from ChannelSplitterOptions: The provided value '${options.channelInterpretation}'`,
85
+ });
86
+ }
87
+
88
+ let napiObj;
89
+
90
+ try {
91
+ napiObj = new nativeBinding.ChannelSplitterNode(context[kNapiObj], parsedOptions);
92
+ } catch (err) {
93
+ throwSanitizedError(err);
94
+ }
95
+
96
+ super(context, {
97
+ [kNapiObj]: napiObj,
98
+ });
99
+
100
+ }
46
101
 
47
- // methods
48
-
49
102
  }
50
103
 
51
- return ChannelSplitterNode;
52
- };
104
+ Object.defineProperties(ChannelSplitterNode, {
105
+ length: {
106
+ __proto__: null,
107
+ writable: false,
108
+ enumerable: false,
109
+ configurable: true,
110
+ value: 1,
111
+ },
112
+ });
53
113
 
114
+ Object.defineProperties(ChannelSplitterNode.prototype, {
115
+ [Symbol.toStringTag]: {
116
+ __proto__: null,
117
+ writable: false,
118
+ enumerable: false,
119
+ configurable: true,
120
+ value: 'ChannelSplitterNode',
121
+ },
54
122
 
55
-
123
+ });
124
+
125
+ return ChannelSplitterNode;
126
+ };
@@ -17,44 +17,104 @@
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');
26
- const AudioScheduledSourceNodeMixin = require('./AudioScheduledSourceNode.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
+ /* eslint-enable no-unused-vars */
27
37
 
28
- module.exports = (NativeConstantSourceNode) => {
29
-
30
- const EventTarget = EventTargetMixin(NativeConstantSourceNode, ['ended']);
31
- const AudioNode = AudioNodeMixin(EventTarget);
32
- const AudioScheduledSourceNode = AudioScheduledSourceNodeMixin(AudioNode);
38
+ const AudioScheduledSourceNode = require('./AudioScheduledSourceNode.js');
33
39
 
40
+ module.exports = (jsExport, nativeBinding) => {
34
41
  class ConstantSourceNode extends AudioScheduledSourceNode {
42
+
43
+ #offset = null;
44
+
35
45
  constructor(context, options) {
36
- if (options !== undefined && typeof options !== 'object') {
37
- throw new TypeError("Failed to construct 'ConstantSourceNode': argument 2 is not of type 'ConstantSourceOptions'")
46
+
47
+ if (arguments.length < 1) {
48
+ throw new TypeError(`Failed to construct 'ConstantSourceNode': 1 argument required, but only ${arguments.length} present`);
49
+ }
50
+
51
+ if (!(context instanceof jsExport.BaseAudioContext)) {
52
+ throw new TypeError(`Failed to construct 'ConstantSourceNode': argument 1 is not of type BaseAudioContext`);
53
+ }
54
+
55
+ // parsed version of the option to be passed to NAPI
56
+ const parsedOptions = {};
57
+
58
+ if (options && typeof options !== 'object') {
59
+ throw new TypeError('Failed to construct \'ConstantSourceNode\': argument 2 is not of type \'ConstantSourceOptions\'');
60
+ }
61
+
62
+ if (options && options.offset !== undefined) {
63
+ parsedOptions.offset = conversions['float'](options.offset, {
64
+ context: `Failed to construct 'ConstantSourceNode': Failed to read the 'offset' property from ConstantSourceOptions: The provided value (${options.offset}})`,
65
+ });
66
+ } else {
67
+ parsedOptions.offset = 1;
38
68
  }
39
69
 
40
- super(context, options);
41
- // EventTargetMixin has been called so EventTargetMixin[kDispatchEvent] is
42
- // bound to this, then we can safely finalize event target initialization
43
- super.__initEventTarget__();
70
+ let napiObj;
44
71
 
45
- this.offset = new AudioParam(this.offset);
72
+ try {
73
+ napiObj = new nativeBinding.ConstantSourceNode(context[kNapiObj], parsedOptions);
74
+ } catch (err) {
75
+ throwSanitizedError(err);
76
+ }
77
+
78
+ super(context, {
79
+ [kNapiObj]: napiObj,
80
+ });
81
+
82
+ this.#offset = new jsExport.AudioParam({
83
+ [kNapiObj]: this[kNapiObj].offset,
84
+ });
46
85
  }
47
86
 
48
- // getters
87
+ get offset() {
88
+ if (!(this instanceof ConstantSourceNode)) {
89
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'ConstantSourceNode\'');
90
+ }
49
91
 
50
- // setters
92
+ return this.#offset;
93
+ }
51
94
 
52
- // methods
53
-
54
95
  }
55
96
 
56
- return ConstantSourceNode;
57
- };
97
+ Object.defineProperties(ConstantSourceNode, {
98
+ length: {
99
+ __proto__: null,
100
+ writable: false,
101
+ enumerable: false,
102
+ configurable: true,
103
+ value: 1,
104
+ },
105
+ });
106
+
107
+ Object.defineProperties(ConstantSourceNode.prototype, {
108
+ [Symbol.toStringTag]: {
109
+ __proto__: null,
110
+ writable: false,
111
+ enumerable: false,
112
+ configurable: true,
113
+ value: 'ConstantSourceNode',
114
+ },
115
+ offset: kEnumerableProperty,
58
116
 
117
+ });
59
118
 
60
-
119
+ return ConstantSourceNode;
120
+ };