From c7bd211b2fc4fcf0c3e06ac691fe638cbf1499b8 Mon Sep 17 00:00:00 2001 From: Fen Dweller Date: Mon, 20 Sep 2021 18:55:53 -0400 Subject: [PATCH] Add a reverb filter --- decs.d.ts | 1 + package-lock.json | 11 ++++ package.json | 1 + src/components/Menu.vue | 1 + src/components/nodes/FilterNode.vue | 1 + src/components/nodes/SourceNode.vue | 1 + src/data/presets.ts | 9 ++++ src/filters/ReverbFilter.ts | 81 +++++++++++++++++++++++++++++ src/serialize.ts | 2 + tsconfig.json | 3 +- 10 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 decs.d.ts create mode 100644 src/filters/ReverbFilter.ts diff --git a/decs.d.ts b/decs.d.ts new file mode 100644 index 0000000..7b1c176 --- /dev/null +++ b/decs.d.ts @@ -0,0 +1 @@ +declare module "soundbank-reverb" \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 5dcb2d1..033294e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "mobile-drag-drop": "^2.3.0-rc.2", "postcss": "^8.3.6", "reflect-metadata": "^0.1.13", + "soundbank-reverb": "^1.1.2", "vue": "^3.0.0", "vue-class-component": "^8.0.0-0", "vue-slider-component": "^3.2.14" @@ -15445,6 +15446,11 @@ "node": ">=0.10.0" } }, + "node_modules/soundbank-reverb": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/soundbank-reverb/-/soundbank-reverb-1.1.2.tgz", + "integrity": "sha1-uBspdgt5B7jIuuEMDZEz2Oxk+/c=" + }, "node_modules/source-list-map": { "version": "2.0.1", "resolved": "https://registry.npm.taobao.org/source-list-map/download/source-list-map-2.0.1.tgz", @@ -30432,6 +30438,11 @@ } } }, + "soundbank-reverb": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/soundbank-reverb/-/soundbank-reverb-1.1.2.tgz", + "integrity": "sha1-uBspdgt5B7jIuuEMDZEz2Oxk+/c=" + }, "source-list-map": { "version": "2.0.1", "resolved": "https://registry.npm.taobao.org/source-list-map/download/source-list-map-2.0.1.tgz", diff --git a/package.json b/package.json index a1f2643..0b39136 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "mobile-drag-drop": "^2.3.0-rc.2", "postcss": "^8.3.6", "reflect-metadata": "^0.1.13", + "soundbank-reverb": "^1.1.2", "vue": "^3.0.0", "vue-class-component": "^8.0.0-0", "vue-slider-component": "^3.2.14" diff --git a/src/components/Menu.vue b/src/components/Menu.vue index d0e5bbc..7f5f628 100644 --- a/src/components/Menu.vue +++ b/src/components/Menu.vue @@ -17,6 +17,7 @@ :node="filter" /> + diff --git a/src/components/nodes/FilterNode.vue b/src/components/nodes/FilterNode.vue index cfd1cee..b672a59 100644 --- a/src/components/nodes/FilterNode.vue +++ b/src/components/nodes/FilterNode.vue @@ -57,6 +57,7 @@ export default class FilterNode extends Vue { font-size: 24pt; margin: 4pt; color: #fcf; + margin-top: 30pt; } .node-properties { diff --git a/src/components/nodes/SourceNode.vue b/src/components/nodes/SourceNode.vue index 2a256e9..0b8fa7a 100644 --- a/src/components/nodes/SourceNode.vue +++ b/src/components/nodes/SourceNode.vue @@ -56,6 +56,7 @@ export default class SourceNode extends Vue { font-size: 24pt; margin: 4pt; color: #fcf; + margin-top: 30pt; } .node-properties { diff --git a/src/data/presets.ts b/src/data/presets.ts index 562479a..14248f5 100644 --- a/src/data/presets.ts +++ b/src/data/presets.ts @@ -102,6 +102,15 @@ export const PresetFilters: Array<{ name: string; [x: string]: any }> = [ kind: "filter", type: "StereoWidthFilter", }, + { + time: 1, + decay: 1, + dry: 1, + wet: 0.5, + name: "Reverb", + kind: "filter", + type: "ReverbFilter", + }, ]; export const DemoScene = [ diff --git a/src/filters/ReverbFilter.ts b/src/filters/ReverbFilter.ts new file mode 100644 index 0000000..d7073c1 --- /dev/null +++ b/src/filters/ReverbFilter.ts @@ -0,0 +1,81 @@ +import { Filter } from "./Filter"; +import { context, exposedNumber } from "../audio"; +import Reverb from "soundbank-reverb"; + +export class ReverbFilter extends Filter { + private reverb: any; + + @exposedNumber({ + name: "Reverb Time", + min: 0.1, + max: 5, + format: (value: number) => + Math.pow(2, value).toLocaleString(undefined, { + maximumFractionDigits: 1, + }) + "s", + map: (value: number) => Math.log(value) / Math.log(2), + unmap: (value: number) => Math.pow(2, value), + }) + public time = 1; + private oldTime = -1; + + @exposedNumber({ + name: "Decay Rate", + min: 0.1, + max: 5, + format: (value: number) => + Math.pow(2, value).toLocaleString(undefined, { + maximumFractionDigits: 1, + }), + map: (value: number) => Math.log(value) / Math.log(2), + unmap: (value: number) => Math.pow(2, value), + }) + public decay = 1; + private oldDecay = -1; + + @exposedNumber({ + name: "Dry Mix", + min: 0, + max: 1, + format: (value: number) => + (value * 100).toLocaleString(undefined, { + maximumFractionDigits: 0, + }) + "%", + }) + public dry = 1; + + @exposedNumber({ + name: "Wet Mix", + min: 0, + max: 1, + format: (value: number) => + (value * 100).toLocaleString(undefined, { + maximumFractionDigits: 0, + }) + "%", + }) + public wet = 0.5; + + constructor() { + super("Reverb Filter"); + this.reverb = Reverb(context); + + this.reverb.time = 1; + this.input.connect(this.reverb); + this.reverb.connect(this.output); + } + + public tick(dt: number): void { + super.tick(dt); + if (this.oldTime != this.time) { + this.reverb.time = this.time; + this.oldTime = this.time; + } + + if (this.oldDecay != this.decay) { + this.reverb.decay = this.decay; + this.oldDecay = this.decay; + } + this.reverb.dry.setTargetAtTime(this.dry, context.currentTime, 0.3); + this.reverb.wet.setTargetAtTime(this.wet, context.currentTime, 0.3); + } +} diff --git a/src/serialize.ts b/src/serialize.ts index fb52e7a..1986f25 100644 --- a/src/serialize.ts +++ b/src/serialize.ts @@ -17,6 +17,7 @@ const constructors: { [key: string]: new (name: string) => Node } = { LowpassFilter: LowpassFilter, HighpassFilter: HighpassFilter, StereoWidthFilter: StereoWidthFilter, + ReverbFilter: ReverbFilter, }; import { SoundSet, Source } from "./sources/Source"; @@ -25,6 +26,7 @@ import { LowpassFilter } from "./filters/LowpassFilter"; import { HighpassFilter } from "./filters/HighpassFilter"; import { StereoWidthFilter } from "./filters/StereoWidthFilter"; import { PresetSoundSets } from "./data/sound-sets"; +import { ReverbFilter } from "./filters/ReverbFilter"; // eslint-disable-next-line @typescript-eslint/no-explicit-any export function serializeNode(_node: T): any { diff --git a/tsconfig.json b/tsconfig.json index 8c93ef5..be8b06c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -32,7 +32,8 @@ "src/**/*.tsx", "src/**/*.vue", "tests/**/*.ts", - "tests/**/*.tsx" + "tests/**/*.tsx", + "decs.d.ts", ], "exclude": [ "node_modules"