| @@ -309,7 +309,6 @@ function createCache(): void { | |||||
| req.onerror = (e) => { | req.onerror = (e) => { | ||||
| alert("Couldn't open the database?"); | alert("Couldn't open the database?"); | ||||
| console.log(e) | |||||
| }; | }; | ||||
| } | } | ||||
| @@ -131,6 +131,13 @@ export const PresetFilters: Array<{ name: string; [x: string]: any }> = [ | |||||
| kind: "filter", | kind: "filter", | ||||
| type: "ReverbFilter", | type: "ReverbFilter", | ||||
| }, | }, | ||||
| { | |||||
| leftDelay: 0, | |||||
| rightDelay: 50, | |||||
| name: "Delay", | |||||
| kind: "filter", | |||||
| type: "DelayFilter", | |||||
| }, | |||||
| ]; | ]; | ||||
| export const DemoScene = [ | export const DemoScene = [ | ||||
| @@ -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); | |||||
| } | |||||
| } | |||||
| @@ -18,6 +18,7 @@ const constructors: { [key: string]: new (name: string) => Node } = { | |||||
| HighpassFilter: HighpassFilter, | HighpassFilter: HighpassFilter, | ||||
| StereoWidthFilter: StereoWidthFilter, | StereoWidthFilter: StereoWidthFilter, | ||||
| ReverbFilter: ReverbFilter, | ReverbFilter: ReverbFilter, | ||||
| DelayFilter: DelayFilter, | |||||
| }; | }; | ||||
| import { SoundSet, Source } from "./sources/Source"; | import { SoundSet, Source } from "./sources/Source"; | ||||
| @@ -27,6 +28,7 @@ import { HighpassFilter } from "./filters/HighpassFilter"; | |||||
| import { StereoWidthFilter } from "./filters/StereoWidthFilter"; | import { StereoWidthFilter } from "./filters/StereoWidthFilter"; | ||||
| import { PresetSoundSets } from "./data/sound-sets"; | import { PresetSoundSets } from "./data/sound-sets"; | ||||
| import { ReverbFilter } from "./filters/ReverbFilter"; | import { ReverbFilter } from "./filters/ReverbFilter"; | ||||
| import { DelayFilter } from "./filters/DelayFilter"; | |||||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||||
| export function serializeNode<T extends Node>(_node: T): any { | export function serializeNode<T extends Node>(_node: T): any { | ||||