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
@@ -17,56 +17,198 @@
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
+ const {
37
+ bridgeEventTarget,
38
+ } = require('./lib/events.js');
39
+ /* eslint-enable no-unused-vars */
27
40
 
28
- module.exports = (NativeOscillatorNode) => {
29
-
30
- const EventTarget = EventTargetMixin(NativeOscillatorNode, ['ended']);
31
- const AudioNode = AudioNodeMixin(EventTarget);
32
- const AudioScheduledSourceNode = AudioScheduledSourceNodeMixin(AudioNode);
41
+ const AudioScheduledSourceNode = require('./AudioScheduledSourceNode.js');
33
42
 
43
+ module.exports = (jsExport, nativeBinding) => {
34
44
  class OscillatorNode extends AudioScheduledSourceNode {
45
+
46
+ #frequency = null;
47
+ #detune = null;
48
+
35
49
  constructor(context, options) {
36
- if (options !== undefined && typeof options !== 'object') {
37
- throw new TypeError("Failed to construct 'OscillatorNode': argument 2 is not of type 'OscillatorOptions'")
50
+
51
+ if (arguments.length < 1) {
52
+ throw new TypeError(`Failed to construct 'OscillatorNode': 1 argument required, but only ${arguments.length} present`);
53
+ }
54
+
55
+ if (!(context instanceof jsExport.BaseAudioContext)) {
56
+ throw new TypeError(`Failed to construct 'OscillatorNode': argument 1 is not of type BaseAudioContext`);
57
+ }
58
+
59
+ // parsed version of the option to be passed to NAPI
60
+ const parsedOptions = {};
61
+
62
+ if (options && typeof options !== 'object') {
63
+ throw new TypeError('Failed to construct \'OscillatorNode\': argument 2 is not of type \'OscillatorOptions\'');
64
+ }
65
+
66
+ if (options && options.type !== undefined) {
67
+ if (!['sine', 'square', 'sawtooth', 'triangle', 'custom'].includes(options.type)) {
68
+ throw new TypeError(`Failed to construct 'OscillatorNode': Failed to read the 'type' property from OscillatorOptions: The provided value '${options.type}' is not a valid enum value of type OscillatorType`);
69
+ }
70
+
71
+ parsedOptions.type = conversions['DOMString'](options.type, {
72
+ context: `Failed to construct 'OscillatorNode': Failed to read the 'type' property from OscillatorOptions: The provided value '${options.type}'`,
73
+ });
74
+ } else {
75
+ parsedOptions.type = 'sine';
76
+ }
77
+
78
+ if (options && options.frequency !== undefined) {
79
+ parsedOptions.frequency = conversions['float'](options.frequency, {
80
+ context: `Failed to construct 'OscillatorNode': Failed to read the 'frequency' property from OscillatorOptions: The provided value (${options.frequency}})`,
81
+ });
82
+ } else {
83
+ parsedOptions.frequency = 440;
84
+ }
85
+
86
+ if (options && options.detune !== undefined) {
87
+ parsedOptions.detune = conversions['float'](options.detune, {
88
+ context: `Failed to construct 'OscillatorNode': Failed to read the 'detune' property from OscillatorOptions: The provided value (${options.detune}})`,
89
+ });
90
+ } else {
91
+ parsedOptions.detune = 0;
38
92
  }
39
93
 
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__();
94
+ if (options && options.periodicWave !== undefined) {
95
+ if (!(options.periodicWave instanceof jsExport.PeriodicWave)) {
96
+ throw new TypeError(`Failed to construct 'OscillatorNode': Failed to read the 'periodicWave' property from OscillatorOptions: The provided value '${options.periodicWave}' is not an instance of PeriodicWave`);
97
+ }
44
98
 
45
- this.frequency = new AudioParam(this.frequency);
46
- this.detune = new AudioParam(this.detune);
99
+ parsedOptions.periodicWave = options.periodicWave[kNapiObj];
100
+ } else {
101
+ parsedOptions.periodicWave = null;
102
+ }
103
+
104
+ if (parsedOptions.type === 'custom' && parsedOptions.periodicWave === null) {
105
+ throw new DOMException('Failed to construct \'OscillatorNode\': A PeriodicWave must be specified if the type is set to \'custom\'', 'InvalidStateError');
106
+ }
107
+
108
+ if (parsedOptions.periodicWave !== null) {
109
+ parsedOptions.type = 'custom';
110
+ }
111
+
112
+ if (options && options.channelCount !== undefined) {
113
+ parsedOptions.channelCount = conversions['unsigned long'](options.channelCount, {
114
+ enforceRange: true,
115
+ context: `Failed to construct 'OscillatorNode': Failed to read the 'channelCount' property from OscillatorOptions: 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 'OscillatorNode': Failed to read the 'channelCount' property from OscillatorOptions: The provided value '${options.channelCountMode}'`,
122
+ });
123
+ }
124
+
125
+ if (options && options.channelInterpretation !== undefined) {
126
+ parsedOptions.channelInterpretation = conversions['DOMString'](options.channelInterpretation, {
127
+ context: `Failed to construct 'OscillatorNode': Failed to read the 'channelInterpretation' property from OscillatorOptions: The provided value '${options.channelInterpretation}'`,
128
+ });
129
+ }
130
+
131
+ let napiObj;
132
+
133
+ try {
134
+ napiObj = new nativeBinding.OscillatorNode(context[kNapiObj], parsedOptions);
135
+ } catch (err) {
136
+ throwSanitizedError(err);
137
+ }
138
+
139
+ super(context, {
140
+ [kNapiObj]: napiObj,
141
+ });
142
+
143
+ // Bridge Rust native event to Node EventTarget
144
+ bridgeEventTarget(this);
145
+
146
+ this.#frequency = new jsExport.AudioParam({
147
+ [kNapiObj]: this[kNapiObj].frequency,
148
+ });
149
+ this.#detune = new jsExport.AudioParam({
150
+ [kNapiObj]: this[kNapiObj].detune,
151
+ });
47
152
  }
48
153
 
49
- // getters
154
+ get frequency() {
155
+ if (!(this instanceof OscillatorNode)) {
156
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'OscillatorNode\'');
157
+ }
50
158
 
51
- get type() {
52
- return super.type;
159
+ return this.#frequency;
53
160
  }
54
161
 
55
- // setters
162
+ get detune() {
163
+ if (!(this instanceof OscillatorNode)) {
164
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'OscillatorNode\'');
165
+ }
166
+
167
+ return this.#detune;
168
+ }
169
+
170
+ get type() {
171
+ if (!(this instanceof OscillatorNode)) {
172
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'OscillatorNode\'');
173
+ }
174
+
175
+ return this[kNapiObj].type;
176
+ }
56
177
 
57
178
  set type(value) {
179
+ if (!(this instanceof OscillatorNode)) {
180
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'OscillatorNode\'');
181
+ }
182
+
183
+ if (!['sine', 'square', 'sawtooth', 'triangle', 'custom'].includes(value)) {
184
+ console.warn(`Failed to set the 'type' property on 'OscillatorNode': Value '${value}' is not a valid 'OscillatorType' enum value`);
185
+ return;
186
+ }
187
+
58
188
  try {
59
- super.type = value;
189
+ this[kNapiObj].type = value;
60
190
  } catch (err) {
61
191
  throwSanitizedError(err);
62
192
  }
63
193
  }
64
194
 
65
- // methods
66
-
67
- setPeriodicWave(...args) {
195
+ setPeriodicWave(periodicWave) {
196
+ if (!(this instanceof OscillatorNode)) {
197
+ throw new TypeError('Invalid Invocation: Value of \'this\' must be of type \'OscillatorNode\'');
198
+ }
199
+
200
+ if (arguments.length < 1) {
201
+ throw new TypeError(`Failed to execute 'setPeriodicWave' on 'OscillatorNode': 1 argument required, but only ${arguments.length} present`);
202
+ }
203
+
204
+ if (!(periodicWave instanceof jsExport.PeriodicWave)) {
205
+ throw new TypeError(`Failed to execute 'setPeriodicWave' on 'OscillatorNode': Parameter 1 is not of type 'PeriodicWave'`);
206
+ }
207
+
208
+ periodicWave = periodicWave[kNapiObj];
209
+
68
210
  try {
69
- return super.setPeriodicWave(...args);
211
+ return this[kNapiObj].setPeriodicWave(periodicWave);
70
212
  } catch (err) {
71
213
  throwSanitizedError(err);
72
214
  }
@@ -74,8 +216,29 @@ module.exports = (NativeOscillatorNode) => {
74
216
 
75
217
  }
76
218
 
77
- return OscillatorNode;
78
- };
219
+ Object.defineProperties(OscillatorNode, {
220
+ length: {
221
+ __proto__: null,
222
+ writable: false,
223
+ enumerable: false,
224
+ configurable: true,
225
+ value: 1,
226
+ },
227
+ });
79
228
 
229
+ Object.defineProperties(OscillatorNode.prototype, {
230
+ [Symbol.toStringTag]: {
231
+ __proto__: null,
232
+ writable: false,
233
+ enumerable: false,
234
+ configurable: true,
235
+ value: 'OscillatorNode',
236
+ },
237
+ frequency: kEnumerableProperty,
238
+ detune: kEnumerableProperty,
239
+ type: kEnumerableProperty,
240
+ setPeriodicWave: kEnumerableProperty,
241
+ });
80
242
 
81
-
243
+ return OscillatorNode;
244
+ };