starting to load sounds from project files

This commit is contained in:
Eric Rosenbaum 2016-09-28 16:42:25 -04:00
parent fbaad0fe06
commit 6988cfc0d3
6 changed files with 88 additions and 18 deletions

View file

@ -23,10 +23,6 @@ function AudioEngine () {
this.reverb.wet.value = 0; this.reverb.wet.value = 0;
Tone.Master.chain(this.delay, this.pitchShift, this.panner, this.reverb); Tone.Master.chain(this.delay, this.pitchShift, this.panner, this.reverb);
// synth setup for play note block
this.synth = new Tone.PolySynth(6, Tone.Synth).toMaster();
// drum sounds // drum sounds
@ -35,20 +31,37 @@ function AudioEngine () {
// sound files // sound files
var soundFileNames = ['meow','boing','cave','drip_drop','drum_machine','eggs','zoop']; // var soundFileNames = ['meow','boing','cave','drip_drop','drum_machine','eggs','zoop'];
this.soundSamplers = this._loadSoundFiles(soundFileNames); // this.soundSamplers = this._loadSoundFiles(soundFileNames);
// sound urls - map each url to its tone.sampler
this.soundSamplers = [];
} }
AudioEngine.prototype.playSound = function (soundNum) { AudioEngine.prototype.playSound = function (soundNum) {
this.soundSamplers[soundNum].triggerAttack(); this.soundSamplers[soundNum].triggerAttack();
}; };
AudioEngine.prototype.playSoundFromUrl = function (url) {
if (url) {
// if we've loaded it already, play it
if (this.soundSamplers[url]) {
this.soundSamplers[url].triggerAttack();
} else {
// else load, play, and store it
var sampler = new Tone.Sampler(url, function() {sampler.triggerAttack();}).toMaster();
this.soundSamplers[url] = sampler;
}
}
};
AudioEngine.prototype.getSoundDuration = function (soundNum) { AudioEngine.prototype.getSoundDuration = function (soundNum) {
return this.soundSamplers[soundNum].player.buffer.duration; return this.soundSamplers[soundNum].player.buffer.duration;
}; };
AudioEngine.prototype.playNoteForBeats = function(note, beats) { AudioEngine.prototype.playNoteForBeats = function(note, beats) {
this.instrument.play(note, this.tone.now(), beats); this.instrument.start(note, Tone.context.currentTime, beats);
// this.instrument.play(note).stop(Tone.context.currentTime+beats);
}; };
AudioEngine.prototype.playDrumForBeats = function(drumNum, beats) { AudioEngine.prototype.playDrumForBeats = function(drumNum, beats) {
@ -56,8 +69,6 @@ AudioEngine.prototype.playDrumForBeats = function(drumNum, beats) {
}; };
AudioEngine.prototype.stopAllSounds = function() { AudioEngine.prototype.stopAllSounds = function() {
// stop synth notes
this.synth.releaseAll();
// stop drum notes // stop drum notes
for (var i=0; i<this.drumSamplers.length; i++) { for (var i=0; i<this.drumSamplers.length; i++) {
this.drumSamplers[i].triggerRelease(); this.drumSamplers[i].triggerRelease();
@ -66,6 +77,8 @@ AudioEngine.prototype.stopAllSounds = function() {
for (var i=0; i<this.soundSamplers.length; i++) { for (var i=0; i<this.soundSamplers.length; i++) {
this.soundSamplers[i].triggerRelease(); this.soundSamplers[i].triggerRelease();
} }
// stop soundfont notes
this.instrument.stop();
}; };
AudioEngine.prototype.setEffect = function(effect, value) { AudioEngine.prototype.setEffect = function(effect, value) {
@ -112,6 +125,10 @@ AudioEngine.prototype.clearEffects = function() {
this.pitchShift.pitch = 0; this.pitchShift.pitch = 0;
} }
AudioEngine.prototype.loadSoundFromUrl = function(url) {
};
AudioEngine.prototype._loadSoundFiles = function(filenames) { AudioEngine.prototype._loadSoundFiles = function(filenames) {
var samplers = []; var samplers = [];

View file

@ -269,16 +269,16 @@
<category name="Sound" colour="#D65CD6"> <category name="Sound" colour="#D65CD6">
<block type="sound_playsound"> <block type="sound_play">
<value name="SOUND_NUM"> <value name="SOUND_MENU">
<shadow type="sound_sounds_menu"> <shadow type="sound_sounds_option">
</shadow> </shadow>
</value> </value>
</block> </block>
<block type="sound_playuntildone"> <block type="sound_playuntildone">
<value name="SOUND_NUM"> <value name="SOUND_MENU">
<shadow type="sound_sounds_menu"> <shadow type="sound_sounds_option">
</shadow> </shadow>
</value> </value>
</block> </block>

View file

@ -1,4 +1,5 @@
var Cast = require('../util/cast'); var Cast = require('../util/cast');
var MathUtil = require('../util/math-util');
var Promise = require('promise'); var Promise = require('promise');
function Scratch3SoundBlocks(runtime) { function Scratch3SoundBlocks(runtime) {
@ -15,7 +16,7 @@ function Scratch3SoundBlocks(runtime) {
*/ */
Scratch3SoundBlocks.prototype.getPrimitives = function() { Scratch3SoundBlocks.prototype.getPrimitives = function() {
return { return {
'sound_playsound': this.playSound, 'sound_play': this.playSound,
'sound_playuntildone': this.playSoundAndWait, 'sound_playuntildone': this.playSoundAndWait,
'sound_stopallsounds': this.stopAllSounds, 'sound_stopallsounds': this.stopAllSounds,
'sound_playnoteforbeats': this.playNoteForBeats, 'sound_playnoteforbeats': this.playNoteForBeats,
@ -30,12 +31,31 @@ Scratch3SoundBlocks.prototype.getPrimitives = function() {
}; };
Scratch3SoundBlocks.prototype.playSound = function (args, util) { Scratch3SoundBlocks.prototype.playSound = function (args, util) {
window.audioEngine.playSound(args.SOUND_NUM); var url = this._getSoundUrl(args.SOUND_MENU, util);
window.audioEngine.playSoundFromUrl(url);
}; };
Scratch3SoundBlocks.prototype._getSoundUrl = function (soundName, util) {
if (util.target.sprite.sounds.length == 0) {
return '';
}
var index;
if (typeof soundName === 'number') {
index = MathUtil.wrapClamp(soundName,0,util.target.sprite.sounds.length);
} else {
index = util.target.getSoundIndexByName(soundName);
if (index == -1) {
return '';
}
}
return util.target.sprite.sounds[index].soundFile;
};
Scratch3SoundBlocks.prototype.playSoundAndWait = function (args, util) { Scratch3SoundBlocks.prototype.playSoundAndWait = function (args, util) {
window.audioEngine.playSound(args.SOUND_NUM); // window.audioEngine.playSound(args.SOUND_NUM);
var duration = window.audioEngine.getSoundDuration(args.SOUND_NUM); // var duration = window.audioEngine.getSoundDuration(args.SOUND_NUM);
return new Promise(function(resolve) { return new Promise(function(resolve) {
setTimeout(function() { setTimeout(function() {
resolve(); resolve();

View file

@ -62,6 +62,21 @@ function parseScratchObject (object, runtime, topLevel) {
}); });
} }
} }
// Sounds from JSON
if (object.hasOwnProperty('sounds')) {
for (var i = 0; i < object.sounds.length; i++) {
var sound = object.sounds[i];
sprite.sounds.push({
format: sound.format,
soundFile: 'https://cdn.assets.scratch.mit.edu/internalapi/asset/'
+ sound.md5 + '/get/',
rate: sound.rate,
sampleCount: sound.sampleCount,
soundID: sound.soundID,
name: sound.soundName
});
}
}
// If included, parse any and all scripts/blocks on the object. // If included, parse any and all scripts/blocks on the object.
if (object.hasOwnProperty('scripts')) { if (object.hasOwnProperty('scripts')) {
parseScripts(object.scripts, blocks); parseScripts(object.scripts, blocks);

View file

@ -255,6 +255,20 @@ Clone.prototype.getCostumeIndexByName = function (costumeName) {
return -1; return -1;
}; };
/**
* Get a sound index of this clone, by name of the sound.
* @param {?string} soundName Name of a sound.
* @return {number} Index of the named sound, or -1 if not present.
*/
Clone.prototype.getSoundIndexByName = function (soundName) {
for (var i = 0; i < this.sprite.sounds.length; i++) {
if (this.sprite.sounds[i].name == soundName) {
return i;
}
}
return -1;
};
/** /**
* Update all drawable properties for this clone. * Update all drawable properties for this clone.
* Use when a batch has changed, e.g., when the drawable is first created. * Use when a batch has changed, e.g., when the drawable is first created.

View file

@ -33,6 +33,10 @@ function Sprite (blocks, runtime) {
* @type {Array.<!Object>} * @type {Array.<!Object>}
*/ */
this.costumes = []; this.costumes = [];
/**
* List of sounds for this sprite.
*/
this.sounds = [];
/** /**
* List of clones for this sprite, including the original. * List of clones for this sprite, including the original.
* @type {Array.<!Clone>} * @type {Array.<!Clone>}