diff --git a/src/extensions/scratch3_music/index.js b/src/extensions/scratch3_music/index.js index 6202b2ce..6d391bb9 100644 --- a/src/extensions/scratch3_music/index.js +++ b/src/extensions/scratch3_music/index.js @@ -60,6 +60,15 @@ class Scratch3MusicBlocks { */ this._instrumentBufferArrays = []; + /** + * An array of audio bufferSourceNodes. Each time you play an instrument or drum sound, + * a bufferSourceNode is created. We keep references to them to make sure their onended + * events can fire. + * @type {Array} + * @private + */ + this._bufferSources = []; + this._loadAllSounds(); } @@ -555,9 +564,14 @@ class Scratch3MusicBlocks { bufferSource.buffer = this._drumBuffers[drumNum]; bufferSource.connect(outputNode); bufferSource.start(); + + const bufferSourceIndex = this._bufferSources.length; + this._bufferSources.push(bufferSource); + this._concurrencyCounter++; bufferSource.onended = () => { this._concurrencyCounter--; + delete this._bufferSources[bufferSourceIndex]; }; } @@ -638,6 +652,10 @@ class Scratch3MusicBlocks { // Create the audio buffer to play the note, and set its pitch const context = util.runtime.audioEngine.audioContext; const bufferSource = context.createBufferSource(); + + const bufferSourceIndex = this._bufferSources.length; + this._bufferSources.push(bufferSource); + bufferSource.buffer = this._instrumentBufferArrays[inst][sampleIndex]; const sampleNote = sampleArray[sampleIndex]; bufferSource.playbackRate.value = this._ratioForPitchInterval(note - sampleNote); @@ -667,6 +685,7 @@ class Scratch3MusicBlocks { this._concurrencyCounter++; bufferSource.onended = () => { this._concurrencyCounter--; + delete this._bufferSources[bufferSourceIndex]; }; }