From 9efd69ff00095a31e7be1682e347fa9f1d03a157 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Fri, 24 Jan 2020 02:22:14 +0000 Subject: [PATCH] refactor(dsp): restructure oscillators, fft, window, update gen-diagrams --- packages/dsp/src/{ => fft}/fft.ts | 4 +-- packages/dsp/src/{util => fft}/window.ts | 0 packages/dsp/src/index.ts | 25 ++++++++-------- .../dsp/src/{stateless => osc}/additive.ts | 0 packages/dsp/src/{stateless => osc}/dsf.ts | 0 packages/dsp/src/{stateless => osc}/mix.ts | 0 .../dsp/src/{stateless => osc}/parabolic.ts | 0 packages/dsp/src/{stateless => osc}/rect.ts | 0 packages/dsp/src/{stateless => osc}/saw.ts | 0 packages/dsp/src/{stateless => osc}/sin.ts | 0 packages/dsp/src/{stateless => osc}/tri.ts | 0 .../dsp/src/{stateless => osc}/wavetable.ts | 0 .../dsp/src/proc/{dcblocker.ts => dcblock.ts} | 4 +-- packages/dsp/src/proc/foldback.ts | 4 +++ packages/dsp/src/proc/svf.ts | 7 ++--- packages/dsp/tools/generate-diagrams.ts | 29 +++++++++++++++---- 16 files changed, 47 insertions(+), 26 deletions(-) rename packages/dsp/src/{ => fft}/fft.ts (99%) rename packages/dsp/src/{util => fft}/window.ts (100%) rename packages/dsp/src/{stateless => osc}/additive.ts (100%) rename packages/dsp/src/{stateless => osc}/dsf.ts (100%) rename packages/dsp/src/{stateless => osc}/mix.ts (100%) rename packages/dsp/src/{stateless => osc}/parabolic.ts (100%) rename packages/dsp/src/{stateless => osc}/rect.ts (100%) rename packages/dsp/src/{stateless => osc}/saw.ts (100%) rename packages/dsp/src/{stateless => osc}/sin.ts (100%) rename packages/dsp/src/{stateless => osc}/tri.ts (100%) rename packages/dsp/src/{stateless => osc}/wavetable.ts (100%) rename packages/dsp/src/proc/{dcblocker.ts => dcblock.ts} (64%) diff --git a/packages/dsp/src/fft.ts b/packages/dsp/src/fft/fft.ts similarity index 99% rename from packages/dsp/src/fft.ts rename to packages/dsp/src/fft/fft.ts index 423452590d..ca428c8f43 100644 --- a/packages/dsp/src/fft.ts +++ b/packages/dsp/src/fft/fft.ts @@ -1,7 +1,7 @@ import { NumericArray } from "@thi.ng/api"; import { isNumber } from "@thi.ng/checks"; -import { ComplexArray } from "./api"; -import { magDb } from "./util/convert"; +import { ComplexArray } from "../api"; +import { magDb } from "../util/convert"; const PI = Math.PI; diff --git a/packages/dsp/src/util/window.ts b/packages/dsp/src/fft/window.ts similarity index 100% rename from packages/dsp/src/util/window.ts rename to packages/dsp/src/fft/window.ts diff --git a/packages/dsp/src/index.ts b/packages/dsp/src/index.ts index 23e975da66..0e09ccd2c4 100644 --- a/packages/dsp/src/index.ts +++ b/packages/dsp/src/index.ts @@ -1,5 +1,4 @@ export * from "./api"; -export * from "./fft"; export * from "./comp/addg"; export * from "./comp/compp"; @@ -31,7 +30,7 @@ export * from "./gen/white-noise"; export * from "./proc/allpass"; export * from "./proc/aproc"; export * from "./proc/biquad"; -export * from "./proc/dcblocker"; +export * from "./proc/dcblock"; export * from "./proc/delay"; export * from "./proc/feedback-delay"; export * from "./proc/foldback"; @@ -41,17 +40,19 @@ export * from "./proc/onepole"; export * from "./proc/svf"; export * from "./proc/waveshaper"; -export * from "./stateless/additive"; -export * from "./stateless/dsf"; -export * from "./stateless/mix"; -export * from "./stateless/parabolic"; -export * from "./stateless/rect"; -export * from "./stateless/saw"; -export * from "./stateless/sin"; -export * from "./stateless/tri"; -export * from "./stateless/wavetable"; +export * from "./osc/additive"; +export * from "./osc/dsf"; +export * from "./osc/mix"; +export * from "./osc/parabolic"; +export * from "./osc/rect"; +export * from "./osc/saw"; +export * from "./osc/sin"; +export * from "./osc/tri"; +export * from "./osc/wavetable"; + +export * from "./fft/fft"; +export * from "./fft/window"; export * from "./util/anti-alias"; export * from "./util/convert"; export * from "./util/filter-response"; -export * from "./util/window"; diff --git a/packages/dsp/src/stateless/additive.ts b/packages/dsp/src/osc/additive.ts similarity index 100% rename from packages/dsp/src/stateless/additive.ts rename to packages/dsp/src/osc/additive.ts diff --git a/packages/dsp/src/stateless/dsf.ts b/packages/dsp/src/osc/dsf.ts similarity index 100% rename from packages/dsp/src/stateless/dsf.ts rename to packages/dsp/src/osc/dsf.ts diff --git a/packages/dsp/src/stateless/mix.ts b/packages/dsp/src/osc/mix.ts similarity index 100% rename from packages/dsp/src/stateless/mix.ts rename to packages/dsp/src/osc/mix.ts diff --git a/packages/dsp/src/stateless/parabolic.ts b/packages/dsp/src/osc/parabolic.ts similarity index 100% rename from packages/dsp/src/stateless/parabolic.ts rename to packages/dsp/src/osc/parabolic.ts diff --git a/packages/dsp/src/stateless/rect.ts b/packages/dsp/src/osc/rect.ts similarity index 100% rename from packages/dsp/src/stateless/rect.ts rename to packages/dsp/src/osc/rect.ts diff --git a/packages/dsp/src/stateless/saw.ts b/packages/dsp/src/osc/saw.ts similarity index 100% rename from packages/dsp/src/stateless/saw.ts rename to packages/dsp/src/osc/saw.ts diff --git a/packages/dsp/src/stateless/sin.ts b/packages/dsp/src/osc/sin.ts similarity index 100% rename from packages/dsp/src/stateless/sin.ts rename to packages/dsp/src/osc/sin.ts diff --git a/packages/dsp/src/stateless/tri.ts b/packages/dsp/src/osc/tri.ts similarity index 100% rename from packages/dsp/src/stateless/tri.ts rename to packages/dsp/src/osc/tri.ts diff --git a/packages/dsp/src/stateless/wavetable.ts b/packages/dsp/src/osc/wavetable.ts similarity index 100% rename from packages/dsp/src/stateless/wavetable.ts rename to packages/dsp/src/osc/wavetable.ts diff --git a/packages/dsp/src/proc/dcblocker.ts b/packages/dsp/src/proc/dcblock.ts similarity index 64% rename from packages/dsp/src/proc/dcblocker.ts rename to packages/dsp/src/proc/dcblock.ts index 6ac48a3762..886d61add5 100644 --- a/packages/dsp/src/proc/dcblocker.ts +++ b/packages/dsp/src/proc/dcblock.ts @@ -6,9 +6,9 @@ import { OnePole } from "./onepole"; * * @param freq */ -export const dcblocker = (freq: number) => new DCBlocker(FilterType.LP, freq); +export const dcBlock = (freq: number) => new DCBlock(FilterType.LP, freq); -export class DCBlocker extends OnePole { +export class DCBlock extends OnePole { next(x: number) { return x - super.next(x); } diff --git a/packages/dsp/src/proc/foldback.ts b/packages/dsp/src/proc/foldback.ts index c2918d6feb..8793a7f116 100644 --- a/packages/dsp/src/proc/foldback.ts +++ b/packages/dsp/src/proc/foldback.ts @@ -5,6 +5,10 @@ import { AProc } from "./aproc"; * Recursively folds input into `[-thresh .. +thresh]` interval and * amplifies it with `amp` (default: 1/thresh). * + * @remarks + * Reference: + * - https://www.desmos.com/calculator/lkyf2ag3ta + * * @param thresh - fold threshold * @param amp - post amplifier */ diff --git a/packages/dsp/src/proc/svf.ts b/packages/dsp/src/proc/svf.ts index f60e3a844a..0076dfc4f5 100644 --- a/packages/dsp/src/proc/svf.ts +++ b/packages/dsp/src/proc/svf.ts @@ -27,14 +27,13 @@ export const svfAllpass = (fc: number, q?: number) => new SVF(FilterType.ALL, fc, q); /** - * State variable filter w/ trapezoidal integration, after Andrew - * Simper. + * Multi-type state variable filter w/ trapezoidal integration, after + * Andrew Simper. * * Reference: * * - https://cytomic.com/files/dsp/SvfLinearTrapOptimised2.pdf * - https://en.wikipedia.org/wiki/Trapezoidal_rule - * */ export class SVF extends AProc implements IReset { protected _a1!: number; @@ -47,7 +46,7 @@ export class SVF extends AProc implements IReset { constructor( protected _type: SVFType, protected _freq: number, - protected _q = 0 + protected _q = 0.5 ) { super(0); this.reset(); diff --git a/packages/dsp/tools/generate-diagrams.ts b/packages/dsp/tools/generate-diagrams.ts index c60d02cd10..8f3c8fcfb3 100644 --- a/packages/dsp/tools/generate-diagrams.ts +++ b/packages/dsp/tools/generate-diagrams.ts @@ -26,7 +26,6 @@ import { import { writeFileSync } from "fs"; import { allpass, - AllPass1, biquadBP, biquadHiShelf, biquadHP, @@ -35,9 +34,10 @@ import { biquadNotch, biquadPeak, curve, - dcblocker, + dcBlock, dsfHOF, filterResponse, + foldback, freqMs, freqRange, IGen, @@ -55,9 +55,12 @@ import { saw, sin, StatelessOscillator, + svfAllpass, svfBP, svfHP, svfLP, + svfNotch, + svfPeak, tri, wavetable, whiteNoise @@ -76,7 +79,7 @@ const OSC: IObjectOf = { tri, parabolic, recttri: mixOscHOF(rect, tri), - dsf: dsfHOF(0.4, 3), + dsf: dsfHOF(0.6, 2.04), wt: wavetable(curve(1, -1, 127).take(128)) }; @@ -245,9 +248,15 @@ withFilters((id) => `${id}-svf-hpf.svg`, svfHP); withFilters((id) => `${id}-svf-bpf.svg`, svfBP); +withFilters((id) => `${id}-svf-notch.svg`, svfNotch); + +withFilters((id) => `${id}-svf-peak.svg`, svfPeak); + +withFilters((id) => `${id}-svf-all.svg`, svfAllpass); + withFilters((id) => `${id}-1pole-lpf.svg`, onepoleLP); -withFilters((id) => `${id}-dcblock.svg`, dcblocker); +withFilters((id) => `${id}-dcblock.svg`, dcBlock); withFilters((id) => `${id}-bq-lpf.svg`, biquadLP); @@ -263,6 +272,14 @@ withFilters((id) => `${id}-bq-lsh.svg`, biquadLoShelf); withFilters((id) => `${id}-bq-hsh.svg`, biquadHiShelf); +withFilters( + (id) => `${id}-foldback.svg`, + (t) => foldback(t), + undefined, + [0.5, 0.3, 0.15], + ["orig", ...[0.5, 0.3, 0.15].map((t) => `t=${t}`)] +); + withFilters( (id) => `${id}-allpass1.svg`, (f) => allpass(f) @@ -289,8 +306,8 @@ withFilters( withFilters( (id) => `${id}-allpass-high.svg`, (f) => { - let flt = new AllPass1(f); - return { + let flt = allpass(f); + return >{ next(x: number) { return flt.high(x); }