work.suroh.tk/assets/js/synth.js

65 lines
1.6 KiB
JavaScript

export class Synth {
// SYNTH VOICE CONSTRUCTOR
constructor(audio, type, env = {
a: 0.2,
r: 0.5,
}) {
this.audio = audio
this.t = this.audio.currentTime
this.env = {
a: env.a,
r: env.r,
}
// PRIMARY GAIN
this.gain = this.audio.createGain()
this.gain.gain.value = 0
// PRIMARY VOICE
this.primVoice = this.audio.createOscillator()
this.primVoice.type = typeof type === 'string' ? type : 'sine'
this.primVoice.connect(this.gain)
this.primVoice.start()
// MOD GAIN
this.modGain = this.audio.createGain()
this.modGain.gain.value = 0
this.modGain.connect(this.gain)
// MOD VOICE
this.modVoice = this.audio.createOscillator()
this.modVoice.type = 'triangle'
this.modVoice.connect(this.modGain)
this.modVoice.start()
}
// OSC -> ADSR -> GAIN
noteOn(freq) {
// note frequency
this.freq = freq ? freq : (Math.random() * 350) + 150
this.primVoice.frequency.setValueAtTime(this.freq, this.t)
this.modVoice.frequency.setValueAtTime(this.freq - 20, this.t)
// clear preScheduled events
this.gain.gain.cancelScheduledValues(this.audio.currentTime)
// attack
this.gain.gain.setTargetAtTime(0.45, this.t + this.env.a, 0.2)
}
noteOff() {
// release
this.gain.gain.setTargetAtTime(0.0, this.t + this.env.r, 1)
}
mod() {
this.modGain.gain.cancelScheduledValues(this.audio.currentTime)
// attack
this.modGain.gain.setTargetAtTime(0.8, this.audio.currentTime, 0.5)
// release
this.modGain.gain.setTargetAtTime(0.8, this.audio.currentTime + 0.4, 0.5)
}
}