Skip to content

Instantly share code, notes, and snippets.

@beefchimi
Last active October 22, 2017 23:46
Show Gist options
  • Save beefchimi/bc5d572bf2f2df3bba26fd7ed851eeb0 to your computer and use it in GitHub Desktop.
Save beefchimi/bc5d572bf2f2df3bba26fd7ed851eeb0 to your computer and use it in GitHub Desktop.
Synth class
import synthPresets from './helpers/synth-presets';
import methodPatch from './helpers/method-patch';
import MobileAudioFix from './helpers/mobile-audio-fix';
const initialGain = 0.001;
export default class Synth {
static synthKeys = Object.keys(synthPresets);
constructor() {
this.context = new AudioContext();
this.mobileAudio = new MobileAudioFix(this.context);
this.mobileAudio.init();
}
play(sound) {
if (!Synth.synthKeys.includes(sound)) {
return Error(`The requested sound is not available: ${sound}`);
}
const config = synthPresets[sound];
const duration = this.context.currentTime + config.duration;
this._buildTone(config);
// `buildTone` created our `oscillator`,
// so we can now patch both `start()` and `stop()` for Safari
this._patchOscillatorMethods();
this.oscillator.start();
this._stop(duration);
}
_buildTone(config) {
this.oscillator = this.context.createOscillator();
this.gainNode = this.context.createGain();
this.oscillator.connect(this.gainNode);
this.gainNode.connect(this.context.destination);
this.oscillator.type = config.wave;
this.oscillator.frequency.setValueAtTime(
config.freq.start,
this.context.currentTime
);
// The oscillator will reach its `end` frequency
// at the half way point of its duration
this.oscillator.frequency.exponentialRampToValueAtTime(
config.freq.end,
this.context.currentTime + (config.duration / 2)
);
// We need to do a very quick fade-in
// so we can avoid the ugly "pop" that happens on .start()
this.gainNode.gain.setValueAtTime(
initialGain,
this.context.currentTime
);
this.gainNode.gain.exponentialRampToValueAtTime(
config.volume,
this.context.currentTime + (config.duration / 6)
);
}
_stop(duration) {
this.gainNode.gain.exponentialRampToValueAtTime(initialGain, duration);
this.oscillator.stop(duration);
}
_patchOscillatorMethods() {
this.oscillator.start = methodPatch.start(this.oscillator);
this.oscillator.stop = methodPatch.stop(this.oscillator);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment