|
|
|
@@ -0,0 +1,58 @@ |
|
|
|
import { Filter } from "./Filter"; |
|
|
|
import { context, exposedNumber } from "../audio"; |
|
|
|
|
|
|
|
export class DelayFilter extends Filter { |
|
|
|
type = "DelayFilter" |
|
|
|
private splitter: ChannelSplitterNode; |
|
|
|
private delayL: DelayNode; |
|
|
|
private delayR: DelayNode; |
|
|
|
private merger: ChannelMergerNode; |
|
|
|
|
|
|
|
@exposedNumber({ |
|
|
|
name: "Left Delay", |
|
|
|
min: 1, |
|
|
|
max: 1000, |
|
|
|
format: (value: number) => |
|
|
|
Math.pow(2, value).toLocaleString(undefined, { |
|
|
|
maximumFractionDigits: 1, |
|
|
|
}) + "ms", |
|
|
|
map: (value: number) => Math.log(value) / Math.log(2), |
|
|
|
unmap: (value: number) => Math.pow(2, value), |
|
|
|
}) |
|
|
|
public leftDelay = 1; |
|
|
|
|
|
|
|
@exposedNumber({ |
|
|
|
name: "Right Delay", |
|
|
|
min: 1, |
|
|
|
max: 1000, |
|
|
|
format: (value: number) => |
|
|
|
Math.pow(2, value).toLocaleString(undefined, { |
|
|
|
maximumFractionDigits: 1, |
|
|
|
}) + "ms", |
|
|
|
map: (value: number) => Math.log(value) / Math.log(2), |
|
|
|
unmap: (value: number) => Math.pow(2, value), |
|
|
|
}) |
|
|
|
public rightDelay = 1; |
|
|
|
|
|
|
|
constructor() { |
|
|
|
super("Delay Filter"); |
|
|
|
this.splitter = context.createChannelSplitter(); |
|
|
|
this.delayL = context.createDelay(); |
|
|
|
this.delayR = context.createDelay(); |
|
|
|
this.merger = context.createChannelMerger(); |
|
|
|
|
|
|
|
this.filterInput.connect(this.splitter); |
|
|
|
this.splitter.connect(this.delayL, 0); |
|
|
|
this.splitter.connect(this.delayR, 1); |
|
|
|
this.delayL.connect(this.merger, 0, 0); |
|
|
|
this.delayR.connect(this.merger, 0, 1); |
|
|
|
|
|
|
|
this.merger.connect(this.output); |
|
|
|
} |
|
|
|
|
|
|
|
public tick(dt: number): void { |
|
|
|
super.tick(dt); |
|
|
|
this.delayL.delayTime.setTargetAtTime(this.leftDelay / 1000, 0, 0.3); |
|
|
|
this.delayR.delayTime.setTargetAtTime(this.rightDelay / 1000, 0, 0.3); |
|
|
|
} |
|
|
|
} |