mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-24 06:52:40 -05:00
play sound and play note block
This commit is contained in:
parent
7709a4095e
commit
d9a703b4ad
5 changed files with 54 additions and 143 deletions
|
@ -39,29 +39,15 @@ AudioLocal.prototype._loadSoundFiles = function(filenames) {
|
||||||
var samplers = [];
|
var samplers = [];
|
||||||
|
|
||||||
for (var name of filenames) {
|
for (var name of filenames) {
|
||||||
|
var sampler = new Tone.Sampler('sounds/' + name + '.mp3').toMaster();
|
||||||
// create an array of samplers for each sound (a hack to get polyphony for each sound)
|
samplers.push(sampler);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return samplers;
|
return samplers;
|
||||||
};
|
};
|
||||||
|
|
||||||
AudioLocal.prototype.midiToFreq = function(midiNote) {
|
AudioLocal.prototype._midiToFreq = function(midiNote) {
|
||||||
var freq = tone.intervalToFrequencyRatio(midiNote - 60) * 261.63; // 60 is C4
|
var freq = this.tone.intervalToFrequencyRatio(midiNote - 60) * 261.63; // 60 is C4
|
||||||
return freq;
|
return freq;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -70,11 +56,16 @@ AudioLocal.prototype.clamp = function(input, min, max) {
|
||||||
};
|
};
|
||||||
|
|
||||||
AudioLocal.prototype.playNoteForBeats = function(note, beats) {
|
AudioLocal.prototype.playNoteForBeats = function(note, beats) {
|
||||||
var midiNote = scaleNoteToMidiNote(note, currentScale, rootNote);
|
var freq = this._midiToFreq(note);
|
||||||
var freq = midiToFreq(midiNote);
|
this.synth.triggerAttackRelease(freq, beats);
|
||||||
synth.triggerAttackRelease(freq, beats, quantizeUnit);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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) {
|
AudioLocal.prototype.connectWorker = function(worker) {
|
||||||
var instance = this;
|
var instance = this;
|
||||||
|
@ -87,7 +78,14 @@ AudioLocal.prototype._onWorkerMessage = function(worker, message) {
|
||||||
if (message.data.type == 'audio') {
|
if (message.data.type == 'audio') {
|
||||||
switch(message.data.method) {
|
switch(message.data.method) {
|
||||||
case 'playSound' :
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
module.exports = AudioWorker;
|
|
@ -278,28 +278,8 @@
|
||||||
</value>
|
</value>
|
||||||
</block>
|
</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_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">
|
<block type="sound_playdrumforbeats">
|
||||||
<value name="DRUMTYPE">
|
<value name="DRUMTYPE">
|
||||||
<shadow type="math_number">
|
<shadow type="math_number">
|
||||||
|
@ -320,18 +300,10 @@
|
||||||
</value>
|
</value>
|
||||||
</block>
|
</block>
|
||||||
|
|
||||||
<block type="sound_playnote">
|
|
||||||
<value name="NOTE">
|
|
||||||
<shadow type="math_number">
|
|
||||||
<field name="NUM">1</field>
|
|
||||||
</shadow>
|
|
||||||
</value>
|
|
||||||
</block>
|
|
||||||
|
|
||||||
<block type="sound_playnoteforbeats">
|
<block type="sound_playnoteforbeats">
|
||||||
<value name="NOTE">
|
<value name="NOTE">
|
||||||
<shadow type="math_number">
|
<shadow type="math_number">
|
||||||
<field name="NUM">1</field>
|
<field name="NUM">60</field>
|
||||||
</shadow>
|
</shadow>
|
||||||
</value>
|
</value>
|
||||||
<value name="BEATS">
|
<value name="BEATS">
|
||||||
|
@ -340,33 +312,6 @@
|
||||||
</value>
|
</value>
|
||||||
</block>
|
</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">
|
<block type="sound_seteffectto">
|
||||||
<value name="EFFECT">
|
<value name="EFFECT">
|
||||||
<shadow type="sound_effects_menu"></shadow>
|
<shadow type="sound_effects_menu"></shadow>
|
||||||
|
|
|
@ -13,40 +13,29 @@ function Scratch3SoundBlocks(runtime) {
|
||||||
Scratch3SoundBlocks.prototype.getPrimitives = function() {
|
Scratch3SoundBlocks.prototype.getPrimitives = function() {
|
||||||
return {
|
return {
|
||||||
'sound_playsound': this.playSound,
|
'sound_playsound': this.playSound,
|
||||||
'sound_playwithpitch': this.playSoundWithPitch,
|
// 'sound_playsoundandwait': this.playSoundAndWait,
|
||||||
'sound_stopallsounds': this.stopAllSounds,
|
'sound_stopallsounds': this.stopAllSounds,
|
||||||
'sound_playnote': this.playNote,
|
|
||||||
'sound_playnoteforbeats': this.playNoteForBeats,
|
'sound_playnoteforbeats': this.playNoteForBeats,
|
||||||
'sound_scalenotetomidinote': this.scaleNoteToMidiNote,
|
|
||||||
'sound_playdrum': this.playDrum,
|
|
||||||
'sound_playdrumforbeats': this.playDrumForBeats,
|
'sound_playdrumforbeats': this.playDrumForBeats,
|
||||||
'sound_setkey' : this.setKey,
|
|
||||||
'sound_seteffectto' : this.setEffect,
|
'sound_seteffectto' : this.setEffect,
|
||||||
'sound_changeeffectby' : this.changeEffect,
|
'sound_changeeffectby' : this.changeEffect,
|
||||||
'sound_cleareffects' : this.clearEffects,
|
'sound_cleareffects' : this.clearEffects,
|
||||||
'sound_scales_menu' : this.scalesMenu,
|
|
||||||
'sound_sounds_menu' : this.soundsMenu,
|
'sound_sounds_menu' : this.soundsMenu,
|
||||||
'sound_roots_menu' : this.rootsMenu,
|
|
||||||
'sound_beats_menu' : this.beatsMenu,
|
'sound_beats_menu' : this.beatsMenu,
|
||||||
'sound_effects_menu' : this.effectsMenu,
|
'sound_effects_menu' : this.effectsMenu,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
Scratch3SoundBlocks.prototype.playSound = function (args, util) {
|
Scratch3SoundBlocks.prototype.playSound = function (args, util) {
|
||||||
// self.postMessage({method: 'playsound', soundnum:args.SOUND_NUM});
|
|
||||||
util.target.playSound(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) {
|
Scratch3SoundBlocks.prototype.stopAllSounds = function (args, util) {
|
||||||
self.postMessage({method: 'stopallsounds'});
|
util.target.stopAllSounds();
|
||||||
};
|
};
|
||||||
|
|
||||||
Scratch3SoundBlocks.prototype.playNoteForBeats = function (args, util) {
|
Scratch3SoundBlocks.prototype.playNoteForBeats = function (args, util) {
|
||||||
self.postMessage({method: 'playnoteforbeats', note:args.NOTE, beats:args.BEATS});
|
util.target.playNoteForBeats(args.NOTE, args.BEATS);
|
||||||
return new Promise(function(resolve) {
|
return new Promise(function(resolve) {
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
resolve();
|
resolve();
|
||||||
|
@ -54,35 +43,6 @@ Scratch3SoundBlocks.prototype.playNoteForBeats = function (args, util) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
Scratch3SoundBlocks.prototype.playDrumForBeats = function (args, util) {
|
Scratch3SoundBlocks.prototype.playDrumForBeats = function (args, util) {
|
||||||
self.postMessage({method: 'playdrumforbeats', drum:args.DRUMTYPE, beats:args.BEATS});
|
self.postMessage({method: 'playdrumforbeats', drum:args.DRUMTYPE, beats:args.BEATS});
|
||||||
return new Promise(function(resolve) {
|
return new Promise(function(resolve) {
|
||||||
|
@ -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) {
|
Scratch3SoundBlocks.prototype.setEffect = function (args, util) {
|
||||||
self.postMessage({method: 'seteffect', effect:args.EFFECT, value:args.VALUE});
|
self.postMessage({method: 'seteffect', effect:args.EFFECT, value:args.VALUE});
|
||||||
};
|
};
|
||||||
|
@ -116,14 +68,6 @@ Scratch3SoundBlocks.prototype.soundsMenu = function (args, util) {
|
||||||
return args.SOUND_MENU;
|
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) {
|
Scratch3SoundBlocks.prototype.beatsMenu = function (args, util) {
|
||||||
return args.BEATS;
|
return args.BEATS;
|
||||||
};
|
};
|
||||||
|
|
|
@ -244,4 +244,12 @@ Clone.prototype.playSound = function (soundNum) {
|
||||||
this.audioWorker.playSound(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;
|
module.exports = Clone;
|
||||||
|
|
Loading…
Reference in a new issue