diff --git a/audioLocal.js b/audioLocal.js index 1f31a1a1e..4c1eb7737 100644 --- a/audioLocal.js +++ b/audioLocal.js @@ -39,29 +39,15 @@ AudioLocal.prototype._loadSoundFiles = function(filenames) { var samplers = []; for (var name of filenames) { - - // create an array of samplers for each sound (a hack to get polyphony for each sound) - var myVoices = []; - for (var i=0; i<6; i++) { - var p = new Tone.Sampler('sounds/' + name + '.mp3').toMaster(); - myVoices.push(p); - } - - var polySampler = { - voices : myVoices, - currentVoice : 0, - nextVoice : function() {return this.voices[this.currentVoice++ % this.voices.length];}, - stopAllVoices : function() {for (var i=0;i<this.voices.length;i++) {this.voices[i].triggerRelease()}}, - }; - - samplers.push(polySampler); + var sampler = new Tone.Sampler('sounds/' + name + '.mp3').toMaster(); + samplers.push(sampler); } return samplers; }; -AudioLocal.prototype.midiToFreq = function(midiNote) { - var freq = tone.intervalToFrequencyRatio(midiNote - 60) * 261.63; // 60 is C4 +AudioLocal.prototype._midiToFreq = function(midiNote) { + var freq = this.tone.intervalToFrequencyRatio(midiNote - 60) * 261.63; // 60 is C4 return freq; }; @@ -70,11 +56,16 @@ AudioLocal.prototype.clamp = function(input, min, max) { }; AudioLocal.prototype.playNoteForBeats = function(note, beats) { - var midiNote = scaleNoteToMidiNote(note, currentScale, rootNote); - var freq = midiToFreq(midiNote); - synth.triggerAttackRelease(freq, beats, quantizeUnit); + var freq = this._midiToFreq(note); + this.synth.triggerAttackRelease(freq, beats); }; +AudioLocal.prototype.stopAllSounds = function() { + // stop sounds triggered with playSound + for (var i=0; i<this.soundSamplers.length; i++) { + this.soundSamplers[i].triggerRelease(); + } +}; AudioLocal.prototype.connectWorker = function(worker) { var instance = this; @@ -87,7 +78,14 @@ AudioLocal.prototype._onWorkerMessage = function(worker, message) { if (message.data.type == 'audio') { switch(message.data.method) { case 'playSound' : - this.soundSamplers[message.data.value].nextVoice().triggerAttack(); + this.soundSamplers[message.data.value].triggerRelease(); + this.soundSamplers[message.data.value].triggerAttack(); + break; + case 'stopAllSounds' : + this.stopAllSounds(); + break; + case 'playNoteForBeats' : + this.playNoteForBeats(message.data.note, message.data.beats); break; } } diff --git a/audioWorker.js b/audioWorker.js index 668d53253..9cbdbcea1 100644 --- a/audioWorker.js +++ b/audioWorker.js @@ -10,4 +10,20 @@ AudioWorker.prototype.playSound = function (soundNum) { }); }; +AudioWorker.prototype.stopAllSounds = function () { + self.postMessage({ + type: 'audio', + method: 'stopAllSounds' + }); +}; + +AudioWorker.prototype.playNoteForBeats = function (note, beats) { + self.postMessage({ + type: 'audio', + method: 'playNoteForBeats', + note: note, + beats: beats + }); +}; + module.exports = AudioWorker; \ No newline at end of file diff --git a/playground/index.html b/playground/index.html index 64992b602..73182ec39 100644 --- a/playground/index.html +++ b/playground/index.html @@ -278,28 +278,8 @@ </value> </block> - <block type="sound_playwithpitch"> - <value name="SOUND_NUM"> - <shadow type="sound_sounds_menu"> - </shadow> - </value> - <value name="PITCH"> - <shadow type="math_number"> - <field name="NUM">1</field> - </shadow> - </value> - </block> - <block type="sound_stopallsounds"></block> - <block type="sound_playdrum"> - <value name="DRUMTYPE"> - <shadow type="math_number"> - <field name="NUM">1</field> - </shadow> - </value> - </block> - <block type="sound_playdrumforbeats"> <value name="DRUMTYPE"> <shadow type="math_number"> @@ -320,18 +300,10 @@ </value> </block> - <block type="sound_playnote"> - <value name="NOTE"> - <shadow type="math_number"> - <field name="NUM">1</field> - </shadow> - </value> - </block> - <block type="sound_playnoteforbeats"> <value name="NOTE"> <shadow type="math_number"> - <field name="NUM">1</field> + <field name="NUM">60</field> </shadow> </value> <value name="BEATS"> @@ -339,34 +311,7 @@ </shadow> </value> </block> - - <block type="sound_scalenotetomidinote"> - <value name="NOTE"> - <shadow type="math_number"> - <field name="NUM">1</field> - </shadow> - </value> - <value name="ROOT"> - <shadow type="sound_roots_menu"> - </shadow> - </value> - <value name="SCALE"> - <shadow type="sound_scales_menu"> - </shadow> - </value> - </block> - - <block type="sound_setkey"> - <value name="ROOT"> - <shadow type="sound_roots_menu"> - </shadow> - </value> - <value name="SCALE"> - <shadow type="sound_scales_menu"> - </shadow> - </value> - </block> - + <block type="sound_seteffectto"> <value name="EFFECT"> <shadow type="sound_effects_menu"></shadow> diff --git a/src/blocks/scratch3_sound.js b/src/blocks/scratch3_sound.js index 4706c7d68..e0777ab42 100644 --- a/src/blocks/scratch3_sound.js +++ b/src/blocks/scratch3_sound.js @@ -13,74 +13,34 @@ function Scratch3SoundBlocks(runtime) { Scratch3SoundBlocks.prototype.getPrimitives = function() { return { 'sound_playsound': this.playSound, - 'sound_playwithpitch': this.playSoundWithPitch, + // 'sound_playsoundandwait': this.playSoundAndWait, 'sound_stopallsounds': this.stopAllSounds, - 'sound_playnote': this.playNote, 'sound_playnoteforbeats': this.playNoteForBeats, - 'sound_scalenotetomidinote': this.scaleNoteToMidiNote, - 'sound_playdrum': this.playDrum, 'sound_playdrumforbeats': this.playDrumForBeats, - 'sound_setkey' : this.setKey, 'sound_seteffectto' : this.setEffect, 'sound_changeeffectby' : this.changeEffect, 'sound_cleareffects' : this.clearEffects, - 'sound_scales_menu' : this.scalesMenu, 'sound_sounds_menu' : this.soundsMenu, - 'sound_roots_menu' : this.rootsMenu, 'sound_beats_menu' : this.beatsMenu, 'sound_effects_menu' : this.effectsMenu, }; }; Scratch3SoundBlocks.prototype.playSound = function (args, util) { - // self.postMessage({method: 'playsound', soundnum:args.SOUND_NUM}); util.target.playSound(args.SOUND_NUM); }; -Scratch3SoundBlocks.prototype.playSoundWithPitch = function (args, util) { - self.postMessage({method: 'playsoundwithpitch', soundnum:args.SOUND_NUM, pitch:args.PITCH}); -}; - Scratch3SoundBlocks.prototype.stopAllSounds = function (args, util) { - self.postMessage({method: 'stopallsounds'}); + util.target.stopAllSounds(); }; Scratch3SoundBlocks.prototype.playNoteForBeats = function (args, util) { - self.postMessage({method: 'playnoteforbeats', note:args.NOTE, beats:args.BEATS}); - return new Promise(function(resolve) { - setTimeout(function() { - resolve(); - }, (1000 * args.BEATS) ); - }); -}; - -Scratch3SoundBlocks.prototype.playNote = function (args, util) { - self.postMessage({method: 'playnote', note:args.NOTE}); -}; - -Scratch3SoundBlocks.prototype.scaleNoteToMidiNote = function (args, util) { - - var root = parseInt(args.ROOT) + 60; - - var scales = { - 'MAJOR' : [0,2,4,5,7,9,11], - 'MINOR' : [0,2,3,5,7,8,10], - 'PENTATONIC': [0, 2, 4, 7, 9], - 'CHROMATIC' : [0,1,2,3,4,5,6,7,8,9,10,11], - }; - - var scale = scales[args.SCALE]; - - var scaleNote = args.NOTE; - - var scaleIndex = (Math.round(scaleNote) - 1) % scale.length; - if (scaleIndex < 0) { - scaleIndex += scale.length; - } - var octave = Math.floor((scaleNote - 1) / scale.length); - var midiNote = root + (octave * 12) + scale[scaleIndex]; - - return midiNote; + util.target.playNoteForBeats(args.NOTE, args.BEATS); + return new Promise(function(resolve) { + setTimeout(function() { + resolve(); + }, (1000 * args.BEATS) ); + }); }; Scratch3SoundBlocks.prototype.playDrumForBeats = function (args, util) { @@ -92,14 +52,6 @@ Scratch3SoundBlocks.prototype.playDrumForBeats = function (args, util) { }); }; -Scratch3SoundBlocks.prototype.playDrum = function (args, util) { - self.postMessage({method: 'playdrum', drum:args.DRUMTYPE}); -}; - -Scratch3SoundBlocks.prototype.setKey = function (args, util) { - self.postMessage({method: 'setkey', root:args.ROOT, scale:args.SCALE}); -}; - Scratch3SoundBlocks.prototype.setEffect = function (args, util) { self.postMessage({method: 'seteffect', effect:args.EFFECT, value:args.VALUE}); }; @@ -116,14 +68,6 @@ Scratch3SoundBlocks.prototype.soundsMenu = function (args, util) { return args.SOUND_MENU; }; -Scratch3SoundBlocks.prototype.scalesMenu = function (args, util) { - return args.SCALE; -}; - -Scratch3SoundBlocks.prototype.rootsMenu = function (args, util) { - return args.ROOT; -}; - Scratch3SoundBlocks.prototype.beatsMenu = function (args, util) { return args.BEATS; }; diff --git a/src/sprites/clone.js b/src/sprites/clone.js index 4f2c20a15..523a00fdd 100644 --- a/src/sprites/clone.js +++ b/src/sprites/clone.js @@ -244,4 +244,12 @@ Clone.prototype.playSound = function (soundNum) { this.audioWorker.playSound(soundNum); } +Clone.prototype.stopAllSounds = function () { + this.audioWorker.stopAllSounds(); +} + +Clone.prototype.playNoteForBeats = function (note,beats) { + this.audioWorker.playNoteForBeats(note, beats); +} + module.exports = Clone;