scratch-audioengine
Advanced tools
Comparing version 0.1.0-prerelease.1476909726 to 0.1.0-prerelease.1477596634
{ | ||
"name": "scratch-audioengine", | ||
"version": "0.1.0-prerelease.1476909726", | ||
"version": "0.1.0-prerelease.1477596634", | ||
"description": "audio engine for scratch 3.0", | ||
@@ -30,2 +30,3 @@ "main": "dist.js", | ||
"json": "9.0.4", | ||
"minilog": "^3.0.1", | ||
"soundfont-player": "0.10.5", | ||
@@ -35,3 +36,6 @@ "tone": "0.8.0", | ||
"webpack": "1.13.2" | ||
}, | ||
"dependencies": { | ||
"vocoder": "^0.1.1" | ||
} | ||
} |
133
src/index.js
@@ -0,1 +1,2 @@ | ||
var log = require('./log'); | ||
var Tone = require('tone'); | ||
@@ -16,21 +17,17 @@ var Soundfont = require('soundfont-player'); | ||
this.reverb = new Tone.Freeverb(); | ||
this.pitchShiftRatio; | ||
this.distortion = new Tone.Distortion(); | ||
this.pitchEffectValue; | ||
// reset effects to their default parameters | ||
this.clearEffects(); | ||
// the effects are chained to an effects node for this clone, then to the master output | ||
// so audio is sent from each sampler or instrument, through the effects in order, then out | ||
// note that the pitch effect works differently - it sets the playback rate for each sampler | ||
// so audio is sent from each player or instrument, through the effects in order, then out | ||
// note that the pitch effect works differently - it sets the playback rate for each player | ||
this.effectsNode = new Tone.Gain(); | ||
this.effectsNode.chain(this.delay, this.panner, this.reverb, Tone.Master); | ||
this.effectsNode.chain(this.distortion, this.delay, this.panner, this.reverb, Tone.Master); | ||
// drum sounds | ||
// reset effects to their default parameters | ||
this.clearEffects(); | ||
// var drumFileNames = ['high_conga', 'small_cowbell', | ||
// 'snare_drum', 'splash cymbal']; | ||
// this.drumSamplers = this._loadSoundFiles(drumFileNames); | ||
// load sounds | ||
// sound urls - map each url to its tone.sampler | ||
this.soundSamplers = []; | ||
this.soundPlayers = []; | ||
this.loadSounds(sounds); | ||
@@ -50,2 +47,7 @@ | ||
// tempo in bpm (beats per minute) | ||
// default is 60bpm | ||
this.currentTempo = 60; | ||
// theremin setup | ||
@@ -63,11 +65,9 @@ | ||
for (var i=0; i<sounds.length; i++) { | ||
var url = sounds[i].fileUrl; | ||
// skip adpcm form sounds since we can't load them yet | ||
if (sounds[i].format == 'adpcm') { | ||
log.warn('cannot load sound in adpcm format'); | ||
continue; | ||
} | ||
var sampler = new Tone.Sampler(url); | ||
sampler.connect(this.effectsNode); | ||
// this.soundSamplers.push(sampler); | ||
this.soundSamplers[i] = sampler; | ||
this.soundPlayers[i] = new Tone.Player(sounds[i].fileUrl); | ||
this.soundPlayers[i].connect(this.effectsNode); | ||
} | ||
@@ -77,9 +77,28 @@ }; | ||
AudioEngine.prototype.playSound = function (index) { | ||
this.soundSamplers[index].triggerAttack(); | ||
this.soundSamplers[index].player.playbackRate = 1 + this.pitchShiftRatio; | ||
var player = this.soundPlayers[index]; | ||
if (player && player.buffer.loaded) { | ||
player.start(); | ||
return new Promise(function (resolve) { | ||
setTimeout(function () { | ||
resolve(); | ||
}, (player.buffer.duration * 1000) / player.playbackRate); | ||
}); | ||
} else { | ||
// if the sound has not yet loaded, wait and try again | ||
log.warn('sound ' + index + ' not loaded yet'); | ||
if (player) { | ||
setTimeout(function () { | ||
this.playSound(index); | ||
}.bind(this), 500); | ||
} | ||
} | ||
}; | ||
AudioEngine.prototype.getSoundDuration = function (index) { | ||
return this.soundSamplers[index].player.buffer.duration; | ||
var player = this.soundPlayers[index]; | ||
if (player && player.buffer.loaded) { | ||
return player.buffer.duration; | ||
} else { | ||
return 0; | ||
} | ||
}; | ||
@@ -100,3 +119,3 @@ | ||
// that releases the theremin - so we can slide continuously between | ||
// successive notes without releasing and attacking | ||
// successive notes without releasing and re-attacking | ||
@@ -132,8 +151,12 @@ var freq = this._midiToFreq(note); | ||
// } | ||
// stop sounds triggered with playSound (indexed by their urls) | ||
for (var key in this.soundSamplers) { | ||
this.soundSamplers[key].triggerRelease(); | ||
// stop sounds triggered with playSound | ||
if (this.soundPlayers && this.soundPlayers.length > 0) { | ||
for (var i=0; i<this.soundPlayers.length; i++) { | ||
this.soundPlayers[i].stop(); | ||
} | ||
} | ||
// stop soundfont notes | ||
this.instrument.stop(); | ||
if (this.instrument) { | ||
this.instrument.stop(); | ||
} | ||
}; | ||
@@ -153,4 +176,10 @@ | ||
case 'PITCH': | ||
this._setPitchShift(value / 20); | ||
this._setPitchShift(value); | ||
break; | ||
case 'DISTORTION' : | ||
this.distortion.wet.value = value / 100; | ||
break; | ||
case 'ROBOTIC' : | ||
// vocoder effect? | ||
break; | ||
} | ||
@@ -174,4 +203,12 @@ }; | ||
case 'PITCH': | ||
this._setPitchShift(this.pitchShiftRatio + (value / 20)); | ||
this._setPitchShift(this.pitchEffectValue + Number(value)); | ||
break; | ||
case 'DISTORTION' : | ||
this.distortion.wet.value += value / 100; | ||
this.distortion.wet.value = this._clamp(this.distortion.wet.value, 0, 1); | ||
break; | ||
case 'ROBOTIC' : | ||
// vocoder effect? | ||
break; | ||
} | ||
@@ -181,6 +218,13 @@ }; | ||
AudioEngine.prototype._setPitchShift = function (value) { | ||
this.pitchShiftRatio = value; | ||
for (var i in this.soundSamplers) { | ||
this.soundSamplers[i].player.playbackRate = 1 + this.pitchShiftRatio; | ||
this.pitchEffectValue = value; | ||
if (!this.soundPlayers) { | ||
return; | ||
} | ||
var ratio = this.tone.intervalToFrequencyRatio(this.pitchEffectValue / 10); | ||
for (var i=0; i<this.soundPlayers.length; i++) { | ||
var s = this.soundPlayers[i]; | ||
if (s) { | ||
s.playbackRate = ratio; | ||
} | ||
} | ||
}; | ||
@@ -202,4 +246,29 @@ | ||
this.reverb.wet.value = 0; | ||
this.distortion.wet.value = 0; | ||
this.effectsNode.gain.value = 1; | ||
}; | ||
AudioEngine.prototype.setVolume = function (value) { | ||
var vol = this._clamp(value, 0, 100); | ||
vol /= 100; | ||
this.effectsNode.gain.value = vol; | ||
}; | ||
AudioEngine.prototype.changeVolume = function (value) { | ||
value /= 100; | ||
var newVol = this.effectsNode.gain.value + value; | ||
this.effectsNode.gain.value = this._clamp(newVol, 0, 1); | ||
}; | ||
AudioEngine.prototype.setTempo = function (value) { | ||
var newTempo = this._clamp(value, 10, 1000); | ||
this.currentTempo = newTempo; | ||
}; | ||
AudioEngine.prototype.changeTempo = function (value) { | ||
var newTempo = this._clamp(this.currentTempo + value, 10, 1000); | ||
this.currentTempo = newTempo; | ||
}; | ||
AudioEngine.prototype._clamp = function (input, min, max) { | ||
@@ -206,0 +275,0 @@ return Math.min(Math.max(input, min), max); |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
825857
15
24012
1
11
+ Addedvocoder@^0.1.1
+ Addedvocoder@0.1.1(transitive)