mirror of
https://github.com/scratchfoundation/scratch-audio.git
synced 2024-12-22 14:02:29 -05:00
rm AudioPlayer and SoundPlayer
This commit is contained in:
parent
c12a1a4766
commit
45a7d1abef
3 changed files with 3 additions and 249 deletions
|
@ -5,7 +5,6 @@ const log = require('./log');
|
||||||
const uid = require('./uid');
|
const uid = require('./uid');
|
||||||
|
|
||||||
const ADPCMSoundDecoder = require('./ADPCMSoundDecoder');
|
const ADPCMSoundDecoder = require('./ADPCMSoundDecoder');
|
||||||
const AudioPlayer = require('./AudioPlayer');
|
|
||||||
const Loudness = require('./Loudness');
|
const Loudness = require('./Loudness');
|
||||||
const SoundPlayer = require('./GreenPlayer');
|
const SoundPlayer = require('./GreenPlayer');
|
||||||
|
|
||||||
|
@ -242,13 +241,11 @@ class AudioEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an AudioPlayer. Each sprite or clone has an AudioPlayer.
|
* Deprecated way to create an AudioPlayer
|
||||||
* It includes a reference to the AudioEngine so it can use global
|
* @todo remove this
|
||||||
* functionality such as playing notes.
|
|
||||||
* @return {AudioPlayer} new AudioPlayer instance
|
|
||||||
*/
|
*/
|
||||||
createPlayer () {
|
createPlayer () {
|
||||||
return new AudioPlayer(this);
|
log.warn('the createPlayer method is no longer available, please use createBank');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,152 +0,0 @@
|
||||||
const PanEffect = require('./effects/PanEffect');
|
|
||||||
const PitchEffect = require('./effects/PitchEffect');
|
|
||||||
const VolumeEffect = require('./effects/VolumeEffect');
|
|
||||||
|
|
||||||
const SoundPlayer = require('./GreenPlayer');
|
|
||||||
|
|
||||||
class AudioPlayer {
|
|
||||||
/**
|
|
||||||
* Each sprite or clone has an audio player
|
|
||||||
* the audio player handles sound playback, volume, and the sprite-specific audio effects:
|
|
||||||
* pitch and pan
|
|
||||||
* @param {AudioEngine} audioEngine AudioEngine for player
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
constructor (audioEngine) {
|
|
||||||
this.audioEngine = audioEngine;
|
|
||||||
|
|
||||||
this.outputNode = this.audioEngine.audioContext.createGain();
|
|
||||||
|
|
||||||
// Create the audio effects.
|
|
||||||
const volumeEffect = new VolumeEffect(this.audioEngine, this, null);
|
|
||||||
const pitchEffect = new PitchEffect(this.audioEngine, this, volumeEffect);
|
|
||||||
const panEffect = new PanEffect(this.audioEngine, this, pitchEffect);
|
|
||||||
this.effects = {
|
|
||||||
volume: volumeEffect,
|
|
||||||
pitch: pitchEffect,
|
|
||||||
pan: panEffect
|
|
||||||
};
|
|
||||||
|
|
||||||
// Chain the effects and player together with the audio engine.
|
|
||||||
// outputNode -> "pitchEffect" -> panEffect -> audioEngine.input
|
|
||||||
panEffect.connect(this.audioEngine);
|
|
||||||
pitchEffect.connect(panEffect);
|
|
||||||
volumeEffect.connect(pitchEffect);
|
|
||||||
|
|
||||||
// Reset effects to their default parameters.
|
|
||||||
this.clearEffects();
|
|
||||||
|
|
||||||
// SoundPlayers mapped by sound id.
|
|
||||||
this.soundPlayers = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get this sprite's input node, so that other objects can route sound through it.
|
|
||||||
* @return {AudioNode} the AudioNode for this sprite's input
|
|
||||||
*/
|
|
||||||
getInputNode () {
|
|
||||||
return this.outputNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all the sound players owned by this audio player.
|
|
||||||
* @return {object<string, SoundPlayer>} mapping of sound ids to sound
|
|
||||||
* players
|
|
||||||
*/
|
|
||||||
getSoundPlayers () {
|
|
||||||
return this.soundPlayers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a SoundPlayer instance to soundPlayers map.
|
|
||||||
* @param {SoundPlayer} soundPlayer - SoundPlayer instance to add
|
|
||||||
*/
|
|
||||||
addSoundPlayer (soundPlayer) {
|
|
||||||
this.soundPlayers[soundPlayer.id] = soundPlayer;
|
|
||||||
|
|
||||||
for (const effectName in this.effects) {
|
|
||||||
this.effects[effectName].update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Play a sound
|
|
||||||
* @param {string} soundId - the soundId id of a sound file
|
|
||||||
* @return {Promise} a Promise that resolves when the sound finishes playing
|
|
||||||
*/
|
|
||||||
playSound (soundId) {
|
|
||||||
// create a new soundplayer to play the sound
|
|
||||||
if (!this.soundPlayers[soundId]) {
|
|
||||||
this.addSoundPlayer(new SoundPlayer(
|
|
||||||
this.audioEngine,
|
|
||||||
{id: soundId, buffer: this.audioEngine.audioBuffers[soundId]}
|
|
||||||
));
|
|
||||||
}
|
|
||||||
const player = this.soundPlayers[soundId];
|
|
||||||
player.connect(this);
|
|
||||||
player.play();
|
|
||||||
|
|
||||||
return player.finished();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop all sounds that are playing
|
|
||||||
*/
|
|
||||||
stopAllSounds () {
|
|
||||||
// stop all active sound players
|
|
||||||
for (const soundId in this.soundPlayers) {
|
|
||||||
this.soundPlayers[soundId].stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set an audio effect to a value
|
|
||||||
* @param {string} effect - the name of the effect
|
|
||||||
* @param {number} value - the value to set the effect to
|
|
||||||
*/
|
|
||||||
setEffect (effect, value) {
|
|
||||||
if (this.effects.hasOwnProperty(effect)) {
|
|
||||||
this.effects[effect].set(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear all audio effects
|
|
||||||
*/
|
|
||||||
clearEffects () {
|
|
||||||
for (const effectName in this.effects) {
|
|
||||||
this.effects[effectName].clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the volume for sounds played by this AudioPlayer
|
|
||||||
* @param {number} value - the volume in range 0-100
|
|
||||||
*/
|
|
||||||
setVolume (value) {
|
|
||||||
this.setEffect('volume', value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connnect this player's output to another audio node
|
|
||||||
* @param {object} target - target whose node to should be connected
|
|
||||||
*/
|
|
||||||
connect (target) {
|
|
||||||
this.outputNode.disconnect();
|
|
||||||
this.outputNode.connect(target.getInputNode());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clean up and disconnect audio nodes.
|
|
||||||
*/
|
|
||||||
dispose () {
|
|
||||||
this.effects.volume.dispose();
|
|
||||||
this.effects.pitch.dispose();
|
|
||||||
this.effects.pan.dispose();
|
|
||||||
|
|
||||||
this.outputNode.disconnect();
|
|
||||||
this.outputNode = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = AudioPlayer;
|
|
|
@ -1,91 +0,0 @@
|
||||||
const log = require('./log');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A SoundPlayer stores an audio buffer, and plays it
|
|
||||||
*/
|
|
||||||
class SoundPlayer {
|
|
||||||
/**
|
|
||||||
* @param {AudioContext} audioContext - a webAudio context
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
constructor (audioContext) {
|
|
||||||
this.audioContext = audioContext;
|
|
||||||
this.outputNode = null;
|
|
||||||
this.buffer = null;
|
|
||||||
this.bufferSource = null;
|
|
||||||
this.playbackRate = 1;
|
|
||||||
this.isPlaying = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connect the SoundPlayer to an output node
|
|
||||||
* @param {GainNode} node - an output node to connect to
|
|
||||||
*/
|
|
||||||
connect (node) {
|
|
||||||
this.outputNode = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set an audio buffer
|
|
||||||
* @param {AudioBuffer} buffer - Buffer to set
|
|
||||||
*/
|
|
||||||
setBuffer (buffer) {
|
|
||||||
this.buffer = buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the playback rate for the sound
|
|
||||||
* @param {number} playbackRate - a ratio where 1 is normal playback, 0.5 is half speed, 2 is double speed, etc.
|
|
||||||
*/
|
|
||||||
setPlaybackRate (playbackRate) {
|
|
||||||
this.playbackRate = playbackRate;
|
|
||||||
if (this.bufferSource && this.bufferSource.playbackRate) {
|
|
||||||
this.bufferSource.playbackRate.value = this.playbackRate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop the sound
|
|
||||||
*/
|
|
||||||
stop () {
|
|
||||||
if (this.bufferSource && this.isPlaying) {
|
|
||||||
this.bufferSource.stop();
|
|
||||||
}
|
|
||||||
this.isPlaying = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start playing the sound
|
|
||||||
* The web audio framework requires a new audio buffer source node for each playback
|
|
||||||
*/
|
|
||||||
start () {
|
|
||||||
if (!this.buffer) {
|
|
||||||
log.warn('tried to play a sound that was not loaded yet');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.bufferSource = this.audioContext.createBufferSource();
|
|
||||||
this.bufferSource.buffer = this.buffer;
|
|
||||||
this.bufferSource.playbackRate.value = this.playbackRate;
|
|
||||||
this.bufferSource.connect(this.outputNode);
|
|
||||||
this.bufferSource.start();
|
|
||||||
|
|
||||||
this.isPlaying = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The sound has finished playing. This is called at the correct time even if the playback rate
|
|
||||||
* has been changed
|
|
||||||
* @return {Promise} a Promise that resolves when the sound finishes playing
|
|
||||||
*/
|
|
||||||
finished () {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
this.bufferSource.onended = () => {
|
|
||||||
this.isPlaying = false;
|
|
||||||
resolve();
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = SoundPlayer;
|
|
Loading…
Reference in a new issue