COCKOS
CONFEDERATED FORUMS
Cockos : REAPER : NINJAM : Forums
Forum Home : Register : FAQ : Members List : Search :
Old 08-19-2015, 10:11 PM   #1
Tired_Joe
Human being with feelings
 
Join Date: Apr 2015
Posts: 55
Default Equalizer or Filter Class

Hi,

I am trying to implement an shelving EQ in my plugin. I built a class with this information:
http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt

and some c code of this website:
http://www-users.cs.york.ac.uk/~fisher/mkfilter/

I tried a lot and the low and hicut seems to work very well. But the shelving EQ produce sometimes horroble noise. I figured out, that the is only there, if I open the project(Reaper/StudioOne) again.

Is there an easy to use filter class in WDL-OL? I donīt want to build the best sounding EQ, only very basic stuff.

Thanks
Tired_Joe is offline   Reply With Quote
Old 08-19-2015, 11:15 PM   #2
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,653
Default

Not AFAIK.

But the cookbook filters generally work pretty well, so why not post your code, so we can fix it?
Tale is offline   Reply With Quote
Old 08-20-2015, 08:05 PM   #3
Tired_Joe
Human being with feelings
 
Join Date: Apr 2015
Posts: 55
Default

Sorry, you are right. Code might be the thing to solve the problem.

First my EQ Class. I know that this is not the best way of writing classes, but I am still learning C++ ... Itīs not trivial for a sound engineer.

clEQ.h

Code:
class HiShelvClass
{  
private:
	int n; 
	double pi;
	double A;
	
	double x[3];
	double y[3];
	
	double w0; 
	double alpha;  
	
	double  a0; 
	double  a1; 
	double  a2; 
	double	b0; 
	double	b1; 
	double  b2; 

public:
	double dBGain;	// Cut or Boost in dB
	double Fs;		// Samplefrequency 
	double f0;		// Frequency
	double S;		// Slope
	
	void Calc();		// Calculation 
	double Process(double SamplesIn); 
};
clEQ.cpp
Code:
#include "clEQ.h"
#include <math.h>
using namespace std;

void HiShelvClass::Calc()		// Calculation for the Process function
{
	pi = (2*acos(0.0));
	n = 2;  
	A = pow (10., dBGain/40.);
	
	
 	w0 = 2.*pi*f0/Fs;
	alpha = sin(w0)/2 *sqrt( (A + 1/A)*(1/S - 1) + 2 );
	
	b0 =    A*( (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha );
	b1 = -2*A*( (A-1) + (A+1)*cos(w0)                   );
	b2 =    A*( (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha );
	a0 =        (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha;
	a1 =    2*( (A-1) - (A+1)*cos(w0)                   );
	a2 =        (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha;
}      

double HiShelvClass::Process(double SamplesIn)
{
	 n= 2;
	
	 x[n-2] = x[n-1];		x[n-1] = x[n];
	 x[n]= SamplesIn;
	 y[n-2] = y[n-1];	    y[n-1] = y[n];
	 y[n] = (b0/a0)*x[n] + (b1/a0)*x[n-1] + (b2/a0)*x[n-2]- (a1/a0)*y[n-1] - (a2/a0)*y[n-2];
	 
	 return y[n];
}

I create a HiShelvClass object in in my plugin header file:
Code:
….
private:
  
  double mEQGain;
  double mEQFrequency;
  double mEQOffset;
  double mEQSlope;

  HiShelvClass Hi_Shelv_EQ;		// Creating the EQ object
};
Then I update all the EQ parameters in switch (paramIdx)
Code:
 switch (paramIdx)
  {
     
    case kEQGain:
      mEQGain = GetParam(kEQGain)->Value();;
 	Hi_Shelv_EQ.dBGain = mEQGain;
  	Hi_Shelv_EQ.Calc();
      break;

      mEQFrequency = GetParam(mEQFrequency)->Value();;
  	Hi_Shelv_EQ.f0 = mEQFrequency;
  	Hi_Shelv_EQ.Calc();
      break;
	
	etc.
ProcessDoubleReplacing

Code:
for (int s = 0; s < nFrames; s++)  
  {
        out1[s] = Hi_Shelv_EQ.Process(in1[s]);
  }

Sometimes everything works as expected and sometimes I can hear no signal. Sometimes it happens when I reopen the project and sometimes when I use the first instance of the plugin. Multiple instances are not the problem I think.

I donīt know if the eq process function is the right one. I am not shure where I found these code. Because I was not able to translate everything from EQCookBook into proper c++ code.

Code:
double HiShelvClass::Process(double SamplesIn)
{
	 n= 2;
	
	 x[n-2] = x[n-1];		x[n-1] = x[n];
	 x[n]= SamplesIn;
	 y[n-2] = y[n-1];	    y[n-1] = y[n];
	 y[n] = (b0/a0)*x[n] + (b1/a0)*x[n-1] + (b2/a0)*x[n-2]- (a1/a0)*y[n-1] - (a2/a0)*y[n-2];
	 
	 return y[n];
}

Last edited by Tired_Joe; 08-20-2015 at 08:23 PM.
Tired_Joe is offline   Reply With Quote
Old 08-21-2015, 12:35 AM   #4
Tired_Joe
Human being with feelings
 
Join Date: Apr 2015
Posts: 55
Default

I think I fixed the problem. My short tests caused no problem.

I had to set all buffer to 0.0
Tired_Joe is offline   Reply With Quote
Old 08-21-2015, 01:01 AM   #5
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,653
Default

This is basically looking good.

Quote:
Originally Posted by Tired_Joe View Post
Sometimes everything works as expected and sometimes I can hear no signal. Sometimes it happens when I reopen the project and sometimes when I use the first instance of the plugin. Multiple instances are not the problem I think.
I think the problem is that you have uninitialised values, e.g. the first time OnParamChange() is called it will set e.g. dBGain, but then f0 is still uninitialised. This means that maybe it is 0, but it could just as well be +inf or another invalid value. The same goes for x[] and y[], they need to be initialised, I guess to zeros.

So I would suggest adding a constructor to your class i.e.:

Code:
// Constructor
HiShelvClass::HiShelvClass():
  // Initialise member variables.
  dBGain(0), Fs(44100), f0(1), S(1)
{
  // Initialise arrays.
  for (int i = 0; i < 3; ++i)
  {
    x[i] = y[i] = 0;
  }
}
Quote:
Originally Posted by Tired_Joe View Post
I donīt know if the eq process function is the right one. I am not shure where I found these code. Because I was not able to translate everything from EQCookBook into proper c++ code.
Well, actually it looks good. Note that the processing function for cookbook filters is always the same, regardless of the filter type.

Do note there are things I would probably do different. E.g. I would use the M_PI constant from <math.h> rather than calculating it on the fly. And I would only use member variables for values that I need in two different methods; variables that I need only I would declare locally. And I probably would optimise away a0. And test for denormals, etc.
Tale is offline   Reply With Quote
Old 08-21-2015, 01:02 AM   #6
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,653
Default

Quote:
Originally Posted by Tired_Joe View Post
I had to set all buffer to 0.0
Right! And the same goes for some of the member variables (see my answer above).
Tale is offline   Reply With Quote
Old 08-24-2015, 07:27 PM   #7
Tired_Joe
Human being with feelings
 
Join Date: Apr 2015
Posts: 55
Default

Thanks a lot.

Everything works fine.

But I recognized that my Plugin uses a lot more CPU (10-12%) if there is no region on the track (Reaper) or the sequencer is not playing.

During "normal" processing with audio data the plugin (4 Equalizers) uses only 1% of CPU, thats really good. (I use a Macbook 2007 with 10.6.8)


Do someone knows whats going wrong?
Tired_Joe is offline   Reply With Quote
Old 08-24-2015, 11:19 PM   #8
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,653
Default

Quote:
Originally Posted by Tired_Joe View Post
Do someone knows whats going wrong?
Denormals? If so, then this will probably fix it:

Code:
#include "WDL/denormal.h"

...
y[n] = (b0/a0)*x[n] + (b1/a0)*x[n-1] + (b2/a0)*x[n-2]- (a1/a0)*y[n-1] - (a2/a0)*y[n-2];
denormal_fix(&y[n]); // Add this line
Tale is offline   Reply With Quote
Old 08-24-2015, 11:58 PM   #9
Tired_Joe
Human being with feelings
 
Join Date: Apr 2015
Posts: 55
Default

Thanks so much. This helps !
Tired_Joe 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:21 PM.


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