Files
bruitiste/src/domain/audio/effects/ReverbEffect.ts
2025-09-30 14:20:50 +02:00

70 lines
2.0 KiB
TypeScript

import type { Effect } from './Effect.interface'
export class ReverbEffect implements Effect {
readonly id = 'reverb'
private audioContext: AudioContext
private inputNode: GainNode
private outputNode: GainNode
private convolverNode: ConvolverNode
private wetNode: GainNode
private dryNode: GainNode
constructor(audioContext: AudioContext) {
this.audioContext = audioContext
this.inputNode = audioContext.createGain()
this.outputNode = audioContext.createGain()
this.convolverNode = audioContext.createConvolver()
this.wetNode = audioContext.createGain()
this.dryNode = audioContext.createGain()
this.wetNode.gain.value = 0
this.dryNode.gain.value = 1
this.inputNode.connect(this.dryNode)
this.inputNode.connect(this.convolverNode)
this.convolverNode.connect(this.wetNode)
this.dryNode.connect(this.outputNode)
this.wetNode.connect(this.outputNode)
this.generateImpulseResponse()
}
private generateImpulseResponse(): void {
const length = this.audioContext.sampleRate * 2
const impulse = this.audioContext.createBuffer(2, length, this.audioContext.sampleRate)
const left = impulse.getChannelData(0)
const right = impulse.getChannelData(1)
for (let i = 0; i < length; i++) {
left[i] = (Math.random() * 2 - 1) * Math.pow(1 - i / length, 2)
right[i] = (Math.random() * 2 - 1) * Math.pow(1 - i / length, 2)
}
this.convolverNode.buffer = impulse
}
getInputNode(): AudioNode {
return this.inputNode
}
getOutputNode(): AudioNode {
return this.outputNode
}
updateParams(values: Record<string, number>): void {
if (values.reverbWetDry !== undefined) {
const wet = values.reverbWetDry / 100
this.wetNode.gain.value = wet
this.dryNode.gain.value = 1 - wet
}
}
dispose(): void {
this.inputNode.disconnect()
this.outputNode.disconnect()
this.convolverNode.disconnect()
this.wetNode.disconnect()
this.dryNode.disconnect()
}
}