Works now as intended, thank you!Ivantsov wrote: Mon Dec 29, 2025 1:14 pm I've uploaded the fix for the warping and changed the license to MIT.
I do plan to update this library to include nonlinear filters as well as other interesting kind of filters.
New modern C++ library for fast decramped modulable filters
- KVRian
- 800 posts since 16 May, 2014 from Germany
-
- KVRist
- 484 posts since 8 May, 2007
Thanks for papers and sample code!Ivantsov wrote: Mon Dec 29, 2025 1:14 pm I've uploaded the fix for the warping and changed the license to MIT.
I do plan to update this library to include nonlinear filters as well as other interesting kind of filters.
-
- KVRer
- Topic Starter
- 16 posts since 16 Apr, 2025
I've just added a function that computes the magnitude response. A simple example is in the README. Enjoy!FigBug wrote: Mon Dec 29, 2025 2:10 pm Do you plan to add a method to calculate filter response at a given frequency? i.e. to draw the curve in the ui?
- KVRAF
- 8503 posts since 12 Feb, 2006 from Helsinki, Finland
There is no such thing as negative frequencies for a real-valued signal, so design for a negative cutoff doesn't make sense. The best you can hope for is a filter identical to a positive cutoff and you can do this for any filter by simply using abs() for your cutoff. In practice you'll probably then want to bound the minimum cutoff at some finite value higher than 0 because there is a singularity at DC (for any filter really).Marvinh wrote: Sat Feb 14, 2026 7:22 pm Am I correct that this filter can go thru zero. go to negative cutoff and back to positive cutoff?
-
- KVRist
- 233 posts since 6 Sep, 2015
Maybe switching from lowpass to highpass (when negative) as well? Never tried it but yeah still issue at 0 . When I tried the repo here 0 was fine but I think its taking care of that internally.mystran wrote: Sat Feb 14, 2026 8:03 pmThe best you can hope for is a filter identical to a positive cutoff and you can do this for any filter by simply using abs() for your cutoff.Marvinh wrote: Sat Feb 14, 2026 7:22 pm Am I correct that this filter can go thru zero. go to negative cutoff and back to positive cutoff?
Edit: I was testing offline once I put it in a realtime project it holds true cant be too close to zero or negative.
-
- KVRer
- Topic Starter
- 16 posts since 16 Apr, 2025
A discrete mapping with a negative cutoff frequency theoretically gives you the same magnitude response, but with singularities (poles or zeros) outside of the unit circle. For example, take a first order allpass filter, if the mapping g(fc) is your pole, then g(-fc) should be your zero. A pole outside of the unit circle makes a causal linear time invariant system unstable, but for nonlinear systems, the fun just begins.
My paper and the library use an even symmetric mapping, reflecting the negative cutoff frequencies. Indeed, you'll see fc^2 or fc^4 in there. The library also allows you to have the cutoff frequency tend to infinity, where a lowpass filter turns into a short circuit. On the other hand, intuitively, a cutoff frequency of 0Hz should give an open circuit (for a lowpass). In fact, in that case, the system's states freeze (like the absolute zero phenomenon). Unfortunately, for the second order filters, there is a multiplication between 0 and infinity which is mathematically not defined and returns NaN. Nevertheless, with 32 bit floating point numbers, I quickly successfully tested with cutoff frequencies as low as 10^-5Hz, which is acceptable.
My paper and the library use an even symmetric mapping, reflecting the negative cutoff frequencies. Indeed, you'll see fc^2 or fc^4 in there. The library also allows you to have the cutoff frequency tend to infinity, where a lowpass filter turns into a short circuit. On the other hand, intuitively, a cutoff frequency of 0Hz should give an open circuit (for a lowpass). In fact, in that case, the system's states freeze (like the absolute zero phenomenon). Unfortunately, for the second order filters, there is a multiplication between 0 and infinity which is mathematically not defined and returns NaN. Nevertheless, with 32 bit floating point numbers, I quickly successfully tested with cutoff frequencies as low as 10^-5Hz, which is acceptable.
- KVRer
- 20 posts since 26 Aug, 2022
@Ivanstov
Hi Yuriy,
I'm porting your two papers to Reaper JSFX.
Am I allowed to share the result, and if yes, under which conditions?
(I've noticed the MIT license for your code, but I'm only using the two papers. Your website says "All rights reserved").
Amazing work by the way!
I've followed paper1 to make a 1-pole low-pass with Transposed Direct Form II and sigma as a user-facing parameter. Worked 1-shot!
Then I replaced TDF2 with "Ivanstov's Optimised state space" from paper 2 (dumbly reproducing the block diagram)... Worked 1-shot!
Read each paper once and got a working implementation at first try. That means your explanations are pretty neat.
Congrats on your results and your pedagogy!
About sharing the JSFX, if you don't want to answer here, my e-mail is antoine.portes@yandex.com
Antoine
Hi Yuriy,
I'm porting your two papers to Reaper JSFX.
Am I allowed to share the result, and if yes, under which conditions?
(I've noticed the MIT license for your code, but I'm only using the two papers. Your website says "All rights reserved").
Amazing work by the way!
I've followed paper1 to make a 1-pole low-pass with Transposed Direct Form II and sigma as a user-facing parameter. Worked 1-shot!
Then I replaced TDF2 with "Ivanstov's Optimised state space" from paper 2 (dumbly reproducing the block diagram)... Worked 1-shot!
Read each paper once and got a working implementation at first try. That means your explanations are pretty neat.
Congrats on your results and your pedagogy!
About sharing the JSFX, if you don't want to answer here, my e-mail is antoine.portes@yandex.com
Antoine
Working-class filter design (GitHub)
Monetize THIS (Bandcamp)
"Man vergilt einem Lehrer schlecht, wenn man immer nur der Schüler bleibt." — Friedrich Nietzsche (Ecce homo)
Monetize THIS (Bandcamp)
"Man vergilt einem Lehrer schlecht, wenn man immer nur der Schüler bleibt." — Friedrich Nietzsche (Ecce homo)
-
- KVRer
- Topic Starter
- 16 posts since 16 Apr, 2025
The papers are in public domain and free. You can do whatever you want with them, but claim to be the original author. Just mentioning the author's full name or surname would be appreciated by me.
I'm happy that you managed to easily build from the papers. In fact, research should be simple and beautiful; otherwise, it's not interesting. The second order filters are a little bit trickier, so if you struggle with implementing them, don't hesitate to write an email to me or even share it in some related thread on this forum.
And thank you for the kind words.
I'm happy that you managed to easily build from the papers. In fact, research should be simple and beautiful; otherwise, it's not interesting. The second order filters are a little bit trickier, so if you struggle with implementing them, don't hesitate to write an email to me or even share it in some related thread on this forum.
And thank you for the kind words.
- KVRer
- 20 posts since 26 Aug, 2022
Wonderful!
Your name and links to your papers were the first lines of code.
If I share anything, I'll make sure you get the credit you deserve.
Since you mentioned second-order filters, I couldn't have them work as expected.
I've added arrows to see the path more explicitly (some are very obvious but obvious doesn't hurt).
So first if I misunderstood the signal path, please correct me.
But I'm pretty sure my failed attempt comes from the fact that I don't understand what "nu_alpha" refers to (circled in green on the block diagram).
I've tried to guess... What I got was a filter indeed, a stable one even, a 2-pole probably (?).
But not a LP!
Your name and links to your papers were the first lines of code.
If I share anything, I'll make sure you get the credit you deserve.
Since you mentioned second-order filters, I couldn't have them work as expected.
I've added arrows to see the path more explicitly (some are very obvious but obvious doesn't hurt).
So first if I misunderstood the signal path, please correct me.
But I'm pretty sure my failed attempt comes from the fact that I don't understand what "nu_alpha" refers to (circled in green on the block diagram).
I've tried to guess... What I got was a filter indeed, a stable one even, a 2-pole probably (?).
But not a LP!
You do not have the required permissions to view the files attached to this post.
-
Guillaume Piolat Guillaume Piolat https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=366815
- KVRist
- 308 posts since 21 Sep, 2015 from Grenoble
I have a question: does it make sense to smooth the coefficients linearly or even exponentially? Would it explode?
Checkout our plug-ins here.
-
- KVRer
- Topic Starter
- 16 posts since 16 Apr, 2025
The signal path with the additional arrows is correct. I'd advise you to first use Table 4.1 to implement the structure. Then you'll notice things can be simplified like shown in the corresponding Figure 4.1. In fact, the circled gain block has the equalityantoineportes wrote: Wed Feb 18, 2026 12:17 pm Wonderful!
Your name and links to your papers were the first lines of code.
If I share anything, I'll make sure you get the credit you deserve.
Since you mentioned second-order filters, I couldn't have them work as expected.
Ivanstov BD4.png
I've added arrows to see the path more explicitly (some are very obvious but obvious doesn't hurt).
So first if I misunderstood the signal path, please correct me.
But I'm pretty sure my failed attempt comes from the fact that I don't understand what "nu_alpha" refers to (circled in green on the block diagram).
I've tried to guess... What I got was a filter indeed, a stable one even, a 2-pole probably (?).
But not a LP!
Code: Select all
v_a / (u pi^2) = G * (1 - a1 + a2) / u, with G = 1 / (1 + a1 + a2) [paper1, table3.1]Code: Select all
v_a = pi^2 * (1 - a1 + a2) / (1 + a1 + a2)Code: Select all
v_a = nu(w = 0) = sqrt(sigma^4) = sigma^2-
- KVRer
- Topic Starter
- 16 posts since 16 Apr, 2025
The filters are stable under modulation of the cutoff frequency and resonance (except for fc = 0Hz). Interpolating the coefficients instead is unnatural and might lead to instability. There is no reason to do that, I think.Guillaume Piolat wrote: Wed Feb 18, 2026 12:25 pm I have a question: does it make sense to smooth the coefficients linearly or even exponentially? Would it explode?
-
- KVRist
- 233 posts since 6 Sep, 2015
I think this would be a good way to modulate maybe a little obvious but not sure if flipping polarity would be correct.Ivantsov wrote: Wed Feb 18, 2026 2:24 pmThe filters are stable under modulation of the cutoff frequency and resonance (except for fc = 0Hz). Interpolating the coefficients instead is unnatural and might lead to instability. There is no reason to do that, I think.Guillaume Piolat wrote: Wed Feb 18, 2026 12:25 pm I have a question: does it make sense to smooth the coefficients linearly or even exponentially? Would it explode?
ex: cutoff < 0 : -lowpass.process(abs(cutoff)), cutoff > 0 : lowpass.process(abs(cutoff)), cutoff == 0 : return 0;
replace 0 with the epsilon you mentioned
-
- KVRer
- 8 posts since 4 May, 2026
Impressive work on the decramping implementation! The stability under extreme frequency modulation (especially handling a Q of 100 from 10^-5 Hz to infinity without blowing up) is exactly the kind of bulletproof DSP I appreciate.
I am currently developing a modern guitar amp suite using JUCE and C++, and I will definitely be compiling your C++20 library to test it out in my pre and post-EQ stages.
Thanks for sharing this level of engineering with the community!
I am currently developing a modern guitar amp suite using JUCE and C++, and I will definitely be compiling your C++20 library to test it out in my pre and post-EQ stages.
Thanks for sharing this level of engineering with the community!
