From c087cf326a7866d89d42486a9b23a609c4292d69 Mon Sep 17 00:00:00 2001 From: Corey Frang Date: Fri, 15 Jun 2018 12:22:49 -0400 Subject: [PATCH] soundbank tests --- src/blocks/scratch3_sound.js | 47 +++++++++++++++------------------- src/sprites/rendered-target.js | 40 ++++++++++++++++------------- src/sprites/sprite.js | 14 +++++++++- test/unit/blocks_sounds.js | 8 +++--- 4 files changed, 60 insertions(+), 49 deletions(-) diff --git a/src/blocks/scratch3_sound.js b/src/blocks/scratch3_sound.js index a599b314c..16b041bf8 100644 --- a/src/blocks/scratch3_sound.js +++ b/src/blocks/scratch3_sound.js @@ -88,6 +88,7 @@ class Scratch3SoundBlocks { if (!soundState) { soundState = Clone.simple(Scratch3SoundBlocks.DEFAULT_SOUND_STATE); target.setCustomState(Scratch3SoundBlocks.STATE_KEY, soundState); + target.soundEffects = soundState.effects; } return soundState; } @@ -139,20 +140,19 @@ class Scratch3SoundBlocks { } playSound (args, util) { - const index = this._getSoundIndex(args.SOUND_MENU, util); - if (index >= 0) { - const soundId = util.target.sprite.sounds[index].soundId; - if (util.target.audioPlayer === null) return; - util.target.audioPlayer.playSound(soundId); - } + // Don't return the promise, it's the only difference for AndWait + this.playSoundAndWait(args, util); } playSoundAndWait (args, util) { const index = this._getSoundIndex(args.SOUND_MENU, util); if (index >= 0) { - const soundId = util.target.sprite.sounds[index].soundId; - if (util.target.audioPlayer === null) return; - return util.target.audioPlayer.playSound(soundId); + const {target} = util; + const {sprite} = target; + const {soundId} = sprite.sounds[index]; + if (sprite.soundBank) { + return sprite.soundBank.playSound(target, soundId); + } } } @@ -199,8 +199,9 @@ class Scratch3SoundBlocks { } _stopAllSoundsForTarget (target) { - if (target.audioPlayer === null) return; - target.audioPlayer.stopAllSounds(); + if (target.sprite.soundBank) { + target.sprite.soundBank.stopAllSounds(target); + } } setEffect (args, util) { @@ -224,23 +225,19 @@ class Scratch3SoundBlocks { soundState.effects[effect] = value; } - const effectRange = Scratch3SoundBlocks.EFFECT_RANGE[effect]; - soundState.effects[effect] = MathUtil.clamp(soundState.effects[effect], effectRange.min, effectRange.max); - - if (util.target.audioPlayer === null) return; - util.target.audioPlayer.setEffect(effect, soundState.effects[effect]); + const {min, max} = Scratch3SoundBlocks.EFFECT_RANGE[effect]; + soundState.effects[effect] = MathUtil.clamp(soundState.effects[effect], min, max); + this._syncEffectsForTarget(util.target); // Yield until the next tick. return Promise.resolve(); } _syncEffectsForTarget (target) { - if (!target || !target.audioPlayer) return; - const soundState = this._getSoundState(target); - for (const effect in soundState.effects) { - if (!soundState.effects.hasOwnProperty(effect)) continue; - target.audioPlayer.setEffect(effect, soundState.effects[effect]); - } + if (!target || !target.sprite.soundBank) return; + target.soundEffects = this._getSoundState(target).effects; + + target.sprite.soundBank.setEffects(target); } clearEffects (args, util) { @@ -253,8 +250,7 @@ class Scratch3SoundBlocks { if (!soundState.effects.hasOwnProperty(effect)) continue; soundState.effects[effect] = 0; } - if (target.audioPlayer === null) return; - target.audioPlayer.clearEffects(); + this._syncEffectsForTarget(target); } _clearEffectsForAllTargets () { @@ -278,8 +274,7 @@ class Scratch3SoundBlocks { _updateVolume (volume, util) { volume = MathUtil.clamp(volume, 0, 100); util.target.volume = volume; - if (util.target.audioPlayer === null) return; - util.target.audioPlayer.setVolume(util.target.volume); + this._syncEffectsForTarget(util.target); // Yield until the next tick. return Promise.resolve(); diff --git a/src/sprites/rendered-target.js b/src/sprites/rendered-target.js index aac0b059a..293666acf 100644 --- a/src/sprites/rendered-target.js +++ b/src/sprites/rendered-target.js @@ -170,21 +170,30 @@ class RenderedTarget extends Target { } } + get audioPlayer () { + /* eslint-disable no-console */ + console.warn('get audioPlayer deprecated, please update to use .sprite.soundBank methods'); + console.warn(new Error('stack for debug').stack); + /* eslint-enable no-console */ + const bank = this.sprite.soundBank; + const audioPlayerProxy = { + playSound: soundId => bank.play(this, soundId) + }; + + Object.defineProperty(this, 'audioPlayer', { + configurable: false, + enumerable: true, + writable: false, + value: audioPlayerProxy + }); + + return audioPlayerProxy; + } + /** * Initialize the audio player for this sprite or clone. */ initAudio () { - this.audioPlayer = null; - if (this.runtime && this.runtime.audioEngine) { - this.audioPlayer = this.runtime.audioEngine.createPlayer(); - // If this is a clone, it gets a reference to its parent's activeSoundPlayers object. - if (!this.isOriginal) { - const parent = this.sprite.clones[0]; - if (parent && parent.audioPlayer) { - this.audioPlayer.activeSoundPlayers = parent.audioPlayer.activeSoundPlayers; - } - } - } } /** @@ -1034,9 +1043,8 @@ class RenderedTarget extends Target { */ onStopAll () { this.clearEffects(); - if (this.audioPlayer) { - this.audioPlayer.stopAllSounds(); - this.audioPlayer.clearEffects(); + if (this.sprite.soundBank) { + this.sprite.soundBank.stopAllSounds(this); } } @@ -1132,10 +1140,6 @@ class RenderedTarget extends Target { this.runtime.requestRedraw(); } } - if (this.audioPlayer) { - this.audioPlayer.stopAllSounds(); - this.audioPlayer.dispose(); - } } } diff --git a/src/sprites/sprite.js b/src/sprites/sprite.js index de735ecc3..c7c35c9e0 100644 --- a/src/sprites/sprite.js +++ b/src/sprites/sprite.js @@ -8,7 +8,8 @@ const StageLayering = require('../engine/stage-layering'); class Sprite { /** * Sprite to be used on the Scratch stage. - * All clones of a sprite have shared blocks, shared costumes, shared variables. + * All clones of a sprite have shared blocks, shared costumes, shared variables, + * shared sounds, etc. * @param {?Blocks} blocks Shared blocks object for all clones of sprite. * @param {Runtime} runtime Reference to the runtime. * @constructor @@ -47,6 +48,11 @@ class Sprite { * @type {Array.} */ this.clones = []; + + this.soundBank = null; + if (this.runtime && this.runtime.audioEngine) { + this.soundBank = this.runtime.audioEngine.createBank(); + } } /** @@ -155,6 +161,12 @@ class Sprite { return Promise.all(assetPromises).then(() => newSprite); } + + dispose () { + if (this.soundBank) { + this.soundBank.dispose(); + } + } } module.exports = Sprite; diff --git a/test/unit/blocks_sounds.js b/test/unit/blocks_sounds.js index 9a44e7f9f..53acc8aff 100644 --- a/test/unit/blocks_sounds.js +++ b/test/unit/blocks_sounds.js @@ -11,10 +11,10 @@ const util = { {name: 'second name', soundId: 'second soundId'}, {name: 'third name', soundId: 'third soundId'}, {name: '6', soundId: 'fourth soundId'} - ] - }, - audioPlayer: { - playSound: soundId => (playedSound = soundId) + ], + soundBank: { + playSound: (target, soundId) => (playedSound = soundId) + } } } };