Old 11-06-2018, 07:06 AM   #1
Revoan
Human being with feelings
 
Join Date: Oct 2018
Posts: 4
Default JSFX Plugin Creation (Help): Low Pass Filter

Hi there, I'm fairly new to the forum and am currently in the midst of preparing a jsfx plugin for a module that I am studying. I've never had any experience with creating a plugin or coding in general and I'm still a little confused at what each line of code does and I would like to seek some assistance in working this out.

From what I understand at the @init section, that is where we set up our variables for the plugin and @sample is where the input samples are then calculated and looped. spl0 and spl1 are the left and right channel outputs respectively. (But please correct me if I'm wrong cause I still feel like I'm missing a lot of stuff)


So far, I have come up with this code:

desc: First order low-pass filter

slider1:0<-120,6,0.1>Input gain

@init
bpos=0;
ip0=0; // initialise our variables to 0, so they are ready to use first time around the sample loop
ip1=0;
prev0=0;
prev1=0;

@slider

@block

@sample
ip0 = (10^(slider1/20))*spl0; // use slider position (dB scale) to control input level
ip1 = (10^(slider1/20))*spl1;
spl0=0.5*(ip0+prev0); // first-order low pass filter equation, add current sample to previous
spl1=0.5*(ip1+prev1);
prev0 = ip0; // store current sample so that next time around the loop it is available us as the previous sample
prev1 = ip1;

After the tutorial session with my lecturer I have a better understanding of how the code works but I was then given an exercise to progress with this.

I am supposed to implement this equation into the code:

Output[n] = (input[n]+input[n-1]+input[n-2])/3

Do I insert its as:

spl0 = (0.5*(ip0+prev0)+0.5((ip0+prev0-1)+0.5*(ip0+prev0-2))/3

I'm sure I'm doing something wrong but any piece of advice would be great. Thanks again
Revoan is offline   Reply With Quote
Old 11-06-2018, 09:33 AM   #2
TBProAudio
Human being with feelings
 
TBProAudio's Avatar
 
Join Date: May 2014
Location: Germany
Posts: 433
Default

Quote:
Originally Posted by Revoan View Post

Output[n] = (input[n]+input[n-1]+input[n-2])/3

Do I insert its as:

spl0 = (0.5*(ip0+prev0)+0.5((ip0+prev0-1)+0.5*(ip0+prev0-2))/3

No, this will not work. "prev0-1" simply subtracts 1 from prev0.


Have a look. Maybe it helps:


Code:
@init
bpos=0;
ip0=0; // initialise our variables to 0, so they are ready to use first time around the sample loop
ip1=0;

prev0_1=0;    // Init n-1
prev1_1=0;
prev0_2=0;    // Init n-2
prev1_2=0;

@slider

@block

@sample
ip0 = (10^(slider1/20))*spl0; // use slider position (dB scale) to control input level
ip1 = (10^(slider1/20))*spl1;

spl0=1/3*(ip0+prev0_l+prev0_2); // use of n, n-1 and n-2
spl1=1/3*(ip1+prev0_l+prev1_l);

prev0_2=prev0_l; // store n - 2
prev1_2=prev1_2;
prev0_l = ip0;      // store n - 1
prev1_l = ip1;
Please note that the first and second call to function "sample" work with null pre filled data. The 3rd call and onwards uses data from spl.
__________________
www.tb-software.com/TBProAudio

Last edited by TBProAudio; 11-06-2018 at 09:39 AM.
TBProAudio is offline   Reply With Quote
Old 11-06-2018, 10:40 AM   #3
Eddy
Human being with feelings
 
Join Date: Jun 2017
Posts: 206
Default

Also you are making a moving average filter so that's the reason you use the 0.5 in the first example - you are taking the average of two values. But in the second new version you are taking the average over 3 values so you use the 1/3, but you don't need the 0.5 multiplier anymore
Eddy is offline   Reply With Quote
Old 11-06-2018, 10:48 AM   #4
TBProAudio
Human being with feelings
 
TBProAudio's Avatar
 
Join Date: May 2014
Location: Germany
Posts: 433
Default

Quote:
Originally Posted by Eddy View Post
Also you are making a moving average filter so that's the reason you use the 0.5 in the first example - you are taking the average of two values. But in the second new version you are taking the average over 3 values so you use the 1/3, but you don't need the 0.5 multiplier anymore

Thanks for pointing this out. I missed this, sorry :-(
__________________
www.tb-software.com/TBProAudio
TBProAudio is offline   Reply With Quote
Old 11-07-2018, 10:29 AM   #5
Revoan
Human being with feelings
 
Join Date: Oct 2018
Posts: 4
Default

Hi TBProAudio,

Thank you for your help. Its much appreciated. And yes, the code version you provided makes a little bit more sense than what I tried to attempt. However, after entering your code, the plugin works but I would like to take it a step further. So I looked at the default JSFX lowpass filter plugin included in reaper and was wondering if anyone could explain to me why the code is written in such a way? I understand that at the slider 1 and slider 2 options are for us to determine what the slider does in the plugin.

Code:
// This effect Copyright (C) 2004 and later Cockos Incorporated
// License: GPL - http://www.gnu.org/licenses/gpl.html
//
//Addl. Modification by Levi Wilbert

desc: low pass filter

slider1:8<0,10>frequency (Exp(0=20Hz, 10=20480Hz))
slider2:0.2<0,1>size (0=sharp, 1=dull)

@slider
  damp=0.01+slider2*20;
  c = 1/tan($pi*(20*pow(2, slider1))/srate);
  fk = 1 / (1 + c*(c+damp));
  fa1 = 2 * (1 - c*c) * fk;
  fa0 = (1 + c*(c-damp)) * fk;
  //damp!=oldamp ? fd1l=fd2l=fd1r=fd2r=0;
  oldamp=damp;

@sample

fd0l = (fk*spl0) - (fa1*fd1l) - (fa0*fd2l);
fd0r = (fk*spl1) - (fa1*fd1r) - (fa0*fd2r);

spl0 = fd0l + fd1l + fd1l + fd2l;
spl1 = fd0r + fd1r + fd1r + fd2r;

fd2l = fd1l;
fd2r = fd1r;

fd1l = fd0l;
fd1r = fd0r;
*edited to insert code straight into the post*

Especially for what happens at:

@slider - I am still unclear as to how the equation works. Is this the standard equation one would use to create commands for a low pass filter? I don't quite understand what damp does but I'm guessing its related to slider 2.

@sample - Please do correct me if I'm wrong but from what I can observe and understand, the variables we set up in the slider section is then implemented into an equation in this section to create the low pass filter effect?

I understand I'm probably asking a lot of basic questions but I'm still trying to wrap my head around this jsfx coding. Thanks again
Attached Files
File Type: txt reaper default js low pass filter plugin.txt (747 Bytes, 3 views)
Revoan is offline   Reply With Quote
Old 11-07-2018, 10:50 AM   #6
ashcat_lt
Human being with feelings
 
Join Date: Dec 2012
Posts: 3,419
Default

I don't understand that equation well enough to explain it to you. It is apparently what you need to do to generate coefficients that will make the type of filter that's implemented here. There are other filter types which can be much different.

I CAN tell you, though, that those coefficients never change unless you move a slider, and only need to be calculated when they change, so doing it for every sample we process is wasting CPU ticks. That's why they put that part in @sample. In your code, you should do the same with the db > ratio calculation (10^(slider1/20)). Store it in a variable in the @slider section and use that in @sample.
ashcat_lt is offline   Reply With Quote
Old 11-07-2018, 11:34 AM   #7
Revoan
Human being with feelings
 
Join Date: Oct 2018
Posts: 4
Default

Quote:
Originally Posted by ashcat_lt View Post
I don't understand that equation well enough to explain it to you. It is apparently what you need to do to generate coefficients that will make the type of filter that's implemented here. There are other filter types which can be much different.

I CAN tell you, though, that those coefficients never change unless you move a slider, and only need to be calculated when they change, so doing it for every sample we process is wasting CPU ticks. That's why they put that part in @sample. In your code, you should do the same with the db > ratio calculation (10^(slider1/20)). Store it in a variable in the @slider section and use that in @sample.
Hi ashcat_lt,

Did you mean something like this?

Code:
@init
bpos=0;
ip0=0; // initialise our variables to 0, so they are ready to use first time around the sample loop
ip1=0;

prev0_1=0;    // Init n-1
prev1_1=0;
prev0_2=0;    // Init n-2
prev1_2=0;

@slider

ip0 = (10^(slider1/20))*spl0; // use slider position (dB scale) to control input level
ip1 = (10^(slider1/20))*spl1;

@block

@sample

spl0=1/3*(ip0+prev0_l+prev0_2); // use of n, n-1 and n-2
spl1=1/3*(ip1+prev0_l+prev1_l);

prev0_2=prev0_l; // store n - 2
prev1_2=prev1_2;
prev0_l = ip0;      // store n - 1
prev1_l = ip1;
Revoan is offline   Reply With Quote
Old 11-07-2018, 12:39 PM   #8
ashcat_lt
Human being with feelings
 
Join Date: Dec 2012
Posts: 3,419
Default

No.

First off you're eventually going to have to actually define slider1, but...

@slider

gain = 10^(slider1/20);

@sample

ip0 = gain * spl0;
ip1 = gain * spl1;
...
ashcat_lt is offline   Reply With Quote
Old 11-09-2018, 05:01 AM   #9
Revoan
Human being with feelings
 
Join Date: Oct 2018
Posts: 4
Default

Okay, so I've had some time to finally get back to work on the plugin again. With the current code, I've done some tests in Reaper using whitenoise and notice that theres actually a dip in the frequencies above 15kHz when turning the plugin on.

https://imgur.com/RYij8OO (Plugin off)

https://imgur.com/gO7ATcb (Plugin On)

So I guess one could say that the plugin is working? I'd like to add another slider to somehow control the frequency cut off, probably say from 4000Hz and above but I'm not sure how to go about that.
Revoan 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 01:10 AM.


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