view BassPedalRackPlugin/PluginProcessor.cpp @ 2:13ec2fa02a26 tip

(none)
author Yannick JACOB <y.jacob@se12.qmul.ac.uk>
date Tue, 03 Sep 2013 15:33:42 +0100
parents 2cd427e000b0
children
line wrap: on
line source
/*
  ==============================================================================

    This file was auto-generated!

    It contains the basic startup code for a Juce application.

  ==============================================================================
*/

#include "PluginProcessor.h"
#include "PluginEditor.h"
#include "filter.h"


//==============================================================================
BassPedalRackProcessor::BassPedalRackProcessor()
{
    // Set default values:
    
	gain_ = 1.0;  //Orignal volume set to one
	index_ = 1.0; //Index is one by default
	mix_ = 0.5;  //as much low than high
	gain1_ = 1.0;  //fundamental =1
	gain2_ = 0.0;  //no other distortion
	gain3_ = 0.0;
	gain4_ = 0.0;
	gain5_ = 0.0;
	gain6_ = 0.0;
	gain7_ = 0.0;
	gain8_ = 0.0;
	gain9_ = 0.0;
	
	//neutral tone stack (even is it is not strictly an allpass filter)
	trebleGain_ = 0.5; 
	bassGain_ = 0.5;
	midGain_ = 0.5;
	//filterLength
	filterLength_ = 151;

	toneStack_ = true;
	shaper_ = false;

	//circular buffers initialisation
	currInd_ =0;
	for (int i = 0; i < 3; i++)
	{
		memIn_[i] = 0;
		memOut_[i] = 0;
	}
	
	for (int i = 0; i < 6; i++)
	{
		tonStackIn_[i] = 0;
		tonStackIn_[i] = 0;
	}

	
	for (int i = 0; i < 2*filterLength_; i++)
		inputMem_[i] = 0;

	
	//Distortion coefficients initialisation	
	RC_ = 6.25*pow((double)10,-6);
	RC2_ = RC_*RC_;
	RC3_ = RC2_*RC_;

	//allpass filter
	highCut_ = 0;
	lowCut_ = 0;
	
    lastUIWidth_ = 550;
    lastUIHeight_ = 350;

	//initialise distortion
	coeffs_[9] = 256*gain9_;
	coeffs_[8] = 128*gain8_;
	coeffs_[7] = -576*gain9_ + 64*gain7_;
	coeffs_[6] = -256*gain8_ + 32*gain6_;
	coeffs_[5] = 432*gain9_ -112*gain7_ + 16*gain5_;
	coeffs_[4] = 160*gain8_ -48*gain6_ + 8*gain4_;
	coeffs_[3] = -120*gain9_ + 56*gain7_ -20*gain5_ + 4*gain3_;
	coeffs_[2] = -32*gain8_ + 18*gain6_ -8*gain4_ + 2*gain2_;
	coeffs_[1] = 9*gain9_ -7*gain7_ + 5*gain5_ -3*gain3_ + gain1_;
	coeffs_[0] = gain8_ - gain6_ + gain4_ - gain2_;
}

BassPedalRackProcessor::~BassPedalRackProcessor()
{
}

//==============================================================================
const String BassPedalRackProcessor::getName() const
{
    return JucePlugin_Name;
}

int BassPedalRackProcessor::getNumParameters()
{
    return kNumParameters;
}

float BassPedalRackProcessor::getParameter (int index)
{
    // This method will be called by the host, probably on the audio thread, so
    // it's absolutely time-critical. Don't use critical sections or anything
    // UI-related, or anything at all that may block in any way!
    switch (index)
    {
		case kMixParam:     return mix_;
		case kHighCutParam:     return (float)highCut_;
		case kIndexParam:     return index_;
		case kGainParam:     return gain_;
		case kLowCutParam:     return (float)lowCut_;
		case kGainLowParam:     return bassGain_;
		case kGainMidParam:     return midGain_;
		case kGainTreParam:     return trebleGain_;
		case kGain1Param:		return gain1_;
		case kGain2Param:		return gain2_;
		case kGain3Param:		return gain3_;
		case kGain4Param:		return gain4_;
		case kGain5Param:		return gain5_;
		case kGain6Param:		return gain6_;
		case kGain7Param:		return gain7_;
		case kGain8Param:		return gain8_;
		case kGain9Param:		return gain9_;
        default:               return 0.0f;
    }
}

void BassPedalRackProcessor::setParameter (int index, float newValue)
{
    // This method will be called by the host, probably on the audio thread, so
    // it's absolutely time-critical. Don't use critical sections or anything
    // UI-related, or anything at all that may block in any way!
    switch (index)
    {
       case kMixParam:
            mix_ = newValue;
            break;
		case kHighCutParam:
            highCut_ = (int)newValue;
            break;
		case kIndexParam:
            index_ = newValue;
            break;
		case kGainParam:
            gain_ = newValue;
            break;
		case kLowCutParam:
            lowCut_ = (int)newValue;
            break;
		case kGainTreParam:
            trebleGain_ = newValue;
			changeToneStack();
            break;
		case kGainLowParam:
            bassGain_ = newValue;
			changeToneStack();
            break;
		case kGainMidParam:
            midGain_ = newValue;
			changeToneStack();
            break;
        case kGain1Param:
            gain1_ = newValue;
			changeCoefficients(kGain1Param);
            break;
        case kGain2Param:
            gain2_ = newValue;
			changeCoefficients(kGain2Param);
            break;
        case kGain3Param:
            gain3_ = newValue;
			changeCoefficients(kGain3Param);
            break;
        case kGain4Param:
            gain4_ = newValue;
			changeCoefficients(kGain4Param);
            break;
        case kGain5Param:
            gain5_ = newValue;
			changeCoefficients(kGain5Param);
            break;
        case kGain6Param:
            gain6_ = newValue;
			changeCoefficients(kGain6Param);
            break;
        case kGain7Param:
            gain7_ = newValue;
			changeCoefficients(kGain7Param);
            break;
        case kGain8Param:
            gain8_ = newValue;
			changeCoefficients(kGain8Param);
            break;
		case kGain9Param:
            gain9_ = newValue;
			changeCoefficients(kGain9Param);
            break;
		default:
            break;
    }
}

const String BassPedalRackProcessor::getParameterName (int index)
{
    switch (index)
    {
		case kMixParam:     return "mix";
		case kLowCutParam:     return "lowcut";
		case kIndexParam:     return "index";
		case kGainParam:     return "gain";
		case kHighCutParam:     return "highcut";
		case kGainLowParam:     return "low";
		case kGainMidParam:     return "mid";
		case kGainTreParam:     return "treble";
		case kGain1Param:     return "gain1";
		case kGain2Param:     return "gain2";
		case kGain3Param:     return "gain3";
		case kGain4Param:     return "gain4";
		case kGain5Param:     return "gain5";
		case kGain6Param:     return "gain6";
		case kGain7Param:     return "gain7";
		case kGain8Param:     return "gain8";
		case kGain9Param:     return "gain9";
        default:               break;
    }
    
    return String::empty;
}

const String BassPedalRackProcessor::getParameterText (int index)
{
    return String (getParameter (index), 2);
}

const String BassPedalRackProcessor::getInputChannelName (int channelIndex) const
{
    return String (channelIndex + 1);
}

const String BassPedalRackProcessor::getOutputChannelName (int channelIndex) const
{
    return String (channelIndex + 1);
}

bool BassPedalRackProcessor::isInputChannelStereoPair (int index) const
{
    return true;
}

bool BassPedalRackProcessor::isOutputChannelStereoPair (int index) const
{
    return true;
}

bool BassPedalRackProcessor::silenceInProducesSilenceOut() const
{
#if JucePlugin_SilenceInProducesSilenceOut
    return true;
#else
    return false;
#endif
}

bool BassPedalRackProcessor::acceptsMidi() const
{
#if JucePlugin_WantsMidiInput
    return true;
#else
    return false;
#endif
}

bool BassPedalRackProcessor::producesMidi() const
{
#if JucePlugin_ProducesMidiOutput
    return true;
#else
    return false;
#endif
}

double BassPedalRackProcessor::getTailLengthSeconds() const
{
    return 0;
}

int BassPedalRackProcessor::getNumPrograms()
{
    return 0;
}

int BassPedalRackProcessor::getCurrentProgram()
{
    return 0;
}

void BassPedalRackProcessor::setCurrentProgram (int index)
{
}

const String BassPedalRackProcessor::getProgramName (int index)
{
    return String::empty;
}

void BassPedalRackProcessor::changeProgramName (int index, const String& newName)
{
}

//==============================================================================
void BassPedalRackProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
	//initialise sampling frequency
	fsd_ = 2*sampleRate;
	fsd2_ = fsd_*fsd_;
	fsd3_ = fsd2_*fsd_;

		//initilise tone control
		a0_ = 1;
	changeToneStack();
}

void BassPedalRackProcessor::releaseResources()
{

}

void BassPedalRackProcessor::changeToneStack()
{
	if (trebleGain_ + midGain_ + bassGain_ < 0.01 )
		toneStack_ = false;
	else
	{
		toneStack_ = true;
		//Transfer function update
		b1_ = (10*trebleGain_+80*midGain_+3240*bassGain_+81)*RC_;
		b2_ = 16*(1120*trebleGain_-2025*midGain_*midGain_+81000*bassGain_*midGain_+2275*midGain_+14480*bassGain_+362)*RC2_*0.2;
		b3_ = -512*(midGain_-40*bassGain_-1)*(280*trebleGain_+153*midGain_)*RC3_;
		a1_ = (400*midGain_+16200*bassGain_+2247)*RC_*0.2;
		a2_ = -16*(2025*midGain_*midGain_-81000*bassGain_*midGain_+2205*midGain_-193680*bassGain_-5962)*RC2_*0.2;
		a3_ = -512*(midGain_-40*bassGain_-1)*(153*midGain_+280)*RC3_;

		//Filter coefficient update
		B0 = -b1_*fsd_ - b2_*fsd2_ - b3_*fsd3_; 
		B1 = -b1_*fsd_ + b2_*fsd2_ + 3*b3_*fsd3_;
		B2 = b1_*fsd_ + b2_*fsd2_ - 3*b3_*fsd3_;
		B3 = b1_*fsd_ - b2_*fsd2_ + b3_*fsd3_;
		A0 = 1/( -a0_ - a1_*fsd_ - a2_*fsd2_ - a3_*fsd3_);
		A1 = -3*a0_ - a1_*fsd_ + a2_*fsd2_ + 3*a3_*fsd3_;
		A2 = -3*a0_ + a1_*fsd_ + a2_*fsd2_ - 3*a3_*fsd3_;
		A3 = -a0_ + a1_*fsd_ - a2_*fsd2_ + a3_*fsd3_;
	}

}

void BassPedalRackProcessor::changeCoefficients(int kcase)
{
	if (abs(gain1_-1)<0.01 && (gain2_ + gain3_ + gain4_ + gain5_ + gain6_ + gain7_ + gain8_ + gain9_)<0.01)
	{
		shaper_ = false;
		scale_ = 1;
	}
	else
	{
		shaper_ = true;
		//scale by the sum of the gains time the distortion index
		scale_ = (gain1_ + gain2_ + gain3_ + gain4_ + gain5_ + gain6_ + gain7_ + gain8_ + gain9_)*index_;
		if (scale_>1)
			scale_ = 1/scale_;
		else
			scale_ = 1;
		//switch to avoid unecessary editing (even/odd and bigger indices that degree)
		switch(kcase)
		{
		case 0: //Update all (initialisation)
			coeffs_[9] = 256*gain9_;
			coeffs_[8] = 128*gain8_;
			coeffs_[7] = -576*gain9_ + 64*gain7_;
			coeffs_[6] = -256*gain8_ + 32*gain6_;
			coeffs_[5] = 432*gain9_ -112*gain7_ + 16*gain5_;
			coeffs_[4] = 160*gain8_ -48*gain6_ + 8*gain4_;
			coeffs_[3] = -120*gain9_ + 56*gain7_ -20*gain5_ + 4*gain3_;
			coeffs_[2] = -32*gain8_ + 18*gain6_ -8*gain4_ + 2*gain2_;
			coeffs_[1] = 9*gain9_ -7*gain7_ + 5*gain5_ -3*gain3_ + gain1_;
			coeffs_[0] = gain8_ - gain6_ + gain4_ - gain2_;
			break;
		case kGain1Param:
			coeffs_[1] = 9*gain9_ -7*gain7_ + 5*gain5_ -3*gain3_ + gain1_;
			break;
		case kGain2Param:
			coeffs_[2] = -32*gain8_ + 18*gain6_ -8*gain4_ + 2*gain2_;
			coeffs_[0] = gain8_ - gain6_ + gain4_ - gain2_;
			break;
		case kGain3Param:
			coeffs_[3] = -120*gain9_ + 56*gain7_ -20*gain5_ + 4*gain3_;
			coeffs_[1] = 9*gain9_ -7*gain7_ + 5*gain5_ -3*gain3_ + gain1_;
			break;
		case kGain4Param:
			coeffs_[4] = 160*gain8_ -48*gain6_ + 8*gain4_;
			coeffs_[2] = -32*gain8_ + 18*gain6_ -8*gain4_ + 2*gain2_;
			coeffs_[0] = gain8_ - gain6_ + gain4_ - gain2_;
			break;
		case kGain5Param:
			coeffs_[5] = 432*gain9_ -112*gain7_ + 16*gain5_;
			coeffs_[3] = -120*gain9_ + 56*gain7_ -20*gain5_ + 4*gain3_;
			coeffs_[1] = 9*gain9_ -7*gain7_ + 5*gain5_ -3*gain3_ + gain1_;
			break;
		case kGain6Param:
			coeffs_[6] = -256*gain8_ + 32*gain6_;
			coeffs_[4] = 160*gain8_ -48*gain6_ + 8*gain4_;
			coeffs_[2] = -32*gain8_ + 18*gain6_ -8*gain4_ + 2*gain2_;
			coeffs_[0] = gain8_ - gain6_ + gain4_ - gain2_;
			break;
		case kGain7Param:
			coeffs_[7] = -576*gain9_ + 64*gain7_;
			coeffs_[5] = 432*gain9_ -112*gain7_ + 16*gain5_;
			coeffs_[3] = -120*gain9_ + 56*gain7_ -20*gain5_ + 4*gain3_;
			coeffs_[1] = 9*gain9_ -7*gain7_ + 5*gain5_ -3*gain3_ + gain1_;
			break;
		case kGain8Param:
			coeffs_[8] = 128*gain8_;
			coeffs_[6] = -256*gain8_ + 32*gain6_;
			coeffs_[4] = 160*gain8_ -48*gain6_ + 8*gain4_;
			coeffs_[2] = -32*gain8_ + 18*gain6_ -8*gain4_ + 2*gain2_;
			coeffs_[0] = gain8_ - gain6_ + gain4_ - gain2_;
			break;
		case kGain9Param:
			coeffs_[9] = 256*gain9_;
			coeffs_[7] = -576*gain9_ + 64*gain7_;
			coeffs_[5] = 432*gain9_ -112*gain7_ + 16*gain5_;
			coeffs_[3] = -120*gain9_ + 56*gain7_ -20*gain5_ + 4*gain3_;
			coeffs_[1] = 9*gain9_ -7*gain7_ + 5*gain5_ -3*gain3_ + gain1_;
			break;
		}
	}
}

double* BassPedalRackProcessor::applyFilter(float input)
{
	double final[2]; //output
	final[0] = 0;
	final[1] = 0;
	double output = 0;  // temp output
	lastIn_[filterInd_] = (double)input; //update the circular buffer with the new index
	int firstMax = filterLength_ - filterInd_; //when indice reaches the end of the circular buffer
	switch(highCut_)
	{ //switch for the index of the HIgh Pass filter
	case 0:
		output = input; //allpass
		break;
	case 1:
		for (int i = 0; i< firstMax; i++) //until the end of the circular buffer
			output += lastIn_[i+filterInd_]*filter_high_1[i];
		for (int i = firstMax; i< filterLength_; i++) //from the beginning of the circular buffer
			output += lastIn_[i+filterInd_-filterLength_]*filter_high_1[i];
		break;
	case 2:
		for (int i = 0; i< firstMax; i++)
			output += lastIn_[i+filterInd_]*filter_high_2[i];
		for (int i = firstMax; i< filterLength_; i++)
			output += lastIn_[i+filterInd_-filterLength_]*filter_high_2[i];
		break;	
	case 3:
		for (int i = 0; i< firstMax; i++)
			output += lastIn_[i+filterInd_]*filter_high_3[i];
		for (int i = firstMax; i< filterLength_; i++)
			output += lastIn_[i+filterInd_-filterLength_]*filter_high_3[i];
		break;
	case 4:
		for (int i = 0; i< firstMax; i++)
			output += lastIn_[i+filterInd_]*filter_high_4[i];
		for (int i = firstMax; i< filterLength_; i++)
			output += lastIn_[i+filterInd_-filterLength_]*filter_high_4[i];
		break;	
	case 5:
		for (int i = 0; i< firstMax; i++)
			output += lastIn_[i+filterInd_]*filter_high_5[i];
		for (int i = firstMax; i< filterLength_; i++)
			output += lastIn_[i+filterInd_-filterLength_]*filter_high_5[i];
		break;
	case 6:
		for (int i = 0; i< firstMax; i++)
			output += lastIn_[i+filterInd_]*filter_high_6[i];
		for (int i = firstMax; i< filterLength_; i++)
			output += lastIn_[i+filterInd_-filterLength_]*filter_high_6[i];
		break;	
	case 7:
		for (int i = 0; i< firstMax; i++)
			output += lastIn_[i+filterInd_]*filter_high_7[i];
		for (int i = firstMax; i< filterLength_; i++)
			output += lastIn_[i+filterInd_-filterLength_]*filter_high_7[i];
		break;
	case 8:
		for (int i = 0; i< firstMax; i++)
			output += lastIn_[i+filterInd_]*filter_high_8[i];
		for (int i = firstMax; i< filterLength_; i++)
			output += lastIn_[i+filterInd_-filterLength_]*filter_high_8[i];
		break;	
		
	case 9:
		for (int i = 0; i< firstMax; i++)
			output += lastIn_[i+filterInd_]*filter_high_9[i];
		for (int i = firstMax; i< filterLength_; i++)
			output += lastIn_[i+filterInd_-filterLength_]*filter_high_9[i];
		break;	
	default:
		break;
	}
	final[0] = output; //store the output
	output = 0; //new output
	switch(lowCut_)
	{ //switch over the Low pass Filter
	case 0:
		output = input;
		break;
	case 1:
		for (int i = 0; i< firstMax; i++)
			output += lastIn_[i+filterInd_]*filter_low_1[i];
		for (int i = firstMax; i< filterLength_; i++)
			output += lastIn_[i+filterInd_-filterLength_]*filter_low_1[i];
		break;
	case 2:
		for (int i = 0; i< firstMax; i++)
			output += lastIn_[i+filterInd_]*filter_low_2[i];
		for (int i = firstMax; i< filterLength_; i++)
			output += lastIn_[i+filterInd_-filterLength_]*filter_low_2[i];
		break;	
	case 3:
		for (int i = 0; i< firstMax; i++)
			output += lastIn_[i+filterInd_]*filter_low_3[i];
		for (int i = firstMax; i< filterLength_; i++)
			output += lastIn_[i+filterInd_-filterLength_]*filter_low_3[i];
		break;
	case 4:
		for (int i = 0; i< firstMax; i++)
			output += lastIn_[i+filterInd_]*filter_low_4[i];
		for (int i = firstMax; i< filterLength_; i++)
			output += lastIn_[i+filterInd_-filterLength_]*filter_low_4[i];
		break;	
	case 5:
		for (int i = 0; i< firstMax; i++)
			output += lastIn_[i+filterInd_]*filter_low_5[i];
		for (int i = firstMax; i< filterLength_; i++)
			output += lastIn_[i+filterInd_-filterLength_]*filter_low_5[i];
		break;
	case 6:
		for (int i = 0; i< firstMax; i++)
			output += lastIn_[i+filterInd_]*filter_low_6[i];
		for (int i = firstMax; i< filterLength_; i++)
			output += lastIn_[i+filterInd_-filterLength_]*filter_low_6[i];
		break;	
	case 7:
		for (int i = 0; i< firstMax; i++)
			output += lastIn_[i+filterInd_]*filter_low_7[i];
		for (int i = firstMax; i< filterLength_; i++)
			output += lastIn_[i+filterInd_-filterLength_]*filter_low_7[i];
		break;
	case 8:
		for (int i = 0; i< firstMax; i++)
			output += lastIn_[i+filterInd_]*filter_low_8[i];
		for (int i = firstMax; i< filterLength_; i++)
			output += lastIn_[i+filterInd_-filterLength_]*filter_low_8[i];
		break;	
	case 9:
		for (int i = 0; i< firstMax; i++)
			output += lastIn_[i+filterInd_]*filter_low_9[i];
		for (int i = firstMax; i< filterLength_; i++)
			output += lastIn_[i+filterInd_-filterLength_]*filter_low_9[i];
		break;	
	default:
		break;
	}
	final[1] = output; //update output
	if (filterInd_==0) //update circular buffer indice (with modulo)
		filterInd_=filterLength_-1;
	else
		filterInd_--;
	return final;
}

float BassPedalRackProcessor::shaper(float x)
{
	double output;
	if(shaper_)
	{
		double dx = (double)x * index_; //distorted input
		//efficient polynomial computation
		output = coeffs_[9];
		for (int ind = 8; ind > -1; ind--)
		{
			output = output*dx + coeffs_[ind];
		}
		output *=scale_;
	}
	else 
		output = (double)x;

	return (float)output;
}

void BassPedalRackProcessor::saveMem(int channel)
{
	//Store the information of this channel

	//divided for the cirular buffer in config indice = 0;
	int firstMax = filterLength_ - filterInd_;
	for (int i=0; i < firstMax; i++)
	{
	//offset of the size of the buffer to have both buffer stored in inputMem;
		inputMem_[channel*filterLength_ + i] = lastIn_[filterInd_ +i];
	}
	for (int i=firstMax; i < filterLength_; i++)
	{
		inputMem_[channel*filterLength_ + i] = lastIn_[filterInd_ + i - filterLength_];
	}

	//Switch for the little (3) circular buffers in configuration index = 2
	switch(currInd_)
	{
	case 0:
		tonStackIn_[channel*3] = memIn_[1];
		tonStackIn_[channel*3+1] = memIn_[2];
		tonStackIn_[channel*3+2] = memIn_[0];
		tonStackOut_[channel*3] = memOut_[1];
		tonStackOut_[channel*3+1] = memOut_[2];
		tonStackOut_[channel*3+2] = memOut_[0];
		break;
	case 1:
		tonStackOut_[channel*3] = memOut_[2];
		tonStackOut_[channel*3+1] = memOut_[0];
		tonStackOut_[channel*3+2] = memOut_[1];

		tonStackIn_[channel*3] = memIn_[2];
		tonStackIn_[channel*3+1] = memIn_[0];
		tonStackIn_[channel*3+2] = memIn_[1];
		break;
	case 2:
		tonStackOut_[channel*3] = memOut_[0];
		tonStackOut_[channel*3+1] = memOut_[1];
		tonStackOut_[channel*3+2] = memOut_[2];

		tonStackIn_[channel*3] = memIn_[0];
		tonStackIn_[channel*3+1] = memIn_[1];
		tonStackIn_[channel*3+2] = memIn_[2];
		break;
	default:
		break;
	}
}

void BassPedalRackProcessor::loadMem(int channel)
{
	//Relaod the information af the new channel
	//Circular buffer for high and low pass filter
	for (int i=0; i < filterLength_; i++)
	{
		lastIn_[i] = inputMem_[channel*filterLength_+i];
	}
	filterInd_ = 0;

	//Circular buffers for Tone control
	memIn_[0] = tonStackIn_[channel*3];
	memIn_[1] = tonStackIn_[channel*3+1];
	memIn_[2] = tonStackIn_[channel*3+2];
	memOut_[0] = tonStackOut_[channel*3];
	memOut_[1] = tonStackOut_[channel*3+1];
	memOut_[2] = tonStackOut_[channel*3+2];
	currInd_ = 2;
}

float BassPedalRackProcessor::applyToneStack(float input)
{
	double di = (double)input;
	double output = di;
	switch(currInd_)
	{
	
	case 0:
		if (toneStack_)
			output = A0*(di*B0 + memIn_[1]*B1 + memIn_[2]*B2 + memIn_[0]*B3 -( memOut_[1]*A1 + memOut_[2]*A2 + memOut_[0]*A3));
		memOut_[currInd_] = output;
		memIn_[currInd_] = di;
		currInd_ = 2;
		break;
	case 1:
		if (toneStack_)
			output = A0*(di*B0 + memIn_[2]*B1 + memIn_[0]*B2 + memIn_[1]*B3 -( memOut_[2]*A1 + memOut_[0]*A2 + memOut_[1]*A3));
		memOut_[currInd_] = output;
		memIn_[currInd_] = di;
		currInd_ = 0;
		break;
	case 2:
		if (toneStack_)
			output = A0*(di*B0 + memIn_[0]*B1 + memIn_[1]*B2 + memIn_[2]*B3 -( memOut_[0]*A1 + memOut_[1]*A2 + memOut_[2]*A3));
		memOut_[currInd_] = output;
		memIn_[currInd_] = di;
		currInd_ = 1;
		break;
	default:
		break;
	}
	
	return (float)output;
}


void BassPedalRackProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
    // Helpful information about this block of samples:
    const int numInputChannels = getNumInputChannels();     // How many input channels for our effect?
    const int numOutputChannels = getNumOutputChannels();   // How many output channels for our effect?
    const int numSamples = buffer.getNumSamples();          // How many samples in the buffer for this block?
    // Go through each channel of audio that's passed in
	double* filtered;  //output of the high/low pass filter
	float mixed;   //mix of both
    for (int channel = 0; channel < numInputChannels; ++channel)
    {
        // channelData is an array of length numSamples which contains the audio for one channel
        float* channelData = buffer.getSampleData(channel);
		loadMem(channel); //load the buffers for this channel
        for (int i = 0; i < numSamples; ++i)
        {
            const float in = channelData[i];

			filtered = applyFilter(in); //Apply Low and High Pass Filter

			//mix the signal while adding distortion the scaled high frequencies
			mixed = (1-mix_)*filtered[1] + mix_*shaper(filtered[0]);
			
			//Apply the tone control and the final gain
			channelData[i] = applyToneStack(mixed)*gain_;
			
			
        }
		saveMem(channel);
		
    }
    
    // In case we have more outputs than inputs, we'll clear any output
    // channels that didn't contain input data, (because these aren't
    // guaranteed to be empty - they may contain garbage).
    for (int i = numInputChannels; i < numOutputChannels; ++i)
    {
        buffer.clear (i, 0, buffer.getNumSamples());
    }
}

//==============================================================================
bool BassPedalRackProcessor::hasEditor() const
{
    return true; // (change this to false if you choose to not supply an editor)
}

AudioProcessorEditor* BassPedalRackProcessor::createEditor()
{
    return new BassPedalRackProcessorEditor (this);
}

//==============================================================================
void BassPedalRackProcessor::getStateInformation (MemoryBlock& destData)
{
    // You should use this method to store your parameters in the memory block.
    // You could do that either as raw data, or use the XML or ValueTree classes
    // as intermediaries to make it easy to save and load complex data.
    
    // Create an outer XML element..
    XmlElement xml("C4DMPLUGINSETTINGS");
    
    // add some attributes to it..
    xml.setAttribute("uiWidth", lastUIWidth_);
    xml.setAttribute("uiHeight", lastUIHeight_);
	xml.setAttribute("mix", mix_);
	xml.setAttribute("index", index_);
	xml.setAttribute("gain", gain_);
	xml.setAttribute("highcut", highCut_);
	xml.setAttribute("treble", trebleGain_);
	xml.setAttribute("lowcut", lowCut_);
	xml.setAttribute("mid", midGain_);
	xml.setAttribute("bass", bassGain_);
	xml.setAttribute("gain1", gain1_);
	xml.setAttribute("gain2", gain2_);
	xml.setAttribute("gain3", gain3_);
	xml.setAttribute("gain4", gain4_);
	xml.setAttribute("gain5", gain5_);
	xml.setAttribute("gain6", gain6_);
	xml.setAttribute("gain7", gain7_);
	xml.setAttribute("gain8", gain8_);
	xml.setAttribute("gain9", gain9_);
	
    
    // then use this helper function to stuff it into the binary blob and return it..
    copyXmlToBinary(xml, destData);
}

void BassPedalRackProcessor::setStateInformation (const void* data, int sizeInBytes)
{
    // You should use this method to restore your parameters from this memory block,
    // whose contents will have been created by the getStateInformation() call.
    
    // This getXmlFromBinary() helper function retrieves our XML from the binary blob..
    ScopedPointer<XmlElement> xmlState (getXmlFromBinary (data, sizeInBytes));
    
    if(xmlState != 0)
    {
        // make sure that it's actually our type of XML object..
        if(xmlState->hasTagName("C4DMPLUGINSETTINGS"))
        {
            // ok, now pull out our parameters..
            lastUIWidth_  = xmlState->getIntAttribute("uiWidth", lastUIWidth_);
            lastUIHeight_ = xmlState->getIntAttribute("uiHeight", lastUIHeight_);
            
            mix_  = (float)xmlState->getDoubleAttribute("mix", mix_);
			index_  = (float)xmlState->getDoubleAttribute("index", index_);
			gain_  = (float)xmlState->getDoubleAttribute("gain", gain_);
			bassGain_  = (float)xmlState->getDoubleAttribute("bass", bassGain_);
			midGain_  = (float)xmlState->getDoubleAttribute("mid", midGain_);
			trebleGain_  = (float)xmlState->getDoubleAttribute("tre", trebleGain_);
			highCut_  = (int)xmlState->getDoubleAttribute("highcut", highCut_);
			lowCut_  = (int)xmlState->getDoubleAttribute("lowcut", lowCut_);
			gain1_  = (float)xmlState->getDoubleAttribute("gain1", gain1_);
			gain2_  = (float)xmlState->getDoubleAttribute("gain2", gain2_);
			gain3_  = (float)xmlState->getDoubleAttribute("gain3", gain3_);
			gain4_  = (float)xmlState->getDoubleAttribute("gain4", gain4_);
			gain5_  = (float)xmlState->getDoubleAttribute("gain5", gain5_);
			gain6_  = (float)xmlState->getDoubleAttribute("gain6", gain6_);
			gain7_  = (float)xmlState->getDoubleAttribute("gain7", gain7_);
			gain8_  = (float)xmlState->getDoubleAttribute("gain8", gain8_);
			gain9_  = (float)xmlState->getDoubleAttribute("gain9", gain9_);
        }
    }
}

//==============================================================================
// This creates new instances of the plugin..
AudioProcessor* JUCE_CALLTYPE createPluginFilter()
{
    return new BassPedalRackProcessor();
}