Go Back   Cockos Incorporated Forums > REAPER Forums > ReaScript, JSFX, REAPER Plug-in Extensions, Developer Forum

Reply
 
Thread Tools Display Modes
Old 03-02-2021, 11:24 AM   #1
Phazma
Human being with feelings
 
Join Date: Jun 2019
Posts: 2,872
Default Resonant filter jsfx that sounds like FilterFreak or Filterbank3?

Has anyone created a jsfx filter-plugin that breaks up when cranking the resonance in a similar way like FilterFreak or Filterbank3? Here are their graphs that show more or less what is going on when boosting the resonance:



From reading the description at SoundToys for Filterfreak I might suspect that both of them are based on Sherman Filterbank but I have no idea. It is nowhere mentioned officially and I never had the pleasure to use one so that I could compare and find it out.

I have found Saike's Filther jsfx which is super deep and has a ton of interesting filter emulations but none of them, when sending the same material through, sound like FilterFreak and Filterbank3 (which sound pretty much identical so I am convinced they emulate the same thing).

So has anyone created a jsfx that sounds similar to these or knows which filter they emulate?

EDIT: For anyone familiar with the plugins I am talking about: I am usually using the FilterFreak filter in 4 pole mode with "Analog Style" set to "Fat" (but the sound seems to change very little based on "style") and in Filterbank3 I am using the LP 30dB Filter. Oddly the 30dB Filter in Filterbank sounds more like the 24dB filter in FilterFreak than the actual 24dB filter does (probably because that one emulates a Moog which seems not to be what I am looking for):

Last edited by Phazma; 03-02-2021 at 11:44 AM.
Phazma is offline   Reply With Quote
Old 03-02-2021, 12:40 PM   #2
todd_r
Human being with feelings
 
todd_r's Avatar
 
Join Date: Nov 2006
Posts: 855
Default

Lots and lots of filters to try out in Saike's Filther

https://github.com/JoepVanlier/JSFX



todd_r is offline   Reply With Quote
Old 03-02-2021, 01:50 PM   #3
Phazma
Human being with feelings
 
Join Date: Jun 2019
Posts: 2,872
Default

Thanks, as mentioned I do have tried out all the LP filters in Filther and there are many beautiful and very interesting ones which I will surely use but it seems to not include one that behaves like this. The one I am searching looks like it attenuates the bass quite a bit when boosting the resonance which gives a nice non-static sound, specially on bass sounds and when going through saturation.

Btw I just discovered Saike's jsfx little ago and he has some serious next level stuff!
Should he happen to read this, know how to make such a filter and be interested to add it to Filther it would be really cool
Phazma is offline   Reply With Quote
Old 03-02-2021, 02:31 PM   #4
todd_r
Human being with feelings
 
todd_r's Avatar
 
Join Date: Nov 2006
Posts: 855
Default

Ah sorry, missed that you'd already tried filther.

Not JSFX, but a couple of good free VSTs to try...

http://www.admiralquality.com/produc...naive-lpf-win/

https://plugins4free.com/plugin/601/
todd_r is offline   Reply With Quote
Old 03-02-2021, 02:53 PM   #5
sai'ke
Human being with feelings
 
sai'ke's Avatar
 
Join Date: Aug 2009
Location: NL
Posts: 1,453
Default

Ah, is it purely the low end drop that you're looking for?

Many analog filters (I'm thinking state variable filters) actually show a low end drop because the designers drop the overall volume when the resonance goes up (because resonance gets so loud and could potentially also distort). I usually choose not to model this drop because I like to keep the bass end at the same level.

If instead you are looking for a specific type of distortion then it becomes more complicated.

A linear filter that does the compensation is not so difficult. We'd still need to know how much they drop the volume though because from the graphs I gather that they don't do perfect compensation (keeping the maximum at unity level). Or hm, maybe they normalize by total energy.

Do you have access to the filter? Can you run some test signals?
__________________
[Tracker Plugin: Thread|Github|Reapack] | [Routing Plugin: Thread|Reapack] | [More JSFX: Thread|Descriptions|Reapack]

Last edited by sai'ke; 03-02-2021 at 03:08 PM.
sai'ke is offline   Reply With Quote
Old 03-02-2021, 03:21 PM   #6
Phazma
Human being with feelings
 
Join Date: Jun 2019
Posts: 2,872
Default

Wow Saike amazing that you would like to help me with that.

I am sure the low end drop plays a big role in it but I have no clue how important the distortion is in achieving the sound. Actually FilterFreak and Filterbank3 they might be 2 different filters but sound very similar to me because of the low end drop. Anyway many people say that FilterFreak is their favorite filter plugin so I think it makes sense to try and actually emulate also the volume compensation and perhaps distortion if possible, and everyone gets a new and sought after filter.

These graphs are the only theoretical information I have but I have access to both FilterFreak and Filterbank3 so I could help you do all the tests you need.

I should mention tough, the reason I am searching for this filter as jsfx even tough I have these 2 vsts is that I would love to copy and integrate that algorithm into a distortion jsfx I am working on. It would be for personal use only, unless it turns out great, in that case I would publish it giving credit to the people who's pieces of code and algorithms I used. I hope you would be okay with me to implement it into my jsfx as well, once you implemented it into Filther.
Phazma is offline   Reply With Quote
Old 03-02-2021, 03:30 PM   #7
sai'ke
Human being with feelings
 
sai'ke's Avatar
 
Join Date: Aug 2009
Location: NL
Posts: 1,453
Default

I license most of my stuff under MIT, which means you can do whatever you want with it.

Well, we can start with a linear filter and see how close that gets you.

Do you want multi-mode or only a lowpass filter?
__________________
[Tracker Plugin: Thread|Github|Reapack] | [Routing Plugin: Thread|Reapack] | [More JSFX: Thread|Descriptions|Reapack]
sai'ke is offline   Reply With Quote
Old 03-02-2021, 03:57 PM   #8
Phazma
Human being with feelings
 
Join Date: Jun 2019
Posts: 2,872
Default

Quote:
Originally Posted by sai'ke View Post
I license most of my stuff under MIT, which means you can do whatever you want with it.

Well, we can start with a linear filter and see how close that gets you.

Do you want multi-mode or only a lowpass filter?
Great! Lowpass is the most important for me, but if multimode doesn't imply too much extra work then it would be nice to have as well for certain situations.
Phazma is offline   Reply With Quote
Old 03-02-2021, 05:05 PM   #9
junh1024
Human being with feelings
 
Join Date: Feb 2014
Posts: 240
Default

not JS, but have you tried ReaEQ: lowpass, & decreasing the bandwidth?
__________________
REAPER 2D/3D Surround suite: Instructions & Download | Discussion | Donate
junh1024 is offline   Reply With Quote
Old 03-02-2021, 09:38 PM   #10
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 876
Default

It looks exactly like a four pole filter straight from the VA filter book. I implemented it here, although I have to add the caveat that the code isn't exactly spectacular. I am positive that I rewrote it sometime in the last six and a half years, but I think the rewrite got lost in a hard drive malfunction and I never went back to it.

Come to think of it, I think that same accident took the 303 filter emulation I was working on as well. Didn't even realize it. Dang.


Anyways, the resonance needs to go higher to see the effect, you can either change slider2 as follows or manually type in higher values. As the value approaches you will see the low frequencies drop exactly like that animated gif.

slider2:1<0,20,0.01>Resonance

https://forum.cockos.com/showthread.php?t=141923
SaulT is offline   Reply With Quote
Old 03-02-2021, 10:27 PM   #11
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 876
Default

Wow, I did not enjoy revisiting that one.

Quick and dirty hack. Raise the resonance, see the drop. I've been experimenting with some nonlinearity in the state variable and introducing some sample delay on purpose. You can see that it changes the cutoff location.


https://stash.reaper.fm/v/41486/moog-over-2.txt
SaulT is offline   Reply With Quote
Old 03-03-2021, 02:32 AM   #12
Phazma
Human being with feelings
 
Join Date: Jun 2019
Posts: 2,872
Default

SaulT, thanks for sharing and revisiting it!

It comes way closer to what I am searching than any of the alternatives. Probably because it is the only one to feature the lowend-drop. However I am still missing some smoothness in sound and I don't know what it could depend on. It sounds like the filter I am searching sounds slightly steeper, even tough it should be a 4 pole filter (in FilterFreak). Funny tough that in Filterbank3 it is a 5 pole filter and sounds pretty much the same to the 4 pole in FilterFreak. Maybe that one is a specially steep 4 pole (even tough I don't know how that could make sense).

I believe that also the way the gain is attenuated when the resonance rises and the low end drops plays a role in the smoothness.

Ultimately but FF and FB3 have a noise floor that rises when boosting the resonance pretty high (which doesn't happen in your filter). While that is not really a desired or needed effect, maybe it gives some important clue on how the filter is designed?
Phazma is offline   Reply With Quote
Old 03-03-2021, 03:51 AM   #13
sai'ke
Human being with feelings
 
sai'ke's Avatar
 
Join Date: Aug 2009
Location: NL
Posts: 1,453
Default

Can you record the response of the filter to this:
https://raw.githubusercontent.com/Jo...io_tester.jsfx

at various levels of resonance (please make note of which audio file corresponds to which resonance level).

The impulses can be used to determine the linear frequency response. Though, the fact that the filter emulates noise might fuck with this a bit.

This'll help us get at least some idea of how much attenuation is taking place. Because essentially, with just that graph with no axis, we're flying blind.
__________________
[Tracker Plugin: Thread|Github|Reapack] | [Routing Plugin: Thread|Reapack] | [More JSFX: Thread|Descriptions|Reapack]
sai'ke is offline   Reply With Quote
Old 03-03-2021, 04:26 AM   #14
Phazma
Human being with feelings
 
Join Date: Jun 2019
Posts: 2,872
Default

Quote:
Originally Posted by sai'ke View Post
Can you record the response of the filter to this:
https://raw.githubusercontent.com/Jo...io_tester.jsfx
Hmm.. how am I supposed to do this? Your JSFX keeps changing the level of the noise output at a certain time interval. Am I supposed to record a 20KHZ-20Hz filter sweep (at different res settings) for each level of noise? If so, at what time interval does the level change?
Phazma is offline   Reply With Quote
Old 03-03-2021, 04:51 AM   #15
sai'ke
Human being with feelings
 
sai'ke's Avatar
 
Join Date: Aug 2009
Location: NL
Posts: 1,453
Default

Quote:
Originally Posted by Phazma View Post
Hmm.. how am I supposed to do this? Your JSFX keeps changing the level of the noise output at a certain time interval. Am I supposed to record a 20KHZ-20Hz filter sweep (at different res settings) for each level of noise? If so, at what time interval does the level change?
Run the entire sequence for a number of resonance settings.

The JSFX goes through different modes and uses different gains to probe nonlinearities. They all give different information.

There's a good chance I will only use a very small subset, but this prevents me from having to ask again if there's additional info needed
__________________
[Tracker Plugin: Thread|Github|Reapack] | [Routing Plugin: Thread|Reapack] | [More JSFX: Thread|Descriptions|Reapack]
sai'ke is offline   Reply With Quote
Old 03-03-2021, 04:59 AM   #16
Phazma
Human being with feelings
 
Join Date: Jun 2019
Posts: 2,872
Default

Ok, so I leave the filter fully open at 20KHz during all measurements and only change the resonance from test to test? Would 10 tests from 0%, 10%... up to 100% resonance be okay?
Phazma is offline   Reply With Quote
Old 03-03-2021, 05:08 AM   #17
sai'ke
Human being with feelings
 
sai'ke's Avatar
 
Join Date: Aug 2009
Location: NL
Posts: 1,453
Default

Quote:
Originally Posted by Phazma View Post
Ok, so I leave the filter fully open at 20KHz during all measurements and only change the resonance from test to test? Would 10 tests from 0%, 10%... up to 100% resonance be okay?
Sorry, put the filter somewhere where we can see the effect you want modelled well. Putting the cutoff at maximum cutoff might not show that much. It may also show some weird artefacts depending on how they modelled it.

In steps of 10% would probably take avery long. Steps of 25% is probably fine

Maybe do it once at 1 kHz and once at 5 kHz.
__________________
[Tracker Plugin: Thread|Github|Reapack] | [Routing Plugin: Thread|Reapack] | [More JSFX: Thread|Descriptions|Reapack]
sai'ke is offline   Reply With Quote
Old 03-03-2021, 09:45 AM   #18
Phazma
Human being with feelings
 
Join Date: Jun 2019
Posts: 2,872
Default

I mostly move within the range of approximately 400-1000Hz so I recorded the files at 400Hz, 700Hz, 1000Hz and 5000Hz.

I used Filterbank3 instead of FilterFreak because I feel the resonance has a more usable range and it is easier to tweak to how I like it. And it has that rare 30dB LP design, which might be interesting in certain situations.

However the noise floor is higher (which I hope we can exclude from modeling) and while doing the test I have seen that it actually has a limiter built in that engages during some of the loudest sine-sweeps.



I hope that these things are not a problem. If they are I will redo it with FilterFreak instead.

I recorded the files at -16dB so to not clip outside of the filter. The frequencies aren't exactly 400-800-700-1000 because Filterbank doesn't let me dial these values in, but the exact frequencies are in the filenames.

Here you go:
https://www.filemail.com/d/behaqpmyeoozjks

Last edited by Phazma; 03-03-2021 at 09:55 AM.
Phazma is offline   Reply With Quote
Old 03-03-2021, 04:58 PM   #19
sai'ke
Human being with feelings
 
sai'ke's Avatar
 
Join Date: Aug 2009
Location: NL
Posts: 1,453
Default

Observations so far (only looked at 1 kHz so far, so take it with a grain of salt):

- Definitely a 4-pole. I don´t see 30 dB/oct, just your plain old 24 dB/oct. Maybe the 6 dB/oct extra refers to something else?

This is the image I get when I look at the differential spectrum between this and a regular 4-pole linear SVF. Note that I compensated the overall output gain here with 1/(1+k)^2, which is roughly the factor I saw in fits to the impulse responses.

Note that theirs is decramped a little bit better (the little bump at the high frequencies), but the linear SVF becomes better than theirs when you oversample.

Resonance at 0.25


Resonance at 0.75 (closer up)


- One curious thing that I see is that they added some really low frequency wobble to it. Not sure if it serves any purpose. I imagine it's not great for headroom, but maybe it does something to the sound that you like? I first conjectured it may mean that in combination with some slight saturation, it would start producing some even harmonics (due to asymmetric clipping), but I don't really see that in the sine sweeps.

- In the sine sweeps I see only odd harmonics popping up, which indicates some saturation with odd symmetry. Whether this is in the filter feedback itself or just something they slap on before or after, I'm not sure about yet. The harmonics only come up when the sweep actually hits the resonance.

Are these your regular drive levels that these recordings were produced at?
__________________
[Tracker Plugin: Thread|Github|Reapack] | [Routing Plugin: Thread|Reapack] | [More JSFX: Thread|Descriptions|Reapack]
sai'ke is offline   Reply With Quote
Old 03-03-2021, 06:16 PM   #20
Phazma
Human being with feelings
 
Join Date: Jun 2019
Posts: 2,872
Default

Depends, I usually hit the filter anywhere between -12dB and -3dB peak, but I often heave distortion afterwards and might boost into the filter even over 0dB if that is what turns out working with the distortion. Still, the "Limiter!" sign like on the picture I posted usually never shows up during my normal usage. And I have strong suspicion that this limiter is actually some form of clipper that causes the distortion that you see. I believe in the sine sweeps with lower volume there is none of that odd harmonic distortion, but better you check that before I say some crap.

Btw just to be sure that you are aware, I repeat that I have lowered the Reaper output volume by -16dB to not distort the recordings. Given that sometimes the peaks on the recordings go up to -2dB during the resonance, it means that what actually came out of the filter was up to +14dB during some of these tests.

I don't know about that rumble. I don't think it has a purpose but who knows.. and it is good to know that it is actually just a 24dB filter, I was wondering why I couldn't hear a difference in steepness to a normal 24dB filter and in fact there is none. God knows why the mis-labeled the filter as 30dB.
Actually this is a very odd plugin but it still manages to sound so great, I don't know why!

Maybe you want me to record just one frequency from FilterFreak as well to see what they have in common and what sets them apart from most other filters beside the low-end drop, to understand what I might be liking about them?

Last edited by Phazma; 03-03-2021 at 06:22 PM.
Phazma is offline   Reply With Quote
Old 03-04-2021, 02:37 AM   #21
sai'ke
Human being with feelings
 
sai'ke's Avatar
 
Join Date: Aug 2009
Location: NL
Posts: 1,453
Default

Nah, let's stick with one filter for now and not muddy the waters by introducing another one into the mix.

I don't have a plugin for this, but could you just put a tone generator in front of this filter, and step the input gain in small steps (the plugin below does this). I'm curious about the harmonics that appear.

Code:
desc:ToneGen
slider1:freq=500<1,22049,1>Frequency

in_pin:left input
in_pin:right input
out_pin:left output
out_pin:right output

@init
/* Settings, may have to tweak */
gain_start = 0;
gain_end = -40;
steps = 11;

gain_step = (gain_end - gain_start) / (steps - 1);
step = 0;

@slider

@block

@sample
( pause == 0 ) ? (
  (step < steps) ? (
    t += 1;
    gain = 10^((gain_start + gain_step * step)/20);
    spl0 = spl1 = gain * sin(2 * $pi * freq * t / srate);
  
    (t > 2 * srate) ? (
      step += 1;
      t = 0;
      pause = 1;
    );
  );
) : (
  (t > srate) ? (
    pause = 0;
    t = 0;
  );
);

t += 1;
Could you do this for the following combos:
Code:
Input freq, Cutoff, Resonance
500         5 kHz,  0.0
500         5 kHz,  0.5
500         5 kHz,  0.75
5 kHz       5 kHz,  0.0
5 kHz       5 kHz,  0.5
5 kHz       5 kHz,  0.75
__________________
[Tracker Plugin: Thread|Github|Reapack] | [Routing Plugin: Thread|Reapack] | [More JSFX: Thread|Descriptions|Reapack]
sai'ke is offline   Reply With Quote
Old 03-04-2021, 04:03 AM   #22
Phazma
Human being with feelings
 
Join Date: Jun 2019
Posts: 2,872
Default

The tests have again been recorded -16dB lower than the actual filter output, just for safety.
Also again, I was not able to dial in precisely 5KHz, the closest possible was 5043,98Hz so I used that.

Here are the files:

https://fil.email/n18qtD5n

I did first put the frequencies you told me into your script and recorded them, but it seems to have output twice the frequency. I don't think that was intended but as I had already recorded the files I am sending them anyway just in case, inside the folder "Filter Tones x2".
In the other folder "Filter Tones x1". I recorded both 500Hz and 5000 Hz (by putting half the values into your script) and in addition I recorded 5044 Hz as well, because maybe there is some difference when the tone and the resonance overlap precisely.

I have noticed on my analyzer that mostly no other frequencies above the noise floor appear, beside in some of the high-resonance tests. At first glance they just look like aliasing though.

EDIT: Actually the filter cutoff frequency seems to not correspond precisely anyway to what the plugin shows. I just tried ro record a file at the most extreme setting of 1.0 resonance at around 5K input freq and cutoff freq to see what goes on with the partial frequencies. You can find it here (named after the frequency the filter claims to be at): https://we.tl/t-cpOSHKov1u

Last edited by Phazma; 03-04-2021 at 04:24 AM.
Phazma is offline   Reply With Quote
Old 03-04-2021, 05:11 AM   #23
sai'ke
Human being with feelings
 
sai'ke's Avatar
 
Join Date: Aug 2009
Location: NL
Posts: 1,453
Default

Ah sorry, yeah, I should've tested it, sorry. I was at a DAW-less computer.

Interesting.

Ah, maybe to make sure that we don't get too much tunnel vision w.r.t. test signals, could you also include an example of an audio clip where you used this filter and you think it behaved exactly how you wanted it to?

Here, it would be nice to have a dry/wet pair so with and without the filter without any filter automation but at a relevant cutoff/resonance (I'm hoping that the thing you love about this filter isn't its dynamic response).

Also make sure that there aren't any effects post this filter. If there are, just remove them, but don't change the sound in any other way to compensate.
__________________
[Tracker Plugin: Thread|Github|Reapack] | [Routing Plugin: Thread|Reapack] | [More JSFX: Thread|Descriptions|Reapack]
sai'ke is offline   Reply With Quote
Old 03-04-2021, 07:39 AM   #24
Phazma
Human being with feelings
 
Join Date: Jun 2019
Posts: 2,872
Default

Here are a few different sound files:

https://we.tl/t-tnTLnUYs37

As said I mostly pair this filter with distortion afterwards, so things like these examples would normally be processed further. And there is something smooth about this filter that gets amplified by distortion. Certainly the pronounced lowend-drop gives more headroom for the distortion, so when boosting the resonance it is easier to make the sounds scream through the distortion compared to filters with no drop which saturate the distortion quickly and it sounds harsh and crackly.
But I think there is something else to it too.. is it maybe that the resoanant frequency is kind of "wobbly"? In general other filters through distortion sound way more "static/mechanic" overall, specially when automated (and even those with a little low-end drop, while this one manages to squelch through the spectrum, always somehow having some kind of movement and enough headroom.
Phazma is offline   Reply With Quote
Old 03-04-2021, 03:37 PM   #25
sai'ke
Human being with feelings
 
sai'ke's Avatar
 
Join Date: Aug 2009
Location: NL
Posts: 1,453
Default

Thanks. I dunno. To me, at least at this input gain level, it looks like a linear 4-pole. I think that what I was observing earlier must have been the limiter kicking in (in the sine sweeps).

I guess you just like the sound of 4p linear filters that compensate for the gain in the resonance?

On your samples, the following code nulled extremely well for me (-48 dB) after dialing in right settings.

When I look at the difference spectrum, it looks pretty much flat, and the phase response is also the same (which makes sense since it almost nulls).

Code:
desc:4p linear SVF
tags: 4-pole linear SVF with gain compensation
author: Joep Vanlier
license: MIT
slider1:freq=0<0,1,.00001>Frequency
slider2:res=0<0,.97,.00001>Resonance
slider3:morph=0<0,1,.00001>Mode

in_pin:left input
in_pin:right input
out_pin:left output
out_pin:right output

@init
oversampling = 1;  // No oversampling, not needed as there is no distortion.
oversampling_ratio = 1 / oversampling;

function init_linearSVF_all(freq, res, morph)
  global(oversampling_ratio)
  local(frac)
  instance(f0, ic1eq, ic2eq, k, g, a1, a2, a3, m0, m1, m2, A)
  (
    f0 = exp( (1-freq) * log(20/22050) ) * oversampling_ratio;
    g = tan(.5 * $pi * f0);
    k = 2 - 2*res;
    a1 = 1/(1+g*(g+k));
    a2 = g*a1;
    a3 = g*a2;
    
    //      v0       v1   v2
    // LP =               v2
    // BP =          v1;
    // HP = v0 - k * v1 - v2;
    // BR = v0 -     v1;
    morph *= 4.0;
    frac = morph - floor(morph);
    morph < 1 ? (
      // LP to BP
      m0 = 0.0;
      m1 = frac;
      m2 = (1.0 - frac);
    ) : ( morph < 2 ) ? (
      // BP to HP
      m0 = frac;
      m1 = (1.0 - frac) - k * frac;
      m2 = -frac;
    ) : ( morph < 3 ) ? (
      // HP to BR
      m0 = (1.0 - frac) + frac;
      m1 = -k * (1.0 - frac) - frac;
      m2 = -(1.0 - frac);
    ) : (
      m0 = (1.0 - frac);
      m1 = -(1.0 - frac);
      m2 = frac;
    );
    
    A = sqrt(1-res*res);
    m0 *= A;
    m1 *= A;
    m2 *= A;
  );
  
function eval_linearSVF_All(v0)
  global()
  local(v1, v2, v3)
  instance(ic1eq, ic2eq, a1, a2, a3, m0, m1, m2, k)
  (
    v3 = v0 - ic2eq;
    v1 = a1 * ic1eq + a2 * v3;
    v2 = ic2eq + a2 * ic1eq + a3 * v3;
    ic1eq = 2.0 * v1 - ic1eq;
    ic2eq = 2.0 * v2 - ic2eq;
    (m0 * v0 + m1 * v1 + m2 * v2)
  );


function reset_linearSVF()
  global()
  local()
  instance(ic1eq, ic2eq, k, a1, a2, a3)
  (
    ic1eq = ic2eq = 0;  
  );
  
@slider

@block

@sample
s += 1;

(s%8 == 0) ? (
  svf1_left.init_linearSVF_all(freq, res, morph);
  svf2_left.init_linearSVF_all(freq, res, morph);
  svf1_right.init_linearSVF_all(freq, res, morph);
  svf2_right.init_linearSVF_all(freq, res, morph);
);

spl0 = svf1_left.eval_linearSVF_All(svf2_left.eval_linearSVF_All(spl0));
spl1 = svf1_right.eval_linearSVF_All(svf2_right.eval_linearSVF_All(spl1));
Note that the code is not optimized (and could be optimized) and I did not include parameter smoothing which you should do if you want to automate this filter at all.

If you don't feel the need to be able to morph this filter between modes, get rid of all that stuff, because then it's just costing you cycles .

The mapping from this 0-1 scale to Hz is:
Code:
.5 * srate * exp( (1-cutoff) * log(20/22050) )
P.S. This filter is also very well behaved when it comes to audio rate modulation. It's basically just cytomics' linear SVF.

P.P.S. If it _doesn't_ sound very similar, please show me some bits where it doesn't. Parts where you are unable to dial in a comparable sound. You can use the spectral analyzer in my repo to help with finding comparable settings. It has a diff mode.

Track 1: Sample
Track 2: Sample + Filter you want to test.
Send track 1 and 2 to track 3 on audio channels 1+2 and 3+4.

Put the spectral analyzer on track 3 and engage diff mode to see the difference spectrum. Enabling phase also shows you the phase differential. Note that if you are using a lowpass, the high frequencies may not be very reliable in the differential spectrum, since their levels are very low.
__________________
[Tracker Plugin: Thread|Github|Reapack] | [Routing Plugin: Thread|Reapack] | [More JSFX: Thread|Descriptions|Reapack]

Last edited by sai'ke; 03-04-2021 at 04:06 PM.
sai'ke is offline   Reply With Quote
Old 03-04-2021, 06:34 PM   #26
Phazma
Human being with feelings
 
Join Date: Jun 2019
Posts: 2,872
Default

Thanks for your effort so far, just gave it a quick try and this is surely the closest one that I tried.

Still, there are some differences in tone which become specially apparent when distorting the filtered sound.

I am not sure what to look out for in the analyzer (or how much difference is important difference), but here is a test-sample with high resonance and very heavy distortion afterwards, where the differences in character should become evident:

https://we.tl/t-DTWGgSpglv

I included the dry sample as well as both filters without distortion and with distortion afterwards. I matched cutoff and resonance by ear. It should be noticeable in the distorted sounds, that your filter has a more raspy character (as if there was an added low octave sawtooth) while the original one sounds somewhat rounder and more biased towards the higher harmonics.
Also notice how every note somehow "closes" with the original filter, giving it a more "moving" quality, while your filter keeps a rather static timbre.

I don't know whether this can give you some idea on what might be going on, to be able to do some more narrowed down tests?
Phazma is offline   Reply With Quote
Old 03-05-2021, 04:30 AM   #27
Phazma
Human being with feelings
 
Join Date: Jun 2019
Posts: 2,872
Default

I think I found out what it was!

When you observe the sample it has an asymmetric waveform. The original filter seems to compensate this while yours doesn't. I added a simple DC Filter at the input of your Filter and now it seems to sounds near identical!

I will do some more tests and let you now if I find anything else but I think the job is done.

If you accept donations I will gladly send a little something for the effort and for being so helpful!

EDIT:
Btw I think I actually won't be using the morphing. Better to keep it simple and efficient. However I have some difficulties to remove it without breaking something. Could you perhaps help me with that?
Here is my edited code with the DC Filter:
Code:
desc:4p linear SVF
tags: 4-pole linear SVF with gain compensation
author: Joep Vanlier
license: MIT
slider1:freq=1<0,1,.00001>Frequency
slider2:res=0<0,.97,.00001>Resonance
slider3:morph=0<0,1,.00001>Mode

in_pin:left input
in_pin:right input
out_pin:left output
out_pin:right output

@init
oversampling = 1;  // No oversampling, not needed as there is no distortion.
oversampling_ratio = 1 / oversampling;
//DCOFF
itm1=itm2=otm1=otm2=0;

function init_linearSVF_all(freq, res, morph)
  global(oversampling_ratio)
  local(frac)
  instance(f0, ic1eq, ic2eq, k, g, a1, a2, a3, m0, m1, m2, A)
  (
    f0 = exp( (1-freq) * log(20/22050) ) * oversampling_ratio;
    g = tan(.5 * $pi * f0);
    k = 2 - 2*res;
    a1 = 1/(1+g*(g+k));
    a2 = g*a1;
    a3 = g*a2;
    
    //      v0       v1   v2
    // LP =               v2
    // BP =          v1;
    // HP = v0 - k * v1 - v2;
    // BR = v0 -     v1;
    morph *= 4.0;
    frac = morph - floor(morph);
    morph < 1 ? (
      // LP to BP
      m0 = 0.0;
      m1 = frac;
      m2 = (1.0 - frac);
    ) : ( morph < 2 ) ? (
      // BP to HP
      m0 = frac;
      m1 = (1.0 - frac) - k * frac;
      m2 = -frac;
    ) : ( morph < 3 ) ? (
      // HP to BR
      m0 = (1.0 - frac) + frac;
      m1 = -k * (1.0 - frac) - frac;
      m2 = -(1.0 - frac);
    ) : (
      m0 = (1.0 - frac);
      m1 = -(1.0 - frac);
      m2 = frac;
    );
    
    A = sqrt(1-res*res);
    m0 *= A;
    m1 *= A;
    m2 *= A;
  );
  
function eval_linearSVF_All(v0)
  global()
  local(v1, v2, v3)
  instance(ic1eq, ic2eq, a1, a2, a3, m0, m1, m2, k)
  (
    v3 = v0 - ic2eq;
    v1 = a1 * ic1eq + a2 * v3;
    v2 = ic2eq + a2 * ic1eq + a3 * v3;
    ic1eq = 2.0 * v1 - ic1eq;
    ic2eq = 2.0 * v2 - ic2eq;
    (m0 * v0 + m1 * v1 + m2 * v2)
  );


function reset_linearSVF()
  global()
  local()
  instance(ic1eq, ic2eq, k, a1, a2, a3)
  (
    ic1eq = ic2eq = 0;  
  );
  
@slider

@block

@sample

otm1=0.999*otm1 + spl0 - itm1; itm1=spl0; spl0=otm1;
otm2=0.999*otm2 + spl1 - itm2; itm2=spl1; spl1=otm2;

s += 1;

(s%8 == 0) ? (
  svf1_left.init_linearSVF_all(freq, res, morph);
  svf2_left.init_linearSVF_all(freq, res, morph);
  svf1_right.init_linearSVF_all(freq, res, morph);
  svf2_right.init_linearSVF_all(freq, res, morph);
);

spl0 = svf1_left.eval_linearSVF_All(svf2_left.eval_linearSVF_All(spl0));
spl1 = svf1_right.eval_linearSVF_All(svf2_right.eval_linearSVF_All(spl1));

Last edited by Phazma; 03-05-2021 at 04:56 AM.
Phazma is offline   Reply With Quote
Old 03-05-2021, 03:01 PM   #28
sai'ke
Human being with feelings
 
sai'ke's Avatar
 
Join Date: Aug 2009
Location: NL
Posts: 1,453
Default

Code:
desc:4p linear SVF
tags: 4-pole linear SVF with gain compensation and DC blocker
author: Joep Vanlier and Phazma
license: MIT
slider1:freq=0.5<0,1,.00001>Frequency
slider2:res=0.5<0,.97,.00001>Resonance

in_pin:left input
in_pin:right input
out_pin:left output
out_pin:right output

@init
oversampling = 1;  // No oversampling, not needed as there is no distortion.
oversampling_ratio = 1 / oversampling;
//DCOFF
itm1=itm2=otm1=otm2=0;

function init_linearSVF_all(freq, res)
  global(oversampling_ratio)
  local(frac)
  instance(f0, ic1eq, ic2eq, k, g, a1, a2, a3, m2)
  (
    f0 = exp( (1-freq) * log(20/22050) ) * oversampling_ratio;
    g = tan(.5 * $pi * f0);
    k = 2 - 2*res;
    a1 = 1/(1+g*(g+k));
    a2 = g*a1;
    a3 = g*a2;
    m2 = 1 - res*res;
  );
  
function eval_linearSVF_All(v0)
  global()
  local(v1, v2, v3)
  instance(ic1eq, ic2eq, ic3eq, ic4eq, a1, a2, a3, m2)
  (
    v3 = v0 - ic2eq;
    v1 = a1 * ic1eq + a2 * v3;
    v2 = ic2eq + a2 * ic1eq + a3 * v3;
    ic1eq = 2.0 * v1 - ic1eq;
    ic2eq = 2.0 * v2 - ic2eq;
    
    v3 = v2 - ic4eq;
    v1 = a1 * ic3eq + a2 * v3;
    v2 = ic4eq + a2 * ic3eq + a3 * v3;
    ic3eq = 2.0 * v1 - ic3eq;
    ic4eq = 2.0 * v2 - ic4eq;
    
    m2 * v2
  );


function reset_linearSVF()
  global()
  local()
  instance(ic1eq, ic2eq, k, a1, a2, a3)
  (
    ic1eq = ic2eq = 0;  
  );
  
@slider

@block

@sample
otm1=0.999*otm1 + spl0 - itm1; itm1=spl0; spl0=otm1;
otm2=0.999*otm2 + spl1 - itm2; itm2=spl1; spl1=otm2;

s += 1;
(s%8 == 0) ? (
  svf_left.init_linearSVF_all(freq, res);
  svf_right.init_linearSVF_all(freq, res);
);

spl0 = svf_left.eval_linearSVF_All(spl0);
spl1 = svf_right.eval_linearSVF_All(spl1);
Here you go. Merging both steps in one filter should cut the cost a bit since you only compute the coefficients once. You also don't need to do the sqrt anymore (which is a somewhat expensive operation). And the morphing can of course go.

Note that the tan is the most expensive operation in this thing at the moment. Currently it's only done for every 8th sample, but you have to see what you can get away with for your purposes. If you modulate the filter very fast, that may not be acceptable.

Also, smooth the slider changes if you use this in a plugin. It will sound much better
__________________
[Tracker Plugin: Thread|Github|Reapack] | [Routing Plugin: Thread|Reapack] | [More JSFX: Thread|Descriptions|Reapack]
sai'ke is offline   Reply With Quote
Old 03-05-2021, 06:21 PM   #29
Phazma
Human being with feelings
 
Join Date: Jun 2019
Posts: 2,872
Default

Thank you a lot!

I have already integrated the filter into my plugin with slider smoothing.
I am planning further down the line to add LFO and maybe Midi triggered envelopes (if I am able to do it) and then I will see how it works with faster modulations. For now I have tried some automations and it seems to work great.

I have also tried to change the cutoffslider to show Hz instead of 0-1 by using your formula but I had no luck (unless I messed something up in coding). What I have done is named the slider "cutoffslider", given it a range of 20-20000 and defined
Code:
cutoff=0.5 * srate * exp( (1-cutoffslider) * log(20/22050) );
and put "cutoff" in all places where your code has "freq". Have I done something wrong?

Also another question, not directly related to the filter.
I am using a custom UI for my effect (created with this: https://geraintluff.github.io/jsfx-u...nerate-ui.html). In my plugin, as well as in js plugins with UI by some other people, when I move a slider and press the space-bar to start playback, the slider stops moving. This is very annoying when re-triggering playback while tweaking a slider.
I have seen that various of your plugins also use GUIs and the controls are always responsive, even when starting/stopping playback. Are you doing something specific to make this possible? Is there a way to specify inside the code to ignore the spacebar?
Phazma is offline   Reply With Quote
Old 03-06-2021, 06:11 AM   #30
sai'ke
Human being with feelings
 
sai'ke's Avatar
 
Join Date: Aug 2009
Location: NL
Posts: 1,453
Default

Quote:
Originally Posted by Phazma View Post
Thank you a lot!

I have already integrated the filter into my plugin with slider smoothing.
I am planning further down the line to add LFO and maybe Midi triggered envelopes (if I am able to do it) and then I will see how it works with faster modulations. For now I have tried some automations and it seems to work great.

I have also tried to change the cutoffslider to show Hz instead of 0-1 by using your formula but I had no luck (unless I messed something up in coding). What I have done is named the slider "cutoffslider", given it a range of 20-20000 and defined
Code:
cutoff=0.5 * srate * exp( (1-cutoffslider) * log(20/22050) );
and put "cutoff" in all places where your code has "freq". Have I done something wrong?
Are you sure you want a linear slider? Generally logarithmic sliders are much more useful. Since JSFX doesn't support logarithmic sliders natively, I'd highly recommend using the 0-1 on the actual slider mapping, and calculating and displaying the Hz value in your @gfx loop. Otherwise automation envelopes will become a pain in the butt.

The equation I gave you is to calculate from the 0-1 range to Hz. So you'd want the inverse for what you want to do:
Code:
zero_to_one = 1 - log(cutoff_hz / (.5*srate)) / log(20/22050);
Quote:
Originally Posted by Phazma View Post
Also another question, not directly related to the filter.
I am using a custom UI for my effect (created with this: https://geraintluff.github.io/jsfx-u...nerate-ui.html). In my plugin, as well as in js plugins with UI by some other people, when I move a slider and press the space-bar to start playback, the slider stops moving. This is very annoying when re-triggering playback while tweaking a slider.
I have seen that various of your plugins also use GUIs and the controls are always responsive, even when starting/stopping playback. Are you doing something specific to make this possible? Is there a way to specify inside the code to ignore the spacebar?
I'm not familiar with Geraint's GUI toolkit, but maybe it resets or reconstruct some input state in @init? I don't think ignoring the space bar is a good approach for fixing this, nor do I know whether it is possible. It'd be better to find out where that state is being overridden and don't reset it.
__________________
[Tracker Plugin: Thread|Github|Reapack] | [Routing Plugin: Thread|Reapack] | [More JSFX: Thread|Descriptions|Reapack]
sai'ke is offline   Reply With Quote
Old 03-06-2021, 09:36 AM   #31
Phazma
Human being with feelings
 
Join Date: Jun 2019
Posts: 2,872
Default

Yes that's what I wanted, showing Hertz on the GUI but having a logarithmic slider response.
I was now able to get the GUI to show Hertz but automation did not work well as you said.

I need some more time to wrap my head around all the GUI stuff in general and see how I can get things done. Now I don't have much time to dedicate to this but I will report back in some days whether I get things to work or still need some help. Big thank you so far!
Phazma is offline   Reply With Quote
Old 03-07-2021, 07:42 AM   #32
sai'ke
Human being with feelings
 
sai'ke's Avatar
 
Join Date: Aug 2009
Location: NL
Posts: 1,453
Default

Automation didn't work well?

And yeah, JSFX UIs definitely have their own set of challenges. I'm curious to see what you come up with. But yes, no rush
__________________
[Tracker Plugin: Thread|Github|Reapack] | [Routing Plugin: Thread|Reapack] | [More JSFX: Thread|Descriptions|Reapack]
sai'ke is offline   Reply With Quote
Old 12-20-2021, 04:24 AM   #33
Phazma
Human being with feelings
 
Join Date: Jun 2019
Posts: 2,872
Default

It's been a long time but I think I have finally a little time to dedicate to this again.

Saike, are you still willing to help me?

I was now able to solve the GUI-knob freezing problem (just had to put "ext_noinit = 1;" into my @init section) and I am also able to have a logarithmic cutoff knob on the GUI that shows Hz, but when I automate that knob the slider response is still linear, which obviously isn't that useful:



I know that the best approach would be to have the actual slider value be 0-1 and map that somehow to control the GUI knob which displays Hz, but whatever I tried in some way or the other didn't work.

Once I get this done, if it is ok with you I might ask for help implementing a Cutoff LFO (similar to the one in FM Filter 2 but with Midi note trigger function) and analyzing the distortion curve of a specific plugin (which I want to implement as well) so that a similar algorithm maybe can be identified.

All other features I hope I will be able to add without needing help. Currently trying to learn and understand more of how buffering and the @block section work as I am having some weird GUI issues when trying to implement a transparent input limiter.
Phazma is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 11:22 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.