Enhance FM synthesis + cleaning code architecture
This commit is contained in:
@ -30,6 +30,11 @@ class FMProcessor extends AudioWorkletProcessor {
|
||||
this.lfoRate4 = 0.43
|
||||
this.lfoDepth = 0.3
|
||||
|
||||
this.pitchLFOPhase = 0
|
||||
this.pitchLFOWaveform = 0
|
||||
this.pitchLFODepth = 0.1
|
||||
this.pitchLFOBaseRate = 2.0
|
||||
|
||||
this.port.onmessage = (event) => {
|
||||
const { type, value } = event.data
|
||||
switch (type) {
|
||||
@ -42,6 +47,11 @@ class FMProcessor extends AudioWorkletProcessor {
|
||||
this.lfoRate3 = value.lfoRates[2]
|
||||
this.lfoRate4 = value.lfoRates[3]
|
||||
}
|
||||
if (value.pitchLFO) {
|
||||
this.pitchLFOWaveform = value.pitchLFO.waveform
|
||||
this.pitchLFODepth = value.pitchLFO.depth
|
||||
this.pitchLFOBaseRate = value.pitchLFO.baseRate
|
||||
}
|
||||
break
|
||||
case 'operatorLevels':
|
||||
this.opLevel1 = value.a
|
||||
@ -73,14 +83,41 @@ class FMProcessor extends AudioWorkletProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
generatePitchLFO(phase, waveform) {
|
||||
const TWO_PI = Math.PI * 2
|
||||
const normalizedPhase = phase / TWO_PI
|
||||
|
||||
switch (waveform) {
|
||||
case 0: // sine
|
||||
return Math.sin(phase)
|
||||
case 1: // triangle
|
||||
return 2 * Math.abs(2 * (normalizedPhase % 1 - 0.5)) - 1
|
||||
case 2: // square
|
||||
return normalizedPhase % 1 < 0.5 ? 1 : -1
|
||||
case 3: // sawtooth
|
||||
return 2 * (normalizedPhase % 1) - 1
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
synthesize(algorithm) {
|
||||
const TWO_PI = Math.PI * 2
|
||||
const sampleRate = 44100
|
||||
|
||||
const freq1 = (this.baseFreq * this.frequencyRatios[0] * TWO_PI) / sampleRate
|
||||
const freq2 = (this.baseFreq * this.frequencyRatios[1] * TWO_PI) / sampleRate
|
||||
const freq3 = (this.baseFreq * this.frequencyRatios[2] * TWO_PI) / sampleRate
|
||||
const freq4 = (this.baseFreq * this.frequencyRatios[3] * TWO_PI) / sampleRate
|
||||
const avgDiff = (Math.abs(this.opLevel1 - this.opLevel3) + Math.abs(this.opLevel2 - this.opLevel4)) / (2 * 255)
|
||||
const pitchLFORate = this.pitchLFOBaseRate * (0.3 + avgDiff * 1.4)
|
||||
const pitchLFOValue = this.generatePitchLFO(this.pitchLFOPhase, this.pitchLFOWaveform)
|
||||
const pitchMod = 1 + pitchLFOValue * this.pitchLFODepth
|
||||
const modulatedBaseFreq = this.baseFreq * pitchMod
|
||||
|
||||
this.pitchLFOPhase += (pitchLFORate * TWO_PI) / sampleRate
|
||||
if (this.pitchLFOPhase > TWO_PI) this.pitchLFOPhase -= TWO_PI
|
||||
|
||||
const freq1 = (modulatedBaseFreq * this.frequencyRatios[0] * TWO_PI) / sampleRate
|
||||
const freq2 = (modulatedBaseFreq * this.frequencyRatios[1] * TWO_PI) / sampleRate
|
||||
const freq3 = (modulatedBaseFreq * this.frequencyRatios[2] * TWO_PI) / sampleRate
|
||||
const freq4 = (modulatedBaseFreq * this.frequencyRatios[3] * TWO_PI) / sampleRate
|
||||
|
||||
const lfo1 = Math.sin(this.lfoPhase1)
|
||||
const lfo2 = Math.sin(this.lfoPhase2)
|
||||
|
||||
Reference in New Issue
Block a user