mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-23 14:32:59 -05:00
Merge pull request #936 from ericrosenbaum/feature/require-music-assets
Feature/require music assets
This commit is contained in:
commit
ca08cd69e9
4 changed files with 123 additions and 37 deletions
|
@ -33,12 +33,14 @@
|
||||||
"babel-eslint": "^7.1.1",
|
"babel-eslint": "^7.1.1",
|
||||||
"babel-loader": "^7.0.0",
|
"babel-loader": "^7.0.0",
|
||||||
"babel-preset-es2015": "^6.24.1",
|
"babel-preset-es2015": "^6.24.1",
|
||||||
|
"buffer-loader": "0.0.1",
|
||||||
"copy-webpack-plugin": "4.2.1",
|
"copy-webpack-plugin": "4.2.1",
|
||||||
"decode-html": "2.0.0",
|
"decode-html": "2.0.0",
|
||||||
"escape-html": "1.0.3",
|
"escape-html": "1.0.3",
|
||||||
"eslint": "^4.5.0",
|
"eslint": "^4.5.0",
|
||||||
"eslint-config-scratch": "^5.0.0",
|
"eslint-config-scratch": "^5.0.0",
|
||||||
"expose-loader": "0.7.4",
|
"expose-loader": "0.7.4",
|
||||||
|
"file-loader": "^1.1.6",
|
||||||
"format-message": "5.2.1",
|
"format-message": "5.2.1",
|
||||||
"format-message-cli": "5.2.1",
|
"format-message-cli": "5.2.1",
|
||||||
"gh-pages": "^1.1.0",
|
"gh-pages": "^1.1.0",
|
||||||
|
|
|
@ -5,6 +5,17 @@ const Cast = require('../../util/cast');
|
||||||
const MathUtil = require('../../util/math-util');
|
const MathUtil = require('../../util/math-util');
|
||||||
const Timer = require('../../util/timer');
|
const Timer = require('../../util/timer');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The instrument and drum sounds, loaded as static assets.
|
||||||
|
* @type {object}
|
||||||
|
*/
|
||||||
|
let assetData = {};
|
||||||
|
try {
|
||||||
|
assetData = require('./manifest');
|
||||||
|
} catch (e) {
|
||||||
|
// Non-webpack environment, don't worry about assets.
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Icon svg to be displayed at the left edge of each extension block, encoded as a data URI.
|
* Icon svg to be displayed at the left edge of each extension block, encoded as a data URI.
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -73,21 +84,20 @@ class Scratch3MusicBlocks {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Download and decode the full set of drum and instrument sounds, and
|
* Decode the full set of drum and instrument sounds, and store the audio buffers in arrays.
|
||||||
* store the audio buffers in arrays.
|
|
||||||
*/
|
*/
|
||||||
_loadAllSounds () {
|
_loadAllSounds () {
|
||||||
const loadingPromises = [];
|
const loadingPromises = [];
|
||||||
this.DRUM_INFO.forEach((drumInfo, index) => {
|
this.DRUM_INFO.forEach((drumInfo, index) => {
|
||||||
const fileName = `drums/${drumInfo.fileName}`;
|
const filePath = `drums/${drumInfo.fileName}`;
|
||||||
const promise = this._loadSound(fileName, index, this._drumBuffers);
|
const promise = this._storeSound(filePath, index, this._drumBuffers);
|
||||||
loadingPromises.push(promise);
|
loadingPromises.push(promise);
|
||||||
});
|
});
|
||||||
this.INSTRUMENT_INFO.forEach((instrumentInfo, instrumentIndex) => {
|
this.INSTRUMENT_INFO.forEach((instrumentInfo, instrumentIndex) => {
|
||||||
this._instrumentBufferArrays[instrumentIndex] = [];
|
this._instrumentBufferArrays[instrumentIndex] = [];
|
||||||
instrumentInfo.samples.forEach((sample, noteIndex) => {
|
instrumentInfo.samples.forEach((sample, noteIndex) => {
|
||||||
const fileName = `instruments/${instrumentInfo.dirName}/${sample}`;
|
const filePath = `instruments/${instrumentInfo.dirName}/${sample}`;
|
||||||
const promise = this._loadSound(fileName, noteIndex, this._instrumentBufferArrays[instrumentIndex]);
|
const promise = this._storeSound(filePath, noteIndex, this._instrumentBufferArrays[instrumentIndex]);
|
||||||
loadingPromises.push(promise);
|
loadingPromises.push(promise);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -97,35 +107,48 @@ class Scratch3MusicBlocks {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Download and decode a sound, and store the buffer in an array.
|
* Decode a sound and store the buffer in an array.
|
||||||
* @param {string} fileName - the audio file name.
|
* @param {string} filePath - the audio file name.
|
||||||
* @param {number} index - the index at which to store the audio buffer.
|
* @param {number} index - the index at which to store the audio buffer.
|
||||||
* @param {array} bufferArray - the array of buffers in which to store it.
|
* @param {array} bufferArray - the array of buffers in which to store it.
|
||||||
* @return {Promise} - a promise which will resolve once the sound has loaded.
|
* @return {Promise} - a promise which will resolve once the sound has been stored.
|
||||||
*/
|
*/
|
||||||
_loadSound (fileName, index, bufferArray) {
|
_storeSound (filePath, index, bufferArray) {
|
||||||
if (!this.runtime.storage) return;
|
const fullPath = `${filePath}.mp3`;
|
||||||
|
|
||||||
|
if (!assetData[fullPath]) return;
|
||||||
|
|
||||||
|
// The sound buffer has already been downloaded via the manifest file required above.
|
||||||
|
const soundBuffer = assetData[fullPath].buffer;
|
||||||
|
|
||||||
|
return this._decodeSound(soundBuffer).then(buffer => {
|
||||||
|
bufferArray[index] = buffer;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode a sound and return a promise with the audio buffer.
|
||||||
|
* @param {ArrayBuffer} soundBuffer - a buffer containing the encoded audio.
|
||||||
|
* @return {Promise} - a promise which will resolve once the sound has decoded.
|
||||||
|
*/
|
||||||
|
_decodeSound (soundBuffer) {
|
||||||
if (!this.runtime.audioEngine) return;
|
if (!this.runtime.audioEngine) return;
|
||||||
if (!this.runtime.audioEngine.audioContext) return;
|
if (!this.runtime.audioEngine.audioContext) return;
|
||||||
return this.runtime.storage.load(this.runtime.storage.AssetType.Sound, fileName, 'mp3')
|
|
||||||
.then(soundAsset => {
|
const context = this.runtime.audioEngine.audioContext;
|
||||||
const context = this.runtime.audioEngine.audioContext;
|
|
||||||
// Check for newer promise-based API
|
// Check for newer promise-based API
|
||||||
if (context.decodeAudioData.length === 1) {
|
if (context.decodeAudioData.length === 1) {
|
||||||
return context.decodeAudioData(soundAsset.data.buffer);
|
return context.decodeAudioData(soundBuffer);
|
||||||
} else { // eslint-disable-line no-else-return
|
} else { // eslint-disable-line no-else-return
|
||||||
// Fall back to callback API
|
// Fall back to callback API
|
||||||
return new Promise((resolve, reject) =>
|
return new Promise((resolve, reject) =>
|
||||||
context.decodeAudioData(soundAsset.data.buffer,
|
context.decodeAudioData(soundBuffer,
|
||||||
buffer => resolve(buffer),
|
buffer => resolve(buffer),
|
||||||
error => reject(error)
|
error => reject(error)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.then(buffer => {
|
|
||||||
bufferArray[index] = buffer;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
63
src/extensions/scratch3_music/manifest.js
Normal file
63
src/extensions/scratch3_music/manifest.js
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
module.exports = {
|
||||||
|
'drums/1-snare.mp3': require('!buffer-loader!./assets/drums/1-snare.mp3'),
|
||||||
|
'drums/2-bass-drum.mp3': require('!buffer-loader!./assets/drums/2-bass-drum.mp3'),
|
||||||
|
'drums/3-side-stick.mp3': require('!buffer-loader!./assets/drums/3-side-stick.mp3'),
|
||||||
|
'drums/4-crash-cymbal.mp3': require('!buffer-loader!./assets/drums/4-crash-cymbal.mp3'),
|
||||||
|
'drums/5-open-hi-hat.mp3': require('!buffer-loader!./assets/drums/5-open-hi-hat.mp3'),
|
||||||
|
'drums/6-closed-hi-hat.mp3': require('!buffer-loader!./assets/drums/6-closed-hi-hat.mp3'),
|
||||||
|
'drums/7-tambourine.mp3': require('!buffer-loader!./assets/drums/7-tambourine.mp3'),
|
||||||
|
'drums/8-hand-clap.mp3': require('!buffer-loader!./assets/drums/8-hand-clap.mp3'),
|
||||||
|
'drums/9-claves.mp3': require('!buffer-loader!./assets/drums/9-claves.mp3'),
|
||||||
|
'drums/10-wood-block.mp3': require('!buffer-loader!./assets/drums/10-wood-block.mp3'),
|
||||||
|
'drums/11-cowbell.mp3': require('!buffer-loader!./assets/drums/11-cowbell.mp3'),
|
||||||
|
'drums/12-triangle.mp3': require('!buffer-loader!./assets/drums/12-triangle.mp3'),
|
||||||
|
'drums/13-bongo.mp3': require('!buffer-loader!./assets/drums/13-bongo.mp3'),
|
||||||
|
'drums/14-conga.mp3': require('!buffer-loader!./assets/drums/14-conga.mp3'),
|
||||||
|
'drums/15-cabasa.mp3': require('!buffer-loader!./assets/drums/15-cabasa.mp3'),
|
||||||
|
'drums/16-guiro.mp3': require('!buffer-loader!./assets/drums/16-guiro.mp3'),
|
||||||
|
'drums/17-vibraslap.mp3': require('!buffer-loader!./assets/drums/17-vibraslap.mp3'),
|
||||||
|
'drums/18-cuica.mp3': require('!buffer-loader!./assets/drums/18-cuica.mp3'),
|
||||||
|
'instruments/1-piano/24.mp3': require('!buffer-loader!./assets/instruments/1-piano/24.mp3'),
|
||||||
|
'instruments/1-piano/36.mp3': require('!buffer-loader!./assets/instruments/1-piano/36.mp3'),
|
||||||
|
'instruments/1-piano/48.mp3': require('!buffer-loader!./assets/instruments/1-piano/48.mp3'),
|
||||||
|
'instruments/1-piano/60.mp3': require('!buffer-loader!./assets/instruments/1-piano/60.mp3'),
|
||||||
|
'instruments/1-piano/72.mp3': require('!buffer-loader!./assets/instruments/1-piano/72.mp3'),
|
||||||
|
'instruments/1-piano/84.mp3': require('!buffer-loader!./assets/instruments/1-piano/84.mp3'),
|
||||||
|
'instruments/1-piano/96.mp3': require('!buffer-loader!./assets/instruments/1-piano/96.mp3'),
|
||||||
|
'instruments/1-piano/108.mp3': require('!buffer-loader!./assets/instruments/1-piano/108.mp3'),
|
||||||
|
'instruments/2-electric-piano/60.mp3': require('!buffer-loader!./assets/instruments/2-electric-piano/60.mp3'),
|
||||||
|
'instruments/3-organ/60.mp3': require('!buffer-loader!./assets/instruments/3-organ/60.mp3'),
|
||||||
|
'instruments/4-guitar/60.mp3': require('!buffer-loader!./assets/instruments/4-guitar/60.mp3'),
|
||||||
|
'instruments/5-electric-guitar/60.mp3': require('!buffer-loader!./assets/instruments/5-electric-guitar/60.mp3'),
|
||||||
|
'instruments/6-bass/36.mp3': require('!buffer-loader!./assets/instruments/6-bass/36.mp3'),
|
||||||
|
'instruments/6-bass/48.mp3': require('!buffer-loader!./assets/instruments/6-bass/48.mp3'),
|
||||||
|
'instruments/7-pizzicato/60.mp3': require('!buffer-loader!./assets/instruments/7-pizzicato/60.mp3'),
|
||||||
|
'instruments/8-cello/36.mp3': require('!buffer-loader!./assets/instruments/8-cello/36.mp3'),
|
||||||
|
'instruments/8-cello/48.mp3': require('!buffer-loader!./assets/instruments/8-cello/48.mp3'),
|
||||||
|
'instruments/8-cello/60.mp3': require('!buffer-loader!./assets/instruments/8-cello/60.mp3'),
|
||||||
|
'instruments/9-trombone/36.mp3': require('!buffer-loader!./assets/instruments/9-trombone/36.mp3'),
|
||||||
|
'instruments/9-trombone/48.mp3': require('!buffer-loader!./assets/instruments/9-trombone/48.mp3'),
|
||||||
|
'instruments/9-trombone/60.mp3': require('!buffer-loader!./assets/instruments/9-trombone/60.mp3'),
|
||||||
|
'instruments/10-clarinet/48.mp3': require('!buffer-loader!./assets/instruments/10-clarinet/48.mp3'),
|
||||||
|
'instruments/10-clarinet/60.mp3': require('!buffer-loader!./assets/instruments/10-clarinet/60.mp3'),
|
||||||
|
'instruments/11-saxophone/36.mp3': require('!buffer-loader!./assets/instruments/11-saxophone/36.mp3'),
|
||||||
|
'instruments/11-saxophone/60.mp3': require('!buffer-loader!./assets/instruments/11-saxophone/60.mp3'),
|
||||||
|
'instruments/11-saxophone/84.mp3': require('!buffer-loader!./assets/instruments/11-saxophone/84.mp3'),
|
||||||
|
'instruments/12-flute/60.mp3': require('!buffer-loader!./assets/instruments/12-flute/60.mp3'),
|
||||||
|
'instruments/12-flute/72.mp3': require('!buffer-loader!./assets/instruments/12-flute/72.mp3'),
|
||||||
|
'instruments/13-wooden-flute/60.mp3': require('!buffer-loader!./assets/instruments/13-wooden-flute/60.mp3'),
|
||||||
|
'instruments/13-wooden-flute/72.mp3': require('!buffer-loader!./assets/instruments/13-wooden-flute/72.mp3'),
|
||||||
|
'instruments/14-bassoon/36.mp3': require('!buffer-loader!./assets/instruments/14-bassoon/36.mp3'),
|
||||||
|
'instruments/14-bassoon/48.mp3': require('!buffer-loader!./assets/instruments/14-bassoon/48.mp3'),
|
||||||
|
'instruments/14-bassoon/60.mp3': require('!buffer-loader!./assets/instruments/14-bassoon/60.mp3'),
|
||||||
|
'instruments/15-choir/48.mp3': require('!buffer-loader!./assets/instruments/15-choir/48.mp3'),
|
||||||
|
'instruments/15-choir/60.mp3': require('!buffer-loader!./assets/instruments/15-choir/60.mp3'),
|
||||||
|
'instruments/15-choir/72.mp3': require('!buffer-loader!./assets/instruments/15-choir/72.mp3'),
|
||||||
|
'instruments/16-vibraphone/60.mp3': require('!buffer-loader!./assets/instruments/16-vibraphone/60.mp3'),
|
||||||
|
'instruments/16-vibraphone/72.mp3': require('!buffer-loader!./assets/instruments/16-vibraphone/72.mp3'),
|
||||||
|
'instruments/17-music-box/60.mp3': require('!buffer-loader!./assets/instruments/17-music-box/60.mp3'),
|
||||||
|
'instruments/18-steel-drum/60.mp3': require('!buffer-loader!./assets/instruments/18-steel-drum/60.mp3'),
|
||||||
|
'instruments/19-marimba/60.mp3': require('!buffer-loader!./assets/instruments/19-marimba/60.mp3'),
|
||||||
|
'instruments/20-synth-lead/60.mp3': require('!buffer-loader!./assets/instruments/20-synth-lead/60.mp3'),
|
||||||
|
'instruments/21-synth-pad/60.mp3': require('!buffer-loader!./assets/instruments/21-synth-pad/60.mp3')
|
||||||
|
};
|
|
@ -22,6 +22,10 @@ const base = {
|
||||||
query: {
|
query: {
|
||||||
presets: ['es2015']
|
presets: ['es2015']
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.mp3$/,
|
||||||
|
loader: 'file-loader'
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
plugins: process.env.NODE_ENV === 'production' ? [
|
plugins: process.env.NODE_ENV === 'production' ? [
|
||||||
|
@ -62,13 +66,7 @@ module.exports = [
|
||||||
output: {
|
output: {
|
||||||
libraryTarget: 'commonjs2',
|
libraryTarget: 'commonjs2',
|
||||||
path: path.resolve('dist', 'node')
|
path: path.resolve('dist', 'node')
|
||||||
},
|
}
|
||||||
plugins: base.plugins.concat([
|
|
||||||
new CopyWebpackPlugin([{
|
|
||||||
from: './src/extensions/scratch3_music/assets',
|
|
||||||
to: 'assets/scratch3_music'
|
|
||||||
}])
|
|
||||||
])
|
|
||||||
}),
|
}),
|
||||||
// Playground
|
// Playground
|
||||||
defaultsDeep({}, base, {
|
defaultsDeep({}, base, {
|
||||||
|
|
Loading…
Reference in a new issue