Add cutoff param smoothing in multimode_filter example

Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
This commit is contained in:
Christopher Arndt 2024-04-29 15:31:28 +02:00
parent 810efc80f8
commit 2ec533edca
3 changed files with 42 additions and 11 deletions

View File

@ -2,6 +2,7 @@
import nymph import nymph
import paramsmooth
import svf import svf
const PluginUri = "urn:nymph:examples:multimode-filter" const PluginUri = "urn:nymph:examples:multimode-filter"
@ -19,6 +20,7 @@ type
q: ptr cfloat q: ptr cfloat
mode: ptr cfloat mode: ptr cfloat
svf: FilterSV svf: FilterSV
smoothCutoff: ParamSmooth
proc instantiate(descriptor: ptr Lv2Descriptor; sampleRate: cdouble; proc instantiate(descriptor: ptr Lv2Descriptor; sampleRate: cdouble;
@ -26,6 +28,7 @@ proc instantiate(descriptor: ptr Lv2Descriptor; sampleRate: cdouble;
Lv2Handle {.cdecl.} = Lv2Handle {.cdecl.} =
let plug = createShared(SVFPlugin) let plug = createShared(SVFPlugin)
plug.svf = initFilterSV(fmLowPass, sampleRate) plug.svf = initFilterSV(fmLowPass, sampleRate)
plug.smoothCutoff = initParamSmooth(20.0, sampleRate)
return plug return plug
@ -56,12 +59,13 @@ proc activate(instance: Lv2Handle) {.cdecl.} =
proc run(instance: Lv2Handle; nSamples: cuint) {.cdecl.} = proc run(instance: Lv2Handle; nSamples: cuint) {.cdecl.} =
let plug = cast[ptr SVFPlugin](instance) let plug = cast[ptr SVFPlugin](instance)
let cutoff = plug.cutoff[].clamp(16.0, 7_000.0)
plug.svf.setMode(plug.mode[].int.clamp(0, 3).FilterMode) plug.svf.setMode(plug.mode[].int.clamp(0, 3).FilterMode)
plug.svf.setCutoff(plug.cutoff[].clamp(16.0, 7_000.0))
plug.svf.setQ(plug.q[].clamp(0.8, 10.0)) plug.svf.setQ(plug.q[].clamp(0.8, 10.0))
plug.svf.calcCoef()
for pos in 0 ..< nSamples: for pos in 0 ..< nSamples:
plug.svf.setCutoff(plug.smoothCutoff.process(cutoff))
plug.svf.calcCoef()
plug.output[pos] = plug.svf.process(plug.input[pos]) plug.output[pos] = plug.svf.process(plug.input[pos])

35
examples/paramsmooth.nim Normal file
View File

@ -0,0 +1,35 @@
## One-pole LPF for smooth parameter changes
##
## https://www.musicdsp.org/en/latest/Filters/257-1-pole-lpf-for-smooth-parameter-changes.html
import math
const TwoPi = PI * 2
type
ParamSmooth* = object
a, b, t, z: float
fs: float64
proc reset*(self: var ParamSmooth) =
self.z = 0.0
proc setSampleRate*(self: var ParamSmooth, sampleRate: float64) =
if sampleRate != self.fs:
self.fs = sampleRate
self.a = exp(-TwoPi / (self.t * 0.001 * sampleRate))
self.b = 1.0 - self.a
self.z = 0.0
proc process*(self: var ParamSmooth, sample: float): float =
self.z = (sample * self.b) + (self.z * self.a)
return self.z
proc initParamSmooth*(smoothingTimeMs: float = 20.0, sampleRate: float64 = 48_000.0): ParamSmooth =
result.t = smoothingTimeMs
result.setSampleRate(sampleRate)

View File

@ -11,15 +11,7 @@ type
FilterSV* = object FilterSV* = object
mode: FilterMode mode: FilterMode
cutoff: float cutoff, q, lowPass, hiPass, bandPass, bandReject, a, b, maxCutoff: float
q: float
lowPass: float
hiPass: float
bandPass: float
bandReject: float
a: float
b: float
maxCutoff: float
sampleRate: float64 sampleRate: float64
needs_update: bool needs_update: bool