From 6ebf50607017b5eace7100b406cc21aac8658530 Mon Sep 17 00:00:00 2001 From: Tijmen Zwaan Date: Tue, 4 Aug 2026 23:14:28 +0200 Subject: [PATCH] Fix node pool reusing incompatible audio nodes when audiocontext changes --- packages/superdough/audioContext.mjs | 8 ++++++-- packages/superdough/nodePools.mjs | 13 +++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/superdough/audioContext.mjs b/packages/superdough/audioContext.mjs index 94ec32d15..1c708e814 100644 --- a/packages/superdough/audioContext.mjs +++ b/packages/superdough/audioContext.mjs @@ -7,14 +7,18 @@ Copyright (C) 2025 Strudel contributors - see . */ +import { clearNodePool } from './nodePools.mjs'; + let audioContext; export const setDefaultAudioContext = () => { - audioContext = new AudioContext(); - return audioContext; + return setAudioContext(new AudioContext()); }; export const setAudioContext = (context) => { + // Existing nodes in the node pool contain references to the previous AudioContext, + // so all the nodes in the pool must be cleared when we set a new AudioContext. + clearNodePool(); audioContext = context; return audioContext; }; diff --git a/packages/superdough/nodePools.mjs b/packages/superdough/nodePools.mjs index 90b4c0ae7..66319e8c6 100644 --- a/packages/superdough/nodePools.mjs +++ b/packages/superdough/nodePools.mjs @@ -5,11 +5,24 @@ Copyright (C) 2025 Strudel contributors - see . */ +import { releaseAudioNode } from './helpers.mjs'; + const nodePools = new Map(); const POOL_KEY = Symbol('nodePoolKey'); export const isPoolable = (node) => !!node[POOL_KEY]; +export const clearNodePool = () => { + for (const pool of nodePools) { + for (const node of pool) { + if (node instanceof AudioNode) { + releaseAudioNode(node); + } + } + } + nodePools.clear(); +}; + const getNodeTime = (node) => { return node.context?.currentTime ?? 0; };