From 61c0d3b787ec40920216445d9b86216304d9ee16 Mon Sep 17 00:00:00 2001 From: HiveBeats Date: Wed, 17 Jan 2024 08:56:58 +0700 Subject: [PATCH] wip: state-variable filter doc --- docs/StateVariableFilter.md | 52 ++++++++++++++++++++++++++++++++++++ docs/image-1.png | Bin 0 -> 3091 bytes docs/image.png | Bin 0 -> 3398 bytes docs/matrix.md | 19 +++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 docs/StateVariableFilter.md create mode 100644 docs/image-1.png create mode 100644 docs/image.png create mode 100644 docs/matrix.md diff --git a/docs/StateVariableFilter.md b/docs/StateVariableFilter.md new file mode 100644 index 0000000..8cbb142 --- /dev/null +++ b/docs/StateVariableFilter.md @@ -0,0 +1,52 @@ +https://www.earlevel.com/main/2003/03/02/the-digital-state-variable-filter/ + +The frequency control coefficient, f, is defined as + +![Alt text](image.png) + +where Fs is the sample rate and Fc is the filter’s corner frequency you want to set. The q coefficient is defined as + +![Alt text](image-1.png) + +where Q normally ranges from 0.5 to inifinity (where the filter oscillates). + + +The main drawback of the digital state variable is that it becomes unstable at higher frequencies. It depends on the Q setting, but basically the upper bound of stability is about where f reaches 1, which is at one-sixth of the sample rate (8 kHz at 48 kHz). The only way around this is to oversample. A simple way to double the filter’s sample rate (and thereby double the filter’s frequency range) is to run the filter twice with the same input sample, and discard one output sample. + + + +example with double-sampling + +``` +input = input buffer; +output = output buffer; +fs = sampling frequency; +fc = cutoff frequency normally something like: + 440.0*pow(2.0, (midi_note - 69.0)/12.0); +res = resonance 0 to 1; +drive = internal distortion 0 to 0.1 +freq = 2.0*sin(PI*MIN(0.25, fc/(fs*2))); // the fs*2 is because it's double sampled +damp = MIN(2.0*(1.0 - pow(res, 0.25)), MIN(2.0, 2.0/freq - freq*0.5)); +notch = notch output +low = low pass output +high = high pass output +band = band pass output +peak = peaking output = low - high +-- +double sampled svf loop: +for (i=0; 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 literal 0 HcmV?d00001 diff --git a/docs/image.png b/docs/image.png new file mode 100644 index 0000000000000000000000000000000000000000..6bbf6e65e3cd9e91b8b7ec115e8671a4aa9100f5 GIT binary patch literal 3398 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 literal 0 HcmV?d00001 diff --git a/docs/matrix.md b/docs/matrix.md new file mode 100644 index 0000000..cc8832f --- /dev/null +++ b/docs/matrix.md @@ -0,0 +1,19 @@ + +// signal -> adsr -> filter +// ^ ^ ^ +// | | | +// can be modulated +// by lfo, or adsr + + + +у каждого из них должна быть ручка для изменения состояния +на каждом семпле????? + + + +багует сам алгоритм изменения частоты, либо алгоритм пересчета коэфициентов фильтра + + + +