92 lines
2.5 KiB
TypeScript
92 lines
2.5 KiB
TypeScript
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[], pitchLFO?: { waveform: number; depth: number; baseRate: 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],
|
|
pitchLFO: pitchLFO || { waveform: 0, depth: 0.1, baseRate: 2.0 }
|
|
}
|
|
})
|
|
}
|
|
|
|
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()
|
|
}
|
|
}
|