mirror of
https://github.com/scratchfoundation/scratch-audio.git
synced 2025-01-18 05:30:06 -05:00
Merge pull request #46 from LLK/feature/remove-most-effects
Remove all audio effects except pitch and pan
This commit is contained in:
commit
09b017ccf4
6 changed files with 2 additions and 311 deletions
|
@ -1,56 +0,0 @@
|
||||||
const Tone = require('tone');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An echo effect (aka 'delay effect' in audio terms)
|
|
||||||
* Effect value of 0 mutes the effect
|
|
||||||
* Values up to 100 set the echo feedback amount,
|
|
||||||
* increasing the time it takes the echo to fade away
|
|
||||||
* Clamped 0-100
|
|
||||||
*/
|
|
||||||
class EchoEffect extends Tone.Effect {
|
|
||||||
constructor () {
|
|
||||||
super();
|
|
||||||
this.value = 0;
|
|
||||||
this.delay = new Tone.FeedbackDelay(0.25, 0.5);
|
|
||||||
this.effectSend.chain(this.delay, this.effectReturn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the effect value
|
|
||||||
* @param {number} val - the new value to set the effect to
|
|
||||||
*/
|
|
||||||
set (val) {
|
|
||||||
this.value = this.clamp(val, 0, 100);
|
|
||||||
|
|
||||||
// mute the effect if value is 0
|
|
||||||
if (this.value === 0) {
|
|
||||||
this.wet.value = 0;
|
|
||||||
} else {
|
|
||||||
this.wet.value = 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
const feedback = (this.value / 100) * 0.75;
|
|
||||||
this.delay.feedback.rampTo(feedback, 1 / 60);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change the effect value
|
|
||||||
* @param {number} val - the value to change the effect by
|
|
||||||
*/
|
|
||||||
changeBy (val) {
|
|
||||||
this.set(this.value + val);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clamp the input to a range
|
|
||||||
* @param {number} input - the input to clamp
|
|
||||||
* @param {number} min - the min value to clamp to
|
|
||||||
* @param {number} max - the max value to clamp to
|
|
||||||
* @return {number} the clamped value
|
|
||||||
*/
|
|
||||||
clamp (input, min, max) {
|
|
||||||
return Math.min(Math.max(input, min), max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = EchoEffect;
|
|
|
@ -1,45 +0,0 @@
|
||||||
const Tone = require('tone');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A fuzz effect (aka 'distortion effect' in audio terms)
|
|
||||||
* Effect value controls the wet/dry amount:
|
|
||||||
* 0 passes through none of the effect, 100 passes through all effect
|
|
||||||
* Clamped 0-100
|
|
||||||
*/
|
|
||||||
class FuzzEffect extends Tone.Effect {
|
|
||||||
constructor () {
|
|
||||||
super();
|
|
||||||
this.value = 0;
|
|
||||||
this.distortion = new Tone.Distortion(1);
|
|
||||||
this.effectSend.chain(this.distortion, this.effectReturn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the effect value
|
|
||||||
* @param {number} val - the new value to set the effect to
|
|
||||||
*/
|
|
||||||
set (val) {
|
|
||||||
this.value = this.clamp(val, 0, 100);
|
|
||||||
this.distortion.wet.value = this.value / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change the effect value
|
|
||||||
* @param {number} val - the value to change the effect by
|
|
||||||
*/
|
|
||||||
changeBy (val) {
|
|
||||||
this.set(this.value + val);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {number} input - the input to clamp
|
|
||||||
* @param {number} min - the min value to clamp to
|
|
||||||
* @param {number} max - the max value to clamp to
|
|
||||||
* @return {number} the clamped value
|
|
||||||
*/
|
|
||||||
clamp (input, min, max) {
|
|
||||||
return Math.min(Math.max(input, min), max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = FuzzEffect;
|
|
|
@ -1,46 +0,0 @@
|
||||||
const Tone = require('tone');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A reverb effect, simulating reverberation in a room
|
|
||||||
* Effect value controls the wet/dry amount:
|
|
||||||
* 0 passes through none of the effect, 100 passes through all effect
|
|
||||||
* Clamped 0 to 100
|
|
||||||
*/
|
|
||||||
class ReverbEffect extends Tone.Effect {
|
|
||||||
constructor () {
|
|
||||||
super();
|
|
||||||
this.value = 0;
|
|
||||||
this.reverb = new Tone.Freeverb();
|
|
||||||
this.effectSend.chain(this.reverb, this.effectReturn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the effect value
|
|
||||||
* @param {number} val - the new value to set the effect to
|
|
||||||
*/
|
|
||||||
set (val) {
|
|
||||||
this.value = this.clamp(val, 0, 100);
|
|
||||||
this.reverb.wet.value = this.value / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change the effect value
|
|
||||||
* @param {number} val - the value to change the effect by
|
|
||||||
*/
|
|
||||||
changeBy (val) {
|
|
||||||
this.set(this.value + val);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clamp the input to a range
|
|
||||||
* @param {number} input - the input to clamp
|
|
||||||
* @param {number} min - the min value to clamp to
|
|
||||||
* @param {number} max - the max value to clamp to
|
|
||||||
* @return {number} the clamped value
|
|
||||||
*/
|
|
||||||
clamp (input, min, max) {
|
|
||||||
return Math.min(Math.max(input, min), max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = ReverbEffect;
|
|
|
@ -1,66 +0,0 @@
|
||||||
const Tone = require('tone');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A "robotic" effect that adds a low-pitched buzzing to the sound, reminiscent of the
|
|
||||||
* voice of the daleks from Dr. Who.
|
|
||||||
* In audio terms it is a feedback comb filter with a short delay time.
|
|
||||||
* The effect value controls the length of this delay time, changing the pitch of the buzz
|
|
||||||
* A value of 0 mutes the effect.
|
|
||||||
* Other values change the pitch of the effect, in units of 10 steps per semitone.
|
|
||||||
* The effect value is not clamped (but probably should be).
|
|
||||||
* Exterminate.
|
|
||||||
*/
|
|
||||||
class RoboticEffect extends Tone.Effect {
|
|
||||||
constructor () {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.value = 0;
|
|
||||||
|
|
||||||
const time = this._delayTimeForValue(100);
|
|
||||||
this.feedbackCombFilter = new Tone.FeedbackCombFilter(time, 0.9);
|
|
||||||
|
|
||||||
this.effectSend.chain(this.feedbackCombFilter, this.effectReturn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the effect value
|
|
||||||
* @param {number} val - the new value to set the effect to
|
|
||||||
*/
|
|
||||||
set (val) {
|
|
||||||
this.value = val;
|
|
||||||
|
|
||||||
// mute the effect if value is 0
|
|
||||||
if (this.value === 0) {
|
|
||||||
this.wet.value = 0;
|
|
||||||
} else {
|
|
||||||
this.wet.value = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set delay time using the value
|
|
||||||
const time = this._delayTimeForValue(this.value);
|
|
||||||
this.feedbackCombFilter.delayTime.rampTo(time, 1 / 60);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change the effect value
|
|
||||||
* @param {number} val - the value to change the effect by
|
|
||||||
*/
|
|
||||||
changeBy (val) {
|
|
||||||
this.set(this.value + val);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compute the delay time for an effect value.
|
|
||||||
* Convert the effect value to a musical note (in units of 10 per semitone),
|
|
||||||
* and return the period (single cycle duration) of the frequency of that note.
|
|
||||||
* @param {number} val - the effect value
|
|
||||||
* @returns {number} a delay time in seconds
|
|
||||||
*/
|
|
||||||
_delayTimeForValue (val) {
|
|
||||||
const midiNote = ((val - 100) / 10) + 36;
|
|
||||||
const freq = Tone.Frequency(midiNote, 'midi').eval();
|
|
||||||
return 1 / freq;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = RoboticEffect;
|
|
|
@ -1,60 +0,0 @@
|
||||||
const Tone = require('tone');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wobble effect. In audio terms, it sounds like tremolo.
|
|
||||||
* It is implemented using a low frequency oscillator (LFO) controlling
|
|
||||||
* a gain node, which causes the loudness of the signal passing through
|
|
||||||
* to increase and decrease rapidly.
|
|
||||||
* Effect value controls the wet/dry amount:
|
|
||||||
* 0 passes through none of the effect, 100 passes through all effect
|
|
||||||
* Effect value also controls the frequency of the LFO.
|
|
||||||
* Clamped 0 to 100
|
|
||||||
*/
|
|
||||||
class WobbleEffect extends Tone.Effect {
|
|
||||||
constructor () {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.value = 0;
|
|
||||||
|
|
||||||
this.wobbleLFO = new Tone.LFO(10, 0, 1).start();
|
|
||||||
this.wobbleGain = new Tone.Gain();
|
|
||||||
this.wobbleLFO.connect(this.wobbleGain.gain);
|
|
||||||
|
|
||||||
this.effectSend.chain(this.wobbleGain, this.effectReturn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the effect value
|
|
||||||
* @param {number} val - the new value to set the effect to
|
|
||||||
*/
|
|
||||||
set (val) {
|
|
||||||
this.value = val;
|
|
||||||
|
|
||||||
this.value = this.clamp(this.value, 0, 100);
|
|
||||||
|
|
||||||
this.wet.value = this.value / 100;
|
|
||||||
|
|
||||||
this.wobbleLFO.frequency.rampTo(this.value / 10, 1 / 60);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change the effect value
|
|
||||||
* @param {number} val - the value to change the effect by
|
|
||||||
*/
|
|
||||||
changeBy (val) {
|
|
||||||
this.set(this.value + val);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clamp the input to a range
|
|
||||||
* @param {number} input - the input to clamp
|
|
||||||
* @param {number} min - the min value to clamp to
|
|
||||||
* @param {number} max - the max value to clamp to
|
|
||||||
* @return {number} the clamped value
|
|
||||||
*/
|
|
||||||
clamp (input, min, max) {
|
|
||||||
return Math.min(Math.max(input, min), max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = WobbleEffect;
|
|
40
src/index.js
40
src/index.js
|
@ -4,11 +4,6 @@ const Tone = require('tone');
|
||||||
const PitchEffect = require('./effects/PitchEffect');
|
const PitchEffect = require('./effects/PitchEffect');
|
||||||
const PanEffect = require('./effects/PanEffect');
|
const PanEffect = require('./effects/PanEffect');
|
||||||
|
|
||||||
const RoboticEffect = require('./effects/RoboticEffect');
|
|
||||||
const FuzzEffect = require('./effects/FuzzEffect');
|
|
||||||
const EchoEffect = require('./effects/EchoEffect');
|
|
||||||
const ReverbEffect = require('./effects/ReverbEffect');
|
|
||||||
|
|
||||||
const SoundPlayer = require('./SoundPlayer');
|
const SoundPlayer = require('./SoundPlayer');
|
||||||
const ADPCMSoundDecoder = require('./ADPCMSoundDecoder');
|
const ADPCMSoundDecoder = require('./ADPCMSoundDecoder');
|
||||||
const InstrumentPlayer = require('./InstrumentPlayer');
|
const InstrumentPlayer = require('./InstrumentPlayer');
|
||||||
|
@ -126,18 +121,6 @@ class AudioPlayer {
|
||||||
case this.audioEngine.EFFECT_NAMES.pan:
|
case this.audioEngine.EFFECT_NAMES.pan:
|
||||||
this.panEffect.set(value);
|
this.panEffect.set(value);
|
||||||
break;
|
break;
|
||||||
case this.audioEngine.EFFECT_NAMES.echo:
|
|
||||||
this.audioEngine.echoEffect.set(value);
|
|
||||||
break;
|
|
||||||
case this.audioEngine.EFFECT_NAMES.reverb:
|
|
||||||
this.audioEngine.reverbEffect.set(value);
|
|
||||||
break;
|
|
||||||
case this.audioEngine.EFFECT_NAMES.fuzz:
|
|
||||||
this.audioEngine.fuzzEffect.set(value);
|
|
||||||
break;
|
|
||||||
case this.audioEngine.EFFECT_NAMES.robot:
|
|
||||||
this.audioEngine.roboticEffect.set(value);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,11 +131,6 @@ class AudioPlayer {
|
||||||
this.panEffect.set(0);
|
this.panEffect.set(0);
|
||||||
this.pitchEffect.set(0, this.activeSoundPlayers);
|
this.pitchEffect.set(0, this.activeSoundPlayers);
|
||||||
this.effectsNode.gain.value = 1;
|
this.effectsNode.gain.value = 1;
|
||||||
|
|
||||||
this.audioEngine.echoEffect.set(0);
|
|
||||||
this.audioEngine.reverbEffect.set(0);
|
|
||||||
this.audioEngine.fuzzEffect.set(0);
|
|
||||||
this.audioEngine.roboticEffect.set(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -172,18 +150,8 @@ class AudioPlayer {
|
||||||
*/
|
*/
|
||||||
class AudioEngine {
|
class AudioEngine {
|
||||||
constructor () {
|
constructor () {
|
||||||
// create the global audio effects
|
|
||||||
this.roboticEffect = new RoboticEffect();
|
|
||||||
this.fuzzEffect = new FuzzEffect();
|
|
||||||
this.echoEffect = new EchoEffect();
|
|
||||||
this.reverbEffect = new ReverbEffect();
|
|
||||||
|
|
||||||
// chain the global effects to the output
|
|
||||||
this.input = new Tone.Gain();
|
this.input = new Tone.Gain();
|
||||||
this.input.chain(
|
this.input.connect(Tone.Master);
|
||||||
this.roboticEffect, this.fuzzEffect, this.echoEffect, this.reverbEffect,
|
|
||||||
Tone.Master
|
|
||||||
);
|
|
||||||
|
|
||||||
// global tempo in bpm (beats per minute)
|
// global tempo in bpm (beats per minute)
|
||||||
this.currentTempo = 60;
|
this.currentTempo = 60;
|
||||||
|
@ -211,11 +179,7 @@ class AudioEngine {
|
||||||
get EFFECT_NAMES () {
|
get EFFECT_NAMES () {
|
||||||
return {
|
return {
|
||||||
pitch: 'pitch',
|
pitch: 'pitch',
|
||||||
pan: 'pan',
|
pan: 'pan'
|
||||||
echo: 'echo',
|
|
||||||
reverb: 'reverb',
|
|
||||||
fuzz: 'fuzz',
|
|
||||||
robot: 'robot'
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue