1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-05 12:10:55 +00:00

[Web] Fix Webkit leak caused by the position reporting audio worklets

Co-authored-by: PizzaLovers007 <trex@parkvue.com>
This commit is contained in:
Adam Scott
2025-06-24 14:34:34 -04:00
parent 88b9932ce1
commit b58c6c829b
2 changed files with 20 additions and 21 deletions

View File

@@ -28,40 +28,31 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/ /**************************************************************************/
const POST_THRESHOLD_S = 0.1;
class GodotPositionReportingProcessor extends AudioWorkletProcessor { class GodotPositionReportingProcessor extends AudioWorkletProcessor {
constructor(...args) { constructor(...args) {
super(...args); super(...args);
this.lastPostTime = currentTime;
this.position = 0; this.position = 0;
this.ended = false;
this.port.onmessage = (event) => { this.port.onmessage = (event) => {
if (event?.data?.type === 'ended') { switch (event?.data?.type) {
this.ended = true; case 'reset':
this.position = 0;
break;
default:
// Do nothing.
} }
}; };
} }
process(inputs, _outputs, _parameters) { process(inputs, _outputs, _parameters) {
if (this.ended) {
return false;
}
if (inputs.length > 0) { if (inputs.length > 0) {
const input = inputs[0]; const input = inputs[0];
if (input.length > 0) { if (input.length > 0) {
this.position += input[0].length; this.position += input[0].length;
this.port.postMessage({ type: 'position', data: this.position });
} }
} }
// Posting messages is expensive. Let's limit the number of posts.
if (currentTime - this.lastPostTime > POST_THRESHOLD_S) {
this.lastPostTime = currentTime;
this.port.postMessage({ type: 'position', data: this.position });
}
return true; return true;
} }
} }

View File

@@ -635,10 +635,14 @@ class SampleNode {
if (this._positionWorklet != null) { if (this._positionWorklet != null) {
return this._positionWorklet; return this._positionWorklet;
} }
this._positionWorklet = new AudioWorkletNode( if (GodotAudio.audioPositionWorkletNodes.length > 0) {
GodotAudio.ctx, this._positionWorklet = GodotAudio.audioPositionWorkletNodes.pop();
'godot-position-reporting-processor' } else {
); this._positionWorklet = new AudioWorkletNode(
GodotAudio.ctx,
'godot-position-reporting-processor'
);
}
this._positionWorklet.port.onmessage = (event) => { this._positionWorklet.port.onmessage = (event) => {
switch (event.data['type']) { switch (event.data['type']) {
case 'position': case 'position':
@@ -648,6 +652,7 @@ class SampleNode {
// Do nothing. // Do nothing.
} }
}; };
this._positionWorklet.port.postMessage('reset');
return this._positionWorklet; return this._positionWorklet;
} }
@@ -678,7 +683,7 @@ class SampleNode {
if (this._positionWorklet) { if (this._positionWorklet) {
this._positionWorklet.disconnect(); this._positionWorklet.disconnect();
this._positionWorklet.port.onmessage = null; this._positionWorklet.port.onmessage = null;
this._positionWorklet.port.postMessage({ type: 'ended' }); GodotAudio.audioPositionWorkletNodes.push(this._positionWorklet);
this._positionWorklet = null; this._positionWorklet = null;
} }
@@ -1198,6 +1203,8 @@ const _GodotAudio = {
/** @type {Promise} */ /** @type {Promise} */
audioPositionWorkletPromise: null, audioPositionWorkletPromise: null,
/** @type {Array<AudioWorkletNode>} */
audioPositionWorkletNodes: null,
/** /**
* Converts linear volume to Db. * Converts linear volume to Db.
@@ -1224,6 +1231,7 @@ const _GodotAudio = {
GodotAudio.sampleNodes = new Map(); GodotAudio.sampleNodes = new Map();
GodotAudio.buses = []; GodotAudio.buses = [];
GodotAudio.busSolo = null; GodotAudio.busSolo = null;
GodotAudio.audioPositionWorkletNodes = [];
const opts = {}; const opts = {};
// If mix_rate is 0, let the browser choose. // If mix_rate is 0, let the browser choose.