Adding new FM synthesis mode

This commit is contained in:
2025-10-06 13:08:59 +02:00
parent 0110a9760b
commit 324cf9d2ed
13 changed files with 1233 additions and 69 deletions

View File

@ -0,0 +1,90 @@
import type { Effect } from './Effect.interface'
import type { FMAlgorithm } from '../../../config/fmAlgorithms'
export class FMSourceEffect implements Effect {
readonly id = 'fm-source'
private inputNode: GainNode
private outputNode: GainNode
private processorNode: AudioWorkletNode | null = null
constructor(audioContext: AudioContext) {
this.inputNode = audioContext.createGain()
this.outputNode = audioContext.createGain()
}
async initialize(audioContext: AudioContext): Promise<void> {
this.processorNode = new AudioWorkletNode(audioContext, 'fm-processor')
this.processorNode.connect(this.outputNode)
}
getInputNode(): AudioNode {
return this.inputNode
}
getOutputNode(): AudioNode {
return this.outputNode
}
setBypass(): void {
// Source node doesn't support bypass
}
updateParams(): void {
// Parameters handled via specific methods
}
setAlgorithm(algorithm: FMAlgorithm, lfoRates?: number[]): void {
if (!this.processorNode) return
this.processorNode.port.postMessage({
type: 'algorithm',
value: {
id: algorithm.id,
ratios: algorithm.frequencyRatios,
lfoRates: lfoRates || [0.37, 0.53, 0.71, 0.43]
}
})
}
setOperatorLevels(a: number, b: number, c: number, d: number): void {
if (!this.processorNode) return
this.processorNode.port.postMessage({
type: 'operatorLevels',
value: { a, b, c, d }
})
}
setBaseFrequency(freq: number): void {
if (!this.processorNode) return
this.processorNode.port.postMessage({ type: 'baseFreq', value: freq })
}
setFeedback(amount: number): void {
if (!this.processorNode) return
this.processorNode.port.postMessage({ type: 'feedback', value: amount })
}
setLoopLength(sampleRate: number, duration: number): void {
if (!this.processorNode) return
const loopLength = sampleRate * duration
this.processorNode.port.postMessage({ type: 'loopLength', value: loopLength })
}
setPlaybackRate(rate: number): void {
if (!this.processorNode) return
this.processorNode.port.postMessage({ type: 'playbackRate', value: rate })
}
reset(): void {
if (!this.processorNode) return
this.processorNode.port.postMessage({ type: 'reset' })
}
dispose(): void {
if (this.processorNode) {
this.processorNode.disconnect()
}
this.inputNode.disconnect()
this.outputNode.disconnect()
}
}