|
@@ -460,7 +460,11 @@ class SampleNode {
|
|
|
const sampleNodeBus = this.getSampleNodeBus(bus);
|
|
|
sampleNodeBus.setVolume(options.volume);
|
|
|
|
|
|
- this.connectPositionWorklet(options.start);
|
|
|
+ this.connectPositionWorklet(options.start).catch((err) => {
|
|
|
+ const newErr = new Error('Failed to create PositionWorklet.');
|
|
|
+ newErr.cause = err;
|
|
|
+ GodotRuntime.error(newErr);
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -612,44 +616,34 @@ class SampleNode {
|
|
|
* Sets up and connects the source to the GodotPositionReportingProcessor
|
|
|
* If the worklet module is not loaded in, it will be added
|
|
|
*/
|
|
|
- connectPositionWorklet(start) {
|
|
|
- try {
|
|
|
- this._positionWorklet = this.createPositionWorklet();
|
|
|
- this._source.connect(this._positionWorklet);
|
|
|
- if (start) {
|
|
|
- this.start();
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- if (error?.name !== 'InvalidStateError') {
|
|
|
- throw error;
|
|
|
- }
|
|
|
- const path = GodotConfig.locate_file('godot.audio.position.worklet.js');
|
|
|
- GodotAudio.ctx.audioWorklet
|
|
|
- .addModule(path)
|
|
|
- .then(() => {
|
|
|
- if (!this.isCanceled) {
|
|
|
- this._positionWorklet = this.createPositionWorklet();
|
|
|
- this._source.connect(this._positionWorklet);
|
|
|
- if (start) {
|
|
|
- this.start();
|
|
|
- }
|
|
|
- }
|
|
|
- }).catch((addModuleError) => {
|
|
|
- GodotRuntime.error('Failed to create PositionWorklet.', addModuleError);
|
|
|
- });
|
|
|
+ async connectPositionWorklet(start) {
|
|
|
+ await GodotAudio.audioPositionWorkletPromise;
|
|
|
+ if (this.isCanceled) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.getPositionWorklet();
|
|
|
+ this._source.connect(this._positionWorklet);
|
|
|
+ if (start) {
|
|
|
+ this.start();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Creates the AudioWorkletProcessor used to track playback position.
|
|
|
- * @returns {AudioWorkletNode}
|
|
|
+ * Get a AudioWorkletProcessor from the pool, or create one if no processor is available.
|
|
|
*/
|
|
|
- createPositionWorklet() {
|
|
|
- const worklet = new AudioWorkletNode(
|
|
|
- GodotAudio.ctx,
|
|
|
- 'godot-position-reporting-processor'
|
|
|
- );
|
|
|
- worklet.port.onmessage = (event) => {
|
|
|
+ getPositionWorklet() {
|
|
|
+ if (this._positionWorklet != null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (GodotAudio.audioPositionWorkletPool.length == 0) {
|
|
|
+ this._positionWorklet = new AudioWorkletNode(
|
|
|
+ GodotAudio.ctx,
|
|
|
+ 'godot-position-reporting-processor'
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ this._positionWorklet = GodotAudio.audioPositionWorkletPool.pop();
|
|
|
+ }
|
|
|
+ this._positionWorklet.port.onmessage = (event) => {
|
|
|
switch (event.data['type']) {
|
|
|
case 'position':
|
|
|
this._playbackPosition = (parseInt(event.data.data, 10) / this.getSample().sampleRate) + this.offset;
|
|
@@ -658,7 +652,6 @@ class SampleNode {
|
|
|
// Do nothing.
|
|
|
}
|
|
|
};
|
|
|
- return worklet;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -688,6 +681,8 @@ class SampleNode {
|
|
|
if (this._positionWorklet) {
|
|
|
this._positionWorklet.disconnect();
|
|
|
this._positionWorklet.port.onmessage = null;
|
|
|
+ this._positionWorklet.port.postMessage({ type: 'clear' });
|
|
|
+ GodotAudio.audioPositionWorkletPool.push(this._positionWorklet);
|
|
|
this._positionWorklet = null;
|
|
|
}
|
|
|
|
|
@@ -731,7 +726,10 @@ class SampleNode {
|
|
|
const pauseTime = this.isPaused
|
|
|
? this.pauseTime
|
|
|
: 0;
|
|
|
- this.connectPositionWorklet();
|
|
|
+ if (this._positionWorklet != null) {
|
|
|
+ this._positionWorklet.port.postMessage({ type: 'clear' });
|
|
|
+ this._source.connect(this._positionWorklet);
|
|
|
+ }
|
|
|
this._source.start(this.startTime, this.offset + pauseTime);
|
|
|
this.isStarted = true;
|
|
|
}
|
|
@@ -1199,6 +1197,10 @@ const _GodotAudio = {
|
|
|
driver: null,
|
|
|
interval: 0,
|
|
|
|
|
|
+ /** @type {Promise} */
|
|
|
+ audioPositionWorkletPromise: null,
|
|
|
+ audioPositionWorkletPool: [],
|
|
|
+
|
|
|
/**
|
|
|
* Converts linear volume to Db.
|
|
|
* @param {number} linear Linear value to convert.
|
|
@@ -1265,6 +1267,10 @@ const _GodotAudio = {
|
|
|
onlatencyupdate(computed_latency);
|
|
|
}, 1000);
|
|
|
GodotOS.atexit(GodotAudio.close_async);
|
|
|
+
|
|
|
+ const path = GodotConfig.locate_file('godot.audio.position.worklet.js');
|
|
|
+ GodotAudio.audioPositionWorkletPromise = ctx.audioWorklet.addModule(path);
|
|
|
+
|
|
|
return ctx.destination.channelCount;
|
|
|
},
|
|
|
|