148 lines · 3.5 KB · C++
RawDownload
/*
	RackAFX(TM)
	Applications Programming Interface
	Derived Class Object Implementation
*/


#include "VADiodeLadderFilter.h"
#include <math.h>
#define  pi 3.1415926535897932384626433832795

CVADiodeLadderFilter::CVADiodeLadderFilter()
{

	// Finish initializations here
	m_dGAMMA = 0.0;
	m_dK = 0.0;

	// our feedback S values (global)
	m_dSG1 = 0.0; 
	m_dSG2 = 0.0;
	m_dSG3 = 0.0; 
	m_dSG4 = 0.0; 

	// Filter coeffs that are constant
	// set a0s
	m_LPF1.m_da0 = 1.0;
	m_LPF2.m_da0 = 0.5;
	m_LPF3.m_da0 = 0.5;
	m_LPF4.m_da0 = 0.5;

	// last LPF has no feedback path
	m_LPF4.m_dGamma = 1.0;
	m_LPF4.m_dDelta = 0.0;
	m_LPF4.m_dEpsilon = 0.0;
	m_LPF4.setFeedback(0.0);

}

CVADiodeLadderFilter::~CVADiodeLadderFilter(void)
{

}

bool CVADiodeLadderFilter::prepareForPlay(float fs)
{

	// this flushes all storage registers in filters including feedback register
	reset();

    m_nSampleRate = fs;
    m_LPF1.m_dSampleRate = m_nSampleRate;
    m_LPF2.m_dSampleRate = m_nSampleRate;
    m_LPF3.m_dSampleRate = m_nSampleRate;
    m_LPF4.m_dSampleRate = m_nSampleRate;

	// set the initial coeffs
	updateFilter();

	return true;
}

void CVADiodeLadderFilter::updateFilter()
{
	// calculate alphas
	double wd = 2*pi*m_dFc;          
	double T  = 1/(float)m_nSampleRate;             
	double wa = (2/T)*tan(wd*T/2); 
	double g = wa*T/2;  

	// Big G's
	double G1, G2, G3, G4;

	G4 = 0.5*g/(1.0 + g);
	G3 = 0.5*g/(1.0 + g - 0.5*g*G4);
	G2 = 0.5*g/(1.0 + g - 0.5*g*G3);
	G1 = g/(1.0 + g - g*G2);
	
	// our big G value GAMMA
	m_dGAMMA = G4*G3*G2*G1;
	
	m_dSG1 =  G4*G3*G2; 
	m_dSG2 =  G4*G3; 
	m_dSG3 =  G4; 
	m_dSG4 =  1.0; 

	// set alphas
	m_LPF1.m_dAlpha = g/(1.0 + g);
	m_LPF2.m_dAlpha = g/(1.0 + g);
	m_LPF3.m_dAlpha = g/(1.0 + g);
	m_LPF4.m_dAlpha = g/(1.0 + g);

	// set betas
	m_LPF1.m_dBeta = 1.0/(1.0 + g - g*G2);
	m_LPF2.m_dBeta = 1.0/(1.0 + g - 0.5*g*G3);
	m_LPF3.m_dBeta = 1.0/(1.0 + g - 0.5*g*G4);
	m_LPF4.m_dBeta = 1.0/(1.0 + g);
	
	// set gammas
	m_LPF1.m_dGamma = 1.0 + G1*G2;
	m_LPF2.m_dGamma = 1.0 + G2*G3;
	m_LPF3.m_dGamma = 1.0 + G3*G4;
	// m_LPF4.m_dGamma = 1.0; // constant - done in constructor
	
	// set deltas
	m_LPF1.m_dDelta = g;
	m_LPF2.m_dDelta = 0.5*g;
	m_LPF3.m_dDelta = 0.5*g;
	// m_LPF4.m_dDelta = 0.0; // constant - done in constructor

	// set epsilons
	m_LPF1.m_dEpsilon = G2;
	m_LPF2.m_dEpsilon = G3;
	m_LPF3.m_dEpsilon = G4;
	// m_LPF4.m_dEpsilon = 0.0; // constant - done in constructor
}

// do the filter
double CVADiodeLadderFilter::doFilter(double xn)
{
//	m_LPF4.setFeedback(0.0); // constant - done in constructor
	m_LPF3.setFeedback(m_LPF4.getFeedbackOutput());
	m_LPF2.setFeedback(m_LPF3.getFeedbackOutput());
	m_LPF1.setFeedback(m_LPF2.getFeedbackOutput());

	// form input
	double SIGMA = m_dSG1*m_LPF1.getFeedbackOutput() + 
				   m_dSG2*m_LPF2.getFeedbackOutput() +
				   m_dSG3*m_LPF3.getFeedbackOutput() +
				   m_dSG4*m_LPF4.getFeedbackOutput();

	// "cheap" nonlinear model; just process input
	if(m_NonLinearProcessing == ON)
	{
		// the 1/tanh(sat) is to normalize the function so x = [-1..+1] --> y = [-1..+1]
		// Normalized Version
		if(m_uNLPType == NORM)
			xn = (1.0/tanh(m_dSaturation))*tanh(m_dSaturation*xn);
		else
			xn = tanh(m_dSaturation*xn);
	}

	// form the input to the loop
	double un = (xn - m_dK*SIGMA)/(1 + m_dK*m_dGAMMA);

	// cascade of series filters
	return m_LPF4.doFilter(m_LPF3.doFilter(m_LPF2.doFilter(m_LPF1.doFilter(un))));
}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t