mirror of
https://github.com/scratchfoundation/scratch-audio.git
synced 2024-12-22 05:53:43 -05:00
Use uid instead of md5 for keying audio buffer cache
This commit is contained in:
parent
6863ad25a2
commit
0555407406
2 changed files with 48 additions and 18 deletions
37
src/index.js
37
src/index.js
|
@ -1,7 +1,8 @@
|
|||
const log = require('./log');
|
||||
|
||||
const AudioContext = require('audio-context');
|
||||
|
||||
const log = require('./log');
|
||||
const uid = require('./uid');
|
||||
|
||||
const PitchEffect = require('./effects/PitchEffect');
|
||||
const PanEffect = require('./effects/PanEffect');
|
||||
|
||||
|
@ -39,35 +40,35 @@ class AudioPlayer {
|
|||
// reset effects to their default parameters
|
||||
this.clearEffects();
|
||||
|
||||
// sound players that are currently playing, indexed by the sound's md5
|
||||
// sound players that are currently playing, indexed by the sound's soundId
|
||||
this.activeSoundPlayers = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Play a sound
|
||||
* @param {string} md5 - the md5 id of a sound file
|
||||
* @param {string} soundId - the soundId id of a sound file
|
||||
* @return {Promise} a Promise that resolves when the sound finishes playing
|
||||
*/
|
||||
playSound (md5) {
|
||||
playSound (soundId) {
|
||||
// if this sound is not in the audio engine, return
|
||||
if (!this.audioEngine.audioBuffers[md5]) {
|
||||
if (!this.audioEngine.audioBuffers[soundId]) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if this sprite or clone is already playing this sound, stop it first
|
||||
if (this.activeSoundPlayers[md5]) {
|
||||
this.activeSoundPlayers[md5].stop();
|
||||
if (this.activeSoundPlayers[soundId]) {
|
||||
this.activeSoundPlayers[soundId].stop();
|
||||
}
|
||||
|
||||
// create a new soundplayer to play the sound
|
||||
const player = new SoundPlayer(this.audioEngine.audioContext);
|
||||
player.setBuffer(this.audioEngine.audioBuffers[md5]);
|
||||
player.setBuffer(this.audioEngine.audioBuffers[soundId]);
|
||||
player.connect(this.effectsNode);
|
||||
this.pitchEffect.updatePlayer(player);
|
||||
player.start();
|
||||
|
||||
// add it to the list of active sound players
|
||||
this.activeSoundPlayers[md5] = player;
|
||||
this.activeSoundPlayers[soundId] = player;
|
||||
|
||||
// remove sounds that are not playing from the active sound players array
|
||||
for (const id in this.activeSoundPlayers) {
|
||||
|
@ -98,8 +99,8 @@ class AudioPlayer {
|
|||
*/
|
||||
stopAllSounds () {
|
||||
// stop all active sound players
|
||||
for (const md5 in this.activeSoundPlayers) {
|
||||
this.activeSoundPlayers[md5].stop();
|
||||
for (const soundId in this.activeSoundPlayers) {
|
||||
this.activeSoundPlayers[soundId].stop();
|
||||
}
|
||||
|
||||
// stop all instruments
|
||||
|
@ -168,7 +169,7 @@ class AudioEngine {
|
|||
this.drumPlayer = new DrumPlayer(this.audioContext);
|
||||
this.numDrums = this.drumPlayer.drumSounds.length;
|
||||
|
||||
// a map of md5s to audio buffers, holding sounds for all sprites
|
||||
// a map of soundIds to audio buffers, holding sounds for all sprites
|
||||
this.audioBuffers = {};
|
||||
|
||||
// microphone, for measuring loudness, with a level meter analyzer
|
||||
|
@ -188,15 +189,14 @@ class AudioEngine {
|
|||
|
||||
/**
|
||||
* Decode a sound, decompressing it into audio samples.
|
||||
* Store a reference to it the sound in the audioBuffers dictionary, indexed by md5
|
||||
* Store a reference to it the sound in the audioBuffers dictionary, indexed by soundId
|
||||
* @param {object} sound - an object containing audio data and metadata for a sound
|
||||
* @property {Buffer} data - sound data loaded from scratch-storage.
|
||||
* @property {string} format - format type, either empty or adpcm.
|
||||
* @property {string} md5 - the MD5 and extension of the sound.
|
||||
* @returns {?Promise} - a promise which will resolve after the audio buffer is stored, or null on error.
|
||||
* @returns {?Promise} - a promise which will resolve to the soundId if decoded and stored.
|
||||
*/
|
||||
decodeSound (sound) {
|
||||
|
||||
const soundId = uid();
|
||||
let loaderPromise = null;
|
||||
|
||||
// Make a copy of the buffer because decoding detaches the original buffer
|
||||
|
@ -216,7 +216,8 @@ class AudioEngine {
|
|||
const storedContext = this;
|
||||
return loaderPromise.then(
|
||||
decodedAudio => {
|
||||
storedContext.audioBuffers[sound.md5] = decodedAudio;
|
||||
storedContext.audioBuffers[soundId] = decodedAudio;
|
||||
return soundId;
|
||||
},
|
||||
error => {
|
||||
log.warn('audio data could not be decoded', error);
|
||||
|
|
29
src/uid.js
Normal file
29
src/uid.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* @fileoverview UID generator, from Blockly.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Legal characters for the unique ID.
|
||||
* Should be all on a US keyboard. No XML special characters or control codes.
|
||||
* Removed $ due to issue 251.
|
||||
* @private
|
||||
*/
|
||||
const soup_ = '!#%()*+,-./:;=?@[]^_`{|}~' +
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
|
||||
/**
|
||||
* Generate a unique ID, from Blockly. This should be globally unique.
|
||||
* 87 characters ^ 20 length > 128 bits (better than a UUID).
|
||||
* @return {string} A globally unique ID string.
|
||||
*/
|
||||
const uid = function () {
|
||||
const length = 20;
|
||||
const soupLength = soup_.length;
|
||||
const id = [];
|
||||
for (let i = 0; i < length; i++) {
|
||||
id[i] = soup_.charAt(Math.random() * soupLength);
|
||||
}
|
||||
return id.join('');
|
||||
};
|
||||
|
||||
module.exports = uid;
|
Loading…
Reference in a new issue