changeset 0:2cd427e000b0

initial commit
author Yannick JACOB <y.jacob@se12.qmul.ac.uk>
date Tue, 03 Sep 2013 12:53:16 +0100
parents
children d8c7b69cb4c9
files AddressPlugin/PluginEditor.cpp AddressPlugin/PluginEditor.h AddressPlugin/PluginProcessor.cpp AddressPlugin/PluginProcessor.h BassPedalRackPlugin/BassPedalRack.jucer BassPedalRackPlugin/ParametersRecap.txt BassPedalRackPlugin/PluginEditor.cpp BassPedalRackPlugin/PluginEditor.h BassPedalRackPlugin/PluginProcessor.cpp BassPedalRackPlugin/PluginProcessor.h BassPedalRackPlugin/filter.h Sirtassa/311CLNOF.WAV Sirtassa/311CLNOF.mid Sirtassa/Lussier_bassoon.mid Sirtassa/Lussier_bassoon.wav Sirtassa/Lussier_mix.wav Sirtassa/Lussier_trumpet.mid Sirtassa/Lussier_trumpet.wav Sirtassa/Sirtassa.m Sirtassa/UpdateFilterCoefficientsOL.m Sirtassa/UpdateGainCoefficientsOL2.m Sirtassa/UpdatePartialCoefficientsOL.m Sirtassa/createBPFilters.m Sirtassa/createExcitationSpectrums.m Sirtassa/createScore.m Sirtassa/midi2nmat.m Sirtassa/refineScore.m
diffstat 27 files changed, 6925 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AddressPlugin/PluginEditor.cpp	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,178 @@
+/*
+  ==============================================================================
+
+    This file was auto-generated by the Introjucer!
+
+    It contains the basic startup code for a Juce application.
+
+  ==============================================================================
+*/
+
+#include "PluginProcessor.h"
+#include "PluginEditor.h"
+
+
+//==============================================================================
+ADRessAudioProcessorEditor::ADRessAudioProcessorEditor (ADRessAudioProcessor* ownerFilter)
+    : AudioProcessorEditor (ownerFilter),
+      fftSizeLabel_("", "FFT Size:"),
+      hopSizeLabel_("", "Hop Size:"),
+      windowTypeLabel_("", "Window Type:"),
+	  widthLabel_("", "Width:"),
+      widthSlider_("width"),
+      azimuthLabel_("", "Azimuth:"),
+      azimuthSlider_("azimuth")
+{
+    // This is where our plugin's editor size is set.
+    // setSize(170, 80);
+    
+	betaE_ = 5;
+    // Set up the selection boxes
+    
+    addAndMakeVisible(&fftSizeComboBox_);
+    fftSizeComboBox_.setEditableText(false);
+    fftSizeComboBox_.setJustificationType(Justification::left);
+    fftSizeComboBox_.addItem("1024", 1024);
+    fftSizeComboBox_.addItem("2048", 2048);
+	fftSizeComboBox_.addItem("4096", 4096);
+    fftSizeComboBox_.addListener(this);
+    
+    addAndMakeVisible(&hopSizeComboBox_);
+    hopSizeComboBox_.setEditableText(false);
+    hopSizeComboBox_.setJustificationType(Justification::left);
+    hopSizeComboBox_.addItem("1/4 Window", ADRessAudioProcessor::kHopSize1_4Window);
+    hopSizeComboBox_.addItem("1/8 Window", ADRessAudioProcessor::kHopSize1_8Window);
+    hopSizeComboBox_.addListener(this);
+    
+    addAndMakeVisible(&windowTypeComboBox_);
+    windowTypeComboBox_.setEditableText(false);
+    windowTypeComboBox_.setJustificationType(Justification::left);
+    windowTypeComboBox_.addItem("Rectangular", ADRessAudioProcessor::kWindowRectangular);
+    windowTypeComboBox_.addItem("Bartlett", ADRessAudioProcessor::kWindowBartlett);
+    windowTypeComboBox_.addItem("Hann", ADRessAudioProcessor::kWindowHann);
+    windowTypeComboBox_.addItem("Hamming", ADRessAudioProcessor::kWindowHamming);
+    windowTypeComboBox_.addListener(this);
+
+	
+	// Set up the sliders
+    addAndMakeVisible(&widthSlider_);
+    widthSlider_.setSliderStyle(Slider::Rotary);
+    widthSlider_.addListener(this);
+    widthSlider_.setRange(0, betaE_, 1);
+    
+    widthLabel_.attachToComponent(&widthSlider_, false);
+    widthLabel_.setFont(Font (11.0f));
+
+
+	    // Set up the sliders
+    addAndMakeVisible(&azimuthSlider_);
+    azimuthSlider_.setSliderStyle(Slider::Rotary);
+    azimuthSlider_.addListener(this);
+    azimuthSlider_.setRange(0, 2*betaE_, 1);
+
+
+    
+    azimuthLabel_.attachToComponent(&azimuthSlider_, false);
+    azimuthLabel_.setFont(Font (11.0f));
+
+    fftSizeLabel_.attachToComponent(&fftSizeComboBox_, false);
+    fftSizeLabel_.setFont(Font (11.0f));
+    
+    hopSizeLabel_.attachToComponent(&hopSizeComboBox_, false);
+    hopSizeLabel_.setFont(Font (11.0f));
+    
+    windowTypeLabel_.attachToComponent(&windowTypeComboBox_, false);
+    windowTypeLabel_.setFont(Font (11.0f));
+    
+    // add the triangular resizer component for the bottom-right of the UI
+    addAndMakeVisible(resizer_ = new ResizableCornerComponent (this, &resizeLimits_));
+    resizeLimits_.setSizeLimits(360, 400, 360, 400);
+    
+    // set our component's initial size to be the last one that was stored in the filter's settings
+    setSize(ownerFilter->lastUIWidth_,
+            ownerFilter->lastUIHeight_);
+    
+    startTimer(50);
+}
+
+ADRessAudioProcessorEditor::~ADRessAudioProcessorEditor()
+{
+}
+
+//==============================================================================
+void ADRessAudioProcessorEditor::paint (Graphics& g)
+{
+    g.fillAll (Colours::grey);
+}
+
+void ADRessAudioProcessorEditor::resized()
+{
+    fftSizeComboBox_.setBounds(20, 20, 150, 30);
+    hopSizeComboBox_.setBounds(200, 20, 150, 30);
+    windowTypeComboBox_.setBounds(20, 75, 150, 30);
+	widthSlider_.setBounds(200, 70, 150, 40);
+
+	azimuthSlider_.setBounds(20, 150, 150, 40);
+    resizer_->setBounds(getWidth() - 16, getHeight() - 16, 16, 16);
+    
+    getProcessor()->lastUIWidth_ = getWidth();
+    getProcessor()->lastUIHeight_ = getHeight();
+}
+
+//==============================================================================
+// This timer periodically checks whether any of the filter's parameters have changed...
+void ADRessAudioProcessorEditor::timerCallback()
+{
+    ADRessAudioProcessor* ourProcessor = getProcessor();
+    
+    fftSizeComboBox_.setSelectedId(ourProcessor->fftSelectedSize_, false);
+    hopSizeComboBox_.setSelectedId(ourProcessor->hopSelectedSize_, false);
+    windowTypeComboBox_.setSelectedId(ourProcessor->windowType_, false);
+
+	widthSlider_.setValue(ourProcessor->width_, dontSendNotification);
+	azimuthSlider_.setValue(ourProcessor->azimuth_, dontSendNotification);
+}
+
+// This is our Slider::Listener callback, when the user drags a slider.
+void ADRessAudioProcessorEditor::sliderValueChanged (Slider* slider)
+{
+	if (slider == &widthSlider_)
+    {
+        // It's vital to use setParameterNotifyingHost to change any parameters that are automatable
+        // by the host, rather than just modifying them directly, otherwise the host won't know
+        // that they've changed.
+        getProcessor()->setParameterNotifyingHost (ADRessAudioProcessor::kWidthParam,
+                                                   (float)widthSlider_.getValue());
+	}
+	
+    if (slider == &azimuthSlider_)
+    {
+		getProcessor()->setParameterNotifyingHost (ADRessAudioProcessor::kAzimuthParam,
+                                                   (float)azimuthSlider_.getValue());
+	}
+}
+
+// Similar callback to sliderValueChanged for ComboBox updates
+void ADRessAudioProcessorEditor::comboBoxChanged (ComboBox *comboBox)
+{
+    if(comboBox == &fftSizeComboBox_)
+    {
+        getProcessor()->setParameterNotifyingHost (ADRessAudioProcessor::kFFTSizeParam,
+                                                   (float)fftSizeComboBox_.getSelectedId());
+    }
+    else if(comboBox == &hopSizeComboBox_)
+    {
+        getProcessor()->setParameterNotifyingHost (ADRessAudioProcessor::kHopSizeParam,
+                                                   (float)hopSizeComboBox_.getSelectedId());
+    }
+    else if(comboBox == &windowTypeComboBox_)
+    {
+        getProcessor()->setParameterNotifyingHost (ADRessAudioProcessor::kWindowTypeParam,
+                                                   (float)windowTypeComboBox_.getSelectedId());
+    }
+}
+
+int ADRessAudioProcessorEditor::getBeta()
+{
+	return betaE_;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AddressPlugin/PluginEditor.h	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,61 @@
+/*
+  ==============================================================================
+
+    This file was auto-generated by the Introjucer!
+
+    It contains the basic startup code for a Juce application.
+
+  ==============================================================================
+*/
+
+#ifndef __PLUGINEDITOR_H_6E48F605__
+#define __PLUGINEDITOR_H_6E48F605__
+
+#include "../JuceLibraryCode/JuceHeader.h"
+#include "PluginProcessor.h"
+
+
+//==============================================================================
+
+class ADRessAudioProcessorEditor  : public AudioProcessorEditor,
+                                   public SliderListener,
+                                   public ComboBox::Listener,
+                                   public Timer
+{
+public:
+    ADRessAudioProcessorEditor (ADRessAudioProcessor* ownerFilter);
+    ~ADRessAudioProcessorEditor();
+
+    //==============================================================================
+    // This is just a standard Juce paint method...
+    void timerCallback();
+    void paint (Graphics& g);
+    void resized();
+    void sliderValueChanged (Slider*);
+    void comboBoxChanged (ComboBox *);
+
+	int getBeta();
+    
+private:
+    Label fftSizeLabel_, hopSizeLabel_, windowTypeLabel_;
+    ComboBox fftSizeComboBox_, hopSizeComboBox_, windowTypeComboBox_;
+
+	Label widthLabel_;
+    Slider widthSlider_;
+
+	Label azimuthLabel_;
+    Slider azimuthSlider_;
+
+
+    ScopedPointer<ResizableCornerComponent> resizer_;
+    ComponentBoundsConstrainer resizeLimits_;
+	int betaE_;
+    
+    ADRessAudioProcessor* getProcessor() const
+    {
+        return static_cast <ADRessAudioProcessor*> (getAudioProcessor());
+    }
+};
+
+
+#endif  // __PLUGINEDITOR_H_6E48F605__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AddressPlugin/PluginProcessor.cpp	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,834 @@
+/*
+  ==============================================================================
+
+    This file was auto-generated!
+
+    It contains the basic startup code for a Juce application.
+
+  ==============================================================================
+*/
+
+#include "PluginProcessor.h"
+#include "PluginEditor.h"
+
+
+//==============================================================================
+
+#define 	M_PI   3.14159265358979323846	/* pi */
+
+ADRessAudioProcessor::ADRessAudioProcessor() : inputBuffer_(2, 1), outputBuffer_(2, 1)
+{
+    // Set default values:
+    fftSelectedSize_ = 2048;
+    hopSelectedSize_ = kHopSize1_8Window;
+    windowType_ = kWindowHann;
+
+    fftInitialised_ = false;
+    fftActualTransformSize_ = 0;
+    inputBufferLength_ = 1;
+    outputBufferLength_ = 1;
+    inputBufferWritePosition_ = outputBufferWritePosition_ = outputBufferReadPosition_ = 0;
+    samplesSinceLastFFT_ = 0;
+    windowBuffer_ = 0;
+    windowBufferLength_ = 0;
+    preparedToPlay_ = false;
+    fftScaleFactor_ = 0.0;
+	beta_ = 5;
+	width_ = 0;
+	azimuth_ = beta_;
+
+
+	indMinL_ = beta_;
+	indMaxL_ = beta_;
+	indMinR_ = beta_;
+	indMaxR_ = beta_;
+	computeR_ = true;
+	computeL_ = true;
+	invGain_ = 2;
+	invBeta_ = 1/(float)beta_;
+	i1 = std::complex<double>(0,1);
+
+    
+    lastUIWidth_ = 360;
+    lastUIHeight_ = 400;
+}
+
+ADRessAudioProcessor::~ADRessAudioProcessor()
+{
+    // Release FFT resources if allocated. This should be handled by
+    // releaseResources() but in the event it doesn't happen, this avoids
+    // a leak. Harmless to call it twice.
+    deinitFFT();
+    deinitWindow();
+}
+
+//==============================================================================
+const String ADRessAudioProcessor::getName() const
+{
+    return JucePlugin_Name;
+}
+
+int ADRessAudioProcessor::getNumParameters()
+{
+    return kNumParameters;
+}
+
+float ADRessAudioProcessor::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 kFFTSizeParam:    return (float)fftSelectedSize_;
+        case kHopSizeParam:    return (float)hopSelectedSize_;
+        case kWindowTypeParam: return (float)windowType_;
+		case kWidthParam:     return (float)width_;
+		case kAzimuthParam:		return (float)azimuth_;
+
+        default:               return 0.0f;
+    }
+}
+
+void ADRessAudioProcessor::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 kFFTSizeParam:
+            if((int)newValue != fftSelectedSize_)
+            {
+                fftSelectedSize_ = (int)newValue;
+                if(preparedToPlay_)
+                {
+                    // Update settings if currently playing, else wait until prepareToPlay() called
+                    initFFT(fftSelectedSize_);
+                    initWindow(fftSelectedSize_, windowType_);
+                }
+            }
+            break;
+        case kHopSizeParam:
+            hopSelectedSize_ = (int)newValue;
+            if(preparedToPlay_)
+                updateHopSize();
+            break;
+        case kWindowTypeParam:
+            // Recalculate window if needed
+            if((int)newValue != windowType_)
+            {
+                windowType_ = (int)newValue;
+                if(preparedToPlay_)
+                    initWindow(fftActualTransformSize_, (int)newValue);
+            }
+            break;
+
+		case kWidthParam:
+            width_ = (int)newValue;
+			changeParams();
+			break;
+
+        case kAzimuthParam:
+            azimuth_ = (int)newValue;
+			changeParams();
+			break;
+
+        default:
+            break;
+    }
+}
+
+void ADRessAudioProcessor::changeParams()
+{
+	int maxA = std::min(azimuth_ + width_,2*beta_);
+	int minA = std::max(azimuth_ - width_,0);
+	if (maxA >= beta_)
+	{
+		computeR_ = true;
+		indMinR_ = 2*beta_ - maxA;
+		if (minA >= beta_)
+		{
+			indMaxR_ = 2*beta_ - minA;
+		} else {
+			indMaxR_ = beta_;
+		}
+	} else {
+		computeR_ = false;
+	}
+
+	if (minA <= beta_)
+	{
+		computeL_ = true;
+		indMinL_ = minA;
+		if (maxA <= beta_)
+		{
+			indMaxL_ = maxA;
+		} else {
+			indMaxL_ = beta_;			
+		}
+	} else {
+		computeL_ = false;
+	}
+
+	invGain_ = (indMaxR_ - indMinR_ + indMaxL_ - indMinL_);
+	if (computeR_)
+		invGain_++;
+	if (computeL_)
+		invGain_++;
+	invGain_ = 1;//invGain_;
+
+}
+
+
+const String ADRessAudioProcessor::getParameterName (int index)
+{
+    switch (index)
+    {
+        case kFFTSizeParam:    return "FFT size";
+        case kHopSizeParam:    return "hop size";
+        case kWindowTypeParam: return "window type";
+		case kWidthParam:     return "volume";
+		case kAzimuthParam:     return "azimuth";
+
+        default:               break;
+    }
+    
+    return String::empty;
+}
+
+const String ADRessAudioProcessor::getParameterText (int index)
+{
+    return String (getParameter (index), 2);
+}
+
+const String ADRessAudioProcessor::getInputChannelName (int channelIndex) const
+{
+    return String (channelIndex + 1);
+}
+
+const String ADRessAudioProcessor::getOutputChannelName (int channelIndex) const
+{
+    return String (channelIndex + 1);
+}
+
+bool ADRessAudioProcessor::isInputChannelStereoPair (int index) const
+{
+    return true;
+}
+
+bool ADRessAudioProcessor::isOutputChannelStereoPair (int index) const
+{
+    return true;
+}
+
+bool ADRessAudioProcessor::silenceInProducesSilenceOut() const
+{
+#if JucePlugin_SilenceInProducesSilenceOut
+    return true;
+#else
+    return false;
+#endif
+}
+
+bool ADRessAudioProcessor::acceptsMidi() const
+{
+#if JucePlugin_WantsMidiInput
+    return true;
+#else
+    return false;
+#endif
+}
+
+bool ADRessAudioProcessor::producesMidi() const
+{
+#if JucePlugin_ProducesMidiOutput
+    return true;
+#else
+    return false;
+#endif
+}
+
+double ADRessAudioProcessor::getTailLengthSeconds() const
+{
+    return 0;
+}
+
+int ADRessAudioProcessor::getNumPrograms()
+{
+    return 0;
+}
+
+int ADRessAudioProcessor::getCurrentProgram()
+{
+    return 0;
+}
+
+void ADRessAudioProcessor::setCurrentProgram (int index)
+{
+}
+
+const String ADRessAudioProcessor::getProgramName (int index)
+{
+    return String::empty;
+}
+
+void ADRessAudioProcessor::changeProgramName (int index, const String& newName)
+{
+}
+
+//==============================================================================
+void ADRessAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
+{
+    // Use this method as the place to do any pre-playback
+    // initialisation that you need..
+    
+    initFFT(fftSelectedSize_);
+    initWindow(fftSelectedSize_, windowType_);
+    preparedToPlay_ = true;
+}
+
+void ADRessAudioProcessor::releaseResources()
+{
+    // When playback stops, you can use this as an opportunity to free up any
+    // spare memory, etc.
+    
+    deinitFFT();
+    deinitWindow();
+    preparedToPlay_ = false;
+}
+
+
+
+
+
+void ADRessAudioProcessor::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?
+    
+    int channel, inwritepos, sampsincefft;
+    int outreadpos, outwritepos;
+    
+    // Grab the lock that prevents the FFT settings from changing
+    fftSpinLock_.enter();
+    
+    // Check that we're initialised and ready to go. If not, set output to 0
+    if(!fftInitialised_)
+    {
+        for (channel = 0; channel < numOutputChannels; ++channel)
+        {
+            buffer.clear (channel, 0, buffer.getNumSamples());
+        }
+        
+        fftSpinLock_.exit();
+        return;
+    }
+
+
+
+    // Go through each channel of audio that's passed in. Collect the samples in the input
+    // buffer. When we've reached the next hop interval, calculate the FFT.
+
+    // channelDataL is an array of length numSamples which contains the audio for one channel
+	float* channelDataL = buffer.getSampleData(0);
+	float* channelDataR = buffer.getSampleData(1);
+	
+	// inputBufferDataL is the circular buffer for collecting input samples for the FFT
+	float* inputBufferDataL = inputBuffer_.getSampleData(0);
+	float* inputBufferDataR = inputBuffer_.getSampleData(1);
+	
+	float* outputBufferDataL = outputBuffer_.getSampleData(0);
+	float* outputBufferDataR = outputBuffer_.getSampleData(1);
+
+	
+	// State variables need to be temporarily cached for each channel. We don't want the
+	// operations on one channel to affect the identical behaviour of the next channel
+	inwritepos = inputBufferWritePosition_;
+	outwritepos = outputBufferWritePosition_;
+	outreadpos = outputBufferReadPosition_;
+	sampsincefft = samplesSinceLastFFT_;
+	
+	for (int i = 0; i < numSamples; ++i)
+	{
+		const float inL = channelDataL[i];
+		const float inR = channelDataR[i];
+		
+		// Store the next buffered sample in the output. Do this first before anything
+		// changes the output buffer-- we will have at least one FFT size worth of data
+		// stored and ready to go. Set the result to 0 when finished in preparation for the
+		// next overlap/add procedure.
+
+		channelDataL[i] = outputBufferDataL[outreadpos];
+		channelDataR[i] = outputBufferDataR[outreadpos];
+		outputBufferDataL[outreadpos] = 0.0;
+		outputBufferDataR[outreadpos] = 0.0;
+			
+		if(++outreadpos >= outputBufferLength_)
+			outreadpos = 0;
+
+		// Store the current sample in the input buffer, incrementing the write pointer. Also
+		// increment how many samples we've stored since the last transform. If it reaches the
+		// hop size, perform an FFT and any frequency-domain processing.
+		inputBufferDataL[inwritepos] = inL;
+		inputBufferDataR[inwritepos] = inR;
+		if (++inwritepos >= inputBufferLength_)
+			inwritepos = 0;
+		if (++sampsincefft >= hopActualSize_)
+		{
+			sampsincefft = 0;
+			
+			// Find the index of the starting sample in the buffer. When the buffer length
+			// is equal to the transform size, this will be the current write position but
+			// this code is more general for larger buffers.
+			int inputBufferStartPosition = (inwritepos + inputBufferLength_
+											- fftActualTransformSize_) % inputBufferLength_;
+			
+			// Window the buffer and copy it into the FFT input
+			int inputBufferIndex = inputBufferStartPosition;
+			for(int fftBufferIndex = 0; fftBufferIndex < fftActualTransformSize_; fftBufferIndex++)
+			{
+				// Set real part to windowed signal; imaginary part to 0.
+				fftTimeDomain_[fftBufferIndex][1] = 0.0;
+				if(fftBufferIndex >= windowBufferLength_) // Safety check, in case window isn't ready
+					fftTimeDomain_[fftBufferIndex][0] = 0.0;
+				else
+					fftTimeDomain_[fftBufferIndex][0] = windowBuffer_[fftBufferIndex]
+															* inputBufferDataL[inputBufferIndex];
+				inputBufferIndex++;
+				if(inputBufferIndex >= inputBufferLength_)
+					inputBufferIndex = 0;
+			}
+
+			// Perform the FFT on the windowed data, going into the frequency domain.Result will be in fftFrequencyDomain_
+			fftw_execute(fftForwardPlan_);
+			
+			// ********** PHASE VOCODER PROCESSING GOES HERE **************
+			// This is the place where frequency-domain calculations are made on the transformed signal. 
+			//Put the result back into fftFrequencyDomain_ before transforming back.
+
+			for (int ii = 0; ii < fftActualTransformSize_/2+1; ii++)
+			{
+				realL_[ii] = fftFrequencyDomain_[ii][0];
+				imagL_[ii] = fftFrequencyDomain_[ii][1];
+			}
+			
+			inputBufferIndex = inputBufferStartPosition;
+			for(int fftBufferIndex = 0; fftBufferIndex < fftActualTransformSize_; fftBufferIndex++)
+			{
+				if(fftBufferIndex >= windowBufferLength_) // Safety check, in case window isn't ready
+					fftTimeDomain_[fftBufferIndex][0] = 0.0;
+				else
+					fftTimeDomain_[fftBufferIndex][0] = windowBuffer_[fftBufferIndex]
+															* inputBufferDataR[inputBufferIndex];
+				inputBufferIndex++;
+				if(inputBufferIndex >= inputBufferLength_)
+					inputBufferIndex = 0;
+			}
+			fftw_execute(fftForwardPlan_);
+
+
+			for (int ii = 0; ii < fftActualTransformSize_/2+1; ii++)
+			{
+				realR_[ii] = fftFrequencyDomain_[ii][0];
+				imagR_[ii] = fftFrequencyDomain_[ii][1];
+			}
+
+
+				
+			double minV, maxV,newVal;
+			std::complex<double> fftTemp;
+			int indMin;
+			for (int ii = 0; ii <fftActualTransformSize_/2+1; ii++)
+			{
+				if (computeR_)
+				{
+					//Right plane
+					minV = realL_[ii]*realL_[ii] + imagL_[ii]*imagL_[ii];
+					maxV  = minV;
+					azr_[ii][0] = 0;
+					indMin = 0;
+					for (int j = 1; j <= beta_; j++)
+					{
+						newVal = (realL_[ii] - j*invBeta_*realR_[ii])*(realL_[ii] - j*invBeta_*realR_[ii]) + (imagL_[ii] - j*invBeta_*imagR_[ii])*(imagL_[ii] - j*invBeta_*imagR_[ii]);
+						azr_[ii][j] = 0;
+
+						if (newVal>maxV)
+						{
+							maxV = newVal; 
+						} 
+						else if (newVal<minV)
+						{
+							minV = newVal; 
+							indMin = j;
+						}
+					}
+					azr_[ii][indMin] = sqrt(maxV) - sqrt(minV);
+				}
+
+				if(computeL_)
+				{
+					////Left plane
+					minV = realR_[ii]*realR_[ii] + imagR_[ii]*imagR_[ii];
+					maxV  = minV;
+					indMin = 0;
+					azl_[ii][0] = 0;
+					for (int j = 1; j <= beta_; j++)
+					{
+						newVal = (realR_[ii] - j*invBeta_*realL_[ii])*(realR_[ii] - j*invBeta_*realL_[ii]) + (imagR_[ii] - j*invBeta_*imagL_[ii])*(imagR_[ii] - j*invBeta_*imagL_[ii]);
+						azr_[ii][j] = 0;
+						if (newVal>maxV)
+						{
+							maxV = newVal; 
+						} 
+						else if (newVal<minV)
+						{
+							minV = newVal; 
+							indMin = j;
+						}
+					}
+					azl_[ii][indMin] = sqrt(maxV) - sqrt(minV);
+				}
+			}
+
+
+			for (int ii = 0; ii < fftActualTransformSize_/2+1; ii++)
+			{
+				fftTemp = 0;
+				for ( int j = indMinR_; j <= indMaxR_; j++)
+				{
+					fftTemp += azr_[ii][j]*exp(i1*imagR_[ii]);
+				} 
+				for ( int j = indMinL_; j <= indMaxL_; j++)
+				{
+					fftTemp += azl_[ii][j]*exp(i1*imagL_[ii]);
+				}
+//				fftTemp *= invGain_;	
+
+				fftFrequencyDomain_[ii][0] = real(fftTemp);
+				fftFrequencyDomain_[ii][1] = imag(fftTemp);
+			}
+
+			for (int ii = 1; ii < fftActualTransformSize_/2; ii++)
+			{
+				fftFrequencyDomain_[fftActualTransformSize_-ii][0] = fftFrequencyDomain_[ii][0];
+				fftFrequencyDomain_[fftActualTransformSize_-ii][1] = -fftFrequencyDomain_[ii][1];
+			}
+			fftw_execute(fftBackwardPlan_);
+
+			float audioTemp;
+			int outputBufferIndex = outwritepos;
+			for(int fftBufferIndex = 0; fftBufferIndex < fftActualTransformSize_; fftBufferIndex++)
+			{
+				audioTemp = (float)fftTimeDomain_[fftBufferIndex][0] * fftScaleFactor_;
+				outputBufferDataR[outputBufferIndex] += audioTemp;
+				outputBufferDataL[outputBufferIndex] += audioTemp;
+				if(++outputBufferIndex >= outputBufferLength_)
+					outputBufferIndex = 0;
+			}
+
+
+
+			// Add the result to the output buffer, starting at the current write position
+			// (Output buffer will have been zeroed after reading the last time around)
+			// Output needs to be scaled by the transform size to get back to original amplitude:
+			// this is a property of how fftw is implemented. Scaling will also need to be adjusted
+			// based on hop size to get the same output level (smaller hop size produces more overlap
+			// and hence higher signal level)
+
+
+
+
+			// Advance the write position within the buffer by the hop size
+			outwritepos = (outwritepos + hopActualSize_) % outputBufferLength_;
+		}
+	}
+    
+    
+    // Having made a local copy of the state variables for each channel, now transfer the result
+    // back to the main state variable so they will be preserved for the next call of processBlock()
+    inputBufferWritePosition_ = inwritepos;
+    outputBufferWritePosition_ = outwritepos;
+    outputBufferReadPosition_ = outreadpos;
+    samplesSinceLastFFT_ = sampsincefft;
+    
+    // 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());
+    }
+    
+    fftSpinLock_.exit();
+}
+
+//==============================================================================
+bool ADRessAudioProcessor::hasEditor() const
+{
+    return true; // (change this to false if you choose to not supply an editor)
+}
+
+AudioProcessorEditor* ADRessAudioProcessor::createEditor()
+{
+    return new ADRessAudioProcessorEditor (this);
+}
+
+//==============================================================================
+void ADRessAudioProcessor::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("fftSize", fftSelectedSize_);
+    xml.setAttribute("hopSize", hopSelectedSize_);
+    xml.setAttribute("windowType", windowType_);
+	xml.setAttribute("volume", width_);
+	xml.setAttribute("azimuth", azimuth_);
+    
+    // then use this helper function to stuff it into the binary blob and return it..
+    copyXmlToBinary(xml, destData);
+}
+
+void ADRessAudioProcessor::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_);
+            
+            fftSelectedSize_  = (int)xmlState->getDoubleAttribute("fftSize", fftSelectedSize_);
+            hopSelectedSize_  = (int)xmlState->getDoubleAttribute("hopSize", hopSelectedSize_);
+            windowType_  = (int)xmlState->getDoubleAttribute("windowType", windowType_);
+			width_  = (int)xmlState->getDoubleAttribute("volume", width_);
+			azimuth_  = (int)xmlState->getDoubleAttribute("azimuth", azimuth_);
+
+            
+            if(preparedToPlay_)
+            {
+                // Update settings if currently playing, else wait until prepareToPlay() called
+                initFFT(fftSelectedSize_);
+                initWindow(fftSelectedSize_, windowType_);
+            }
+        }
+    }
+}
+
+//==============================================================================
+// Initialise the FFT data structures for a given length transform
+void ADRessAudioProcessor::initFFT(int length)
+{
+    if(fftInitialised_)
+        deinitFFT();
+    
+    // Save the current length so we know how big our results are later
+    fftActualTransformSize_ = length;
+    
+    // Here we allocate the complex-number buffers for the FFT. This uses
+    // a convenient wrapper on the more general fftw_malloc()
+    fftTimeDomain_ = fftw_alloc_complex(length);
+    fftFrequencyDomain_ = fftw_alloc_complex(length);
+    
+    // FFTW_ESTIMATE doesn't necessarily produce the fastest executing code (FFTW_MEASURE
+    // will get closer) but it carries a minimum startup cost. FFTW_MEASURE might stall for
+    // several seconds which would be annoying in an audio plug-in context.
+    fftForwardPlan_ = fftw_plan_dft_1d(fftActualTransformSize_, fftTimeDomain_,
+                                       fftFrequencyDomain_, FFTW_FORWARD, FFTW_ESTIMATE);
+    fftBackwardPlan_ = fftw_plan_dft_1d(fftActualTransformSize_, fftFrequencyDomain_,
+                                       fftTimeDomain_, FFTW_BACKWARD, FFTW_ESTIMATE);
+    
+    // Allocate the buffer that the samples will be collected in
+    inputBufferLength_ = fftActualTransformSize_;
+    inputBuffer_.setSize(2, inputBufferLength_);
+    inputBuffer_.clear();
+    inputBufferWritePosition_ = 0;
+    samplesSinceLastFFT_ = 0;
+    
+    // Allocate the output buffer to be twice the size of the FFT
+    // This will be enough for all hop size cases
+    outputBufferLength_ = 2*fftActualTransformSize_;
+    outputBuffer_.setSize(2, outputBufferLength_);
+    outputBuffer_.clear();
+    outputBufferReadPosition_ = 0;
+    
+    updateHopSize();
+    
+    fftInitialised_ = true;
+}
+
+// Free the FFT data structures
+void ADRessAudioProcessor::deinitFFT()
+{
+    if(!fftInitialised_)
+        return;
+    
+    // Prevent this variable from changing while an audio callback is running.
+    // Once it has changed, the next audio callback will find that it's not
+    // initialised and will return silence instead of attempting to work with the
+    // (invalid) FFT structures. This produces an audible glitch but no crash,
+    // and is the simplest way to handle parameter changes in this example code.
+    fftSpinLock_.enter();
+    fftInitialised_ = false;
+    fftSpinLock_.exit();
+    
+    fftw_destroy_plan(fftForwardPlan_);
+    fftw_destroy_plan(fftBackwardPlan_);
+    fftw_free(fftTimeDomain_);
+    fftw_free(fftFrequencyDomain_);
+    
+    // Leave the input buffer in memory until the plugin is released
+}
+
+//==============================================================================
+// Create a new window of a given length and type
+void ADRessAudioProcessor::initWindow(int length, int windowType)
+{
+    if(windowBuffer_ != 0)
+        deinitWindow();
+    if(length == 0) // Sanity check
+        return;
+    
+    // Allocate memory for the window
+    windowBuffer_ = (double *)malloc(length * sizeof(double));
+    
+    // Write the length as a double here to simplify the code below (otherwise
+    // typecasts would be wise)
+    double windowLength = length;
+    
+    // Set values for the window, depending on its type
+    for(int i = 0; i < length; i++)
+    {
+        // Window functions are typically defined to be symmetrical. This will cause a
+        // problem in the overlap-add process: the windows instead need to be periodic
+        // when arranged end-to-end. As a result we calculate the window of one sample
+        // larger than usual, and drop the last sample. (This works as long as N is even.)
+        // See Julius Smith, "Spectral Audio Signal Processing" for details.
+        switch(windowType)
+        {
+            case kWindowBartlett:
+                windowBuffer_[i] = (2.0/(windowLength + 2.0))*
+                    (0.5*(windowLength + 2.0) - abs((double)i - 0.5*windowLength));
+                break;
+            case kWindowHann:
+                windowBuffer_[i] = 0.5*(1.0 - cos(2.0*M_PI*(double)i/windowLength));
+                break;
+            case kWindowHamming:
+                windowBuffer_[i] = 0.54 - 0.46*cos(2.0*M_PI*(double)i/windowLength);
+                break;
+            case kWindowRectangular:
+            default:
+                windowBuffer_[i] = 1.0;
+                break;
+        }
+    }
+    
+    windowBufferLength_ = length;
+    updateScaleFactor();
+}
+
+// Free the window buffer
+void ADRessAudioProcessor::deinitWindow()
+{
+    if(windowBuffer_ == 0)
+        return;
+    
+    // Delay clearing the window until the audio thread is not running
+    // to avoid a crash if the code tries to access an invalid window
+    fftSpinLock_.enter();
+    windowBufferLength_ = 0;
+    fftSpinLock_.exit();
+    
+    free(windowBuffer_);
+    windowBuffer_ = 0;
+}
+
+// Update the actual hop size depending on the window size and hop size settings
+// Hop size is expressed as a fraction of a window in the parameters.
+void ADRessAudioProcessor::updateHopSize()
+{
+    switch(hopSelectedSize_)
+    {
+        case kHopSize1Window:
+            hopActualSize_ = fftActualTransformSize_;
+            break;
+        case kHopSize1_2Window:
+            hopActualSize_ = fftActualTransformSize_ / 2;
+            break;
+        case kHopSize1_4Window:
+            hopActualSize_ = fftActualTransformSize_ / 4;
+            break;
+        case kHopSize1_8Window:
+            hopActualSize_ = fftActualTransformSize_ / 8;
+            break;
+    }
+    
+    // Update the factor by which samples are scaled to preserve unity gain
+    updateScaleFactor();
+    
+    // Read pointer lags the write pointer to allow for FFT buffers to accumulate and
+    // be processed. Total latency is sum of the FFT size and the hop size.
+    outputBufferWritePosition_ = hopActualSize_ + fftActualTransformSize_;
+}
+
+// Update the factor by which each output sample is scaled. This needs to update
+// every time FFT size, hop size, and window type are changed.
+void ADRessAudioProcessor::updateScaleFactor()
+{
+    // The gain needs to be normalised by the sum of the window, which implicitly
+    // accounts for the length of the transform and the window type. From there
+    // we also update based on hop size: smaller hop means more overlap means the
+    // overall gain should be reduced.
+    double windowSum = 0.0;
+    
+    for(int i = 0; i < windowBufferLength_; i++)
+    {
+        windowSum += windowBuffer_[i];
+    }
+    
+    if(windowSum == 0.0)
+        fftScaleFactor_ = 0.0; // Catch invalid cases and mute output
+    else
+    {
+        switch(hopSelectedSize_)
+        {
+            case kHopSize1Window:   // 0dB
+                fftScaleFactor_ = 1.0/(double)windowSum;
+                break;
+            case kHopSize1_2Window: // -6dB
+                fftScaleFactor_ = 0.5/(double)windowSum;
+                break;
+            case kHopSize1_4Window: // -12dB
+                fftScaleFactor_ = 0.25/(double)windowSum;
+                break;
+            case kHopSize1_8Window: // -18dB
+                fftScaleFactor_ = 0.125/(double)windowSum;
+                break;
+        }
+    }
+}
+
+//==============================================================================
+// This creates new instances of the plugin..
+AudioProcessor* JUCE_CALLTYPE createPluginFilter()
+{
+    return new ADRessAudioProcessor();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AddressPlugin/PluginProcessor.h	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,187 @@
+/*
+  ==============================================================================
+
+    This file was auto-generated!
+
+    It contains the basic startup code for a Juce application.
+
+  ==============================================================================
+*/
+
+#ifndef __PLUGINPROCESSOR_H_4693CB6E__
+#define __PLUGINPROCESSOR_H_4693CB6E__
+
+#include "../JuceLibraryCode/JuceHeader.h"
+#include <fftw3.h>
+#include <complex>
+//==============================================================================
+/**
+*/
+class ADRessAudioProcessor  : public AudioProcessor
+{
+public:
+    //==============================================================================
+    ADRessAudioProcessor();
+    ~ADRessAudioProcessor();
+
+    //==============================================================================
+    void prepareToPlay (double sampleRate, int samplesPerBlock);
+    void releaseResources();
+
+
+    void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
+
+    //==============================================================================
+    AudioProcessorEditor* createEditor();
+    bool hasEditor() const;
+
+    //==============================================================================
+    const String getName() const;
+
+    int getNumParameters();
+
+    float getParameter (int index);
+    void setParameter (int index, float newValue);
+
+    const String getParameterName (int index);
+    const String getParameterText (int index);
+
+    const String getInputChannelName (int channelIndex) const;
+    const String getOutputChannelName (int channelIndex) const;
+    bool isInputChannelStereoPair (int index) const;
+    bool isOutputChannelStereoPair (int index) const;
+
+    bool silenceInProducesSilenceOut() const;
+    bool acceptsMidi() const;
+    bool producesMidi() const;
+    
+    double getTailLengthSeconds() const;
+
+    //==============================================================================
+    int getNumPrograms();
+    int getCurrentProgram();
+    void setCurrentProgram (int index);
+    const String getProgramName (int index);
+    void changeProgramName (int index, const String& newName);
+
+    //==============================================================================
+    void getStateInformation (MemoryBlock& destData);
+    void setStateInformation (const void* data, int sizeInBytes);
+    
+    //==============================================================================
+    
+    // these are used to persist the UI's size - the values are stored along with the
+    // filter's other parameters, and the UI component will update them when it gets
+    // resized.
+    int lastUIWidth_, lastUIHeight_;
+    
+    enum Parameters
+    {
+        kFFTSizeParam = 0,
+        kHopSizeParam,
+        kWindowTypeParam,
+		kWidthParam,
+		kAzimuthParam,
+        kNumParameters
+    };
+    
+    enum Window
+    {
+        kWindowRectangular = 1,
+        kWindowBartlett,
+        kWindowHann,
+        kWindowHamming
+    };
+    
+    enum HopSize
+    {
+        kHopSize1Window = 1,
+        kHopSize1_2Window,
+        kHopSize1_4Window,
+        kHopSize1_8Window
+    };
+    
+    // This parameter indicates the FFT size for phase vocoder computation. It is selected
+    // by the GUI and may temporarily differ from the actual size used in calculations.
+    int fftSelectedSize_;
+    int hopSelectedSize_;       // Hop size, chosen from one of the options above
+    int windowType_;            // Type of window used
+    
+	int /*indL_, indR_,*/ width_, azimuth_, beta_;
+	int indMinL_,indMinR_,indMaxL_,indMaxR_;
+	float invGain_;
+
+	bool computeR_, computeL_;
+	float invBeta_;
+	std::complex<double> i1;
+
+private:
+
+	double azr_[2049][11];
+	double azl_[2049][11];
+	double realR_[2049];
+	double imagR_[2049];
+	double realL_[2049];
+	double imagL_[2049];
+
+    // Methods to initialise and de-initialise the FFT machinery
+    void initFFT(int length);
+    void deinitFFT();
+    
+    // Methods to initialise and de-initialise the window
+    void initWindow(int length, int windowType);
+    void deinitWindow();
+    
+    // Methods to update the buffering for the given hop size and the output scaling
+    void updateHopSize();
+    void updateScaleFactor();
+    
+    // Whether the FFT has been initialised and is therefore ready to go
+    bool fftInitialised_;
+    
+    // Variables for calculating the FFT and IFFT: complex data structures and the
+    // "plan" used by the fftw library to calculate the transforms.
+    fftw_complex *fftTimeDomain_, *fftFrequencyDomain_;
+    fftw_plan fftForwardPlan_, fftBackwardPlan_;
+    
+    // Size of the FFT (generally a power of two) and the hop size (in samples, generally a fraction of FFT size)
+    int fftActualTransformSize_;
+    int hopActualSize_;
+    
+    // Amount by which to scale_ the inverse FFT to return to original amplitude: depends on the
+    // transform size (because of fftw implementation) and the hop size (because of inherent overlap)
+    double fftScaleFactor_;
+    
+    // Circular buffer gathers audio samples from the input until enough are available
+    // for the FFT calculation
+    AudioSampleBuffer inputBuffer_;
+    int inputBufferLength_;
+    int inputBufferWritePosition_;
+    
+    // Circular buffer that collects output samples from the FFT overlap-add process
+    // before they are ready to be sent to the output stream
+    AudioSampleBuffer outputBuffer_;
+    int outputBufferLength_;
+    int outputBufferReadPosition_, outputBufferWritePosition_;
+    
+    // How many samples since the last FFT?
+    int samplesSinceLastFFT_;
+    
+    // Stored window function for pre-processing input frames
+    double *windowBuffer_;
+    int windowBufferLength_;
+    
+    // Whether or not prepareToPlay() has been called, i.e. that resources are in use
+    bool preparedToPlay_;
+    
+    // Spin lock that prevents the FFT settings from changing in the middle of the audio
+    // thread.
+    SpinLock fftSpinLock_;
+
+	void changeParams();
+    
+    //==============================================================================
+    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ADRessAudioProcessor);
+};
+
+#endif  // __PLUGINPROCESSOR_H_4693CB6E__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BassPedalRackPlugin/BassPedalRack.jucer	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<JUCERPROJECT id="AC7ScK" name="BassPedalRack" projectType="audioplug" version="2.0.0"
+              bundleIdentifier="BPREffect" buildVST="1" buildRTAS="0" buildAU="0"
+              pluginName="BPR" pluginDesc="Selective Chebychev Distortion and Tone Control"
+              pluginManufacturer="JYs&amp;M" pluginManufacturerCode="JYsM"
+              pluginCode="bpr" pluginChannelConfigs="{1, 1}, {2, 2}" pluginIsSynth="0"
+              pluginWantsMidiIn="0" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="1"
+              pluginTailLength="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="bprAU"
+              pluginAUViewClass="emptyAU_V1" pluginRTASCategory="" jucerVersion="3.0.0"
+              companyName="JYs&amp;M" aaxIdentifier="com.yourcompany.empty"
+              pluginAAXCategory="AAX_ePlugInCategory_Dynamics">
+  <EXPORTFORMATS>
+    <VS2010 targetFolder="Builds/VisualStudio2010" libraryType="1" juceFolder="C:\Users\Spook's\Desktop\QMUL\DAFX\Assignments\AS3\juce-latest\juce\modules"
+            vstFolder="C:\Users\Spook's\Desktop\QMUL\DAFX\Assignments\AS3\vstsdk2.4">
+      <CONFIGURATIONS>
+        <CONFIGURATION name="Debug" winWarningLevel="4" generateManifest="1" winArchitecture="32-bit"
+                       isDebug="1" optimisation="1" targetName="bpr"/>
+        <CONFIGURATION name="Release" winWarningLevel="4" generateManifest="1" winArchitecture="32-bit"
+                       isDebug="0" optimisation="2" targetName="bpr"/>
+      </CONFIGURATIONS>
+    </VS2010>
+  </EXPORTFORMATS>
+  <MAINGROUP id="oVUVUz" name="BassPedalRack">
+    <GROUP id="{F4483B04-0E7A-D77C-795E-A491F61E239B}" name="Source">
+      <FILE id="d7EIMU" name="PluginProcessor.cpp" compile="1" resource="0"
+            file="Source/PluginProcessor.cpp"/>
+      <FILE id="YDAD0P" name="PluginProcessor.h" compile="0" resource="0"
+            file="Source/PluginProcessor.h"/>
+      <FILE id="VTO1E6" name="PluginEditor.cpp" compile="1" resource="0"
+            file="Source/PluginEditor.cpp"/>
+      <FILE id="mhOgcd" name="PluginEditor.h" compile="0" resource="0" file="Source/PluginEditor.h"/>
+    </GROUP>
+  </MAINGROUP>
+  <MODULES>
+    <MODULE id="juce_core" showAllCode="1" useLocalCopy="0"/>
+    <MODULE id="juce_events" showAllCode="1" useLocalCopy="0"/>
+    <MODULE id="juce_graphics" showAllCode="1" useLocalCopy="0"/>
+    <MODULE id="juce_gui_basics" showAllCode="1" useLocalCopy="0"/>
+    <MODULE id="juce_gui_extra" showAllCode="1" useLocalCopy="0"/>
+    <MODULE id="juce_gui_audio" showAllCode="1" useLocalCopy="1"/>
+    <MODULE id="juce_audio_basics" showAllCode="1" useLocalCopy="0"/>
+    <MODULE id="juce_audio_formats" showAllCode="1" useLocalCopy="0"/>
+    <MODULE id="juce_audio_processors" showAllCode="1" useLocalCopy="0"/>
+    <MODULE id="juce_audio_plugin_client" showAllCode="1" useLocalCopy="0"/>
+    <MODULE id="juce_data_structures" showAllCode="1" useLocalCopy="0"/>
+  </MODULES>
+  <JUCEOPTIONS JUCE_QUICKTIME="disabled"/>
+</JUCERPROJECT>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BassPedalRackPlugin/ParametersRecap.txt	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,37 @@
+Parameters recap:
+
+-lowCut: 	cutoff frequency of the low pass filter.
+			0 to 10. 
+			0 is no filter. 
+			10  is no output. 
+			1 to 9 increases the cutoff frequency.
+			
+-highCut: 	cutoff frequency of the high pass filter.
+			0 to 10. 
+			0 is no filter. 
+			10  is no output. 
+			1 to 9 increases the cutoff frequency.
+			
+-index: 	distortion index
+			0 to 5.
+			0 no signal
+			1 basic distortion
+			preprocess x =x*index before distortion
+			
+-gain1-9:	gain of the Nth Chebychev polynomial
+			0 to 5
+			0 no gain at the polynomial
+			correspond to the gain of the Nth harmonic
+			
+-mix:		mixing value between filtered low frequencies and distorted filterd high frequencies
+			0 to 1
+			0 is only output from low pass filter
+			0.5 is balance between both
+			1 is only output from distorted high pass filter
+			
+-treble,	gain of the three tone control knobs
+ mid,		0 to 1
+ low		0 is minimum
+			0.5 is neutral (although still does not have a falt frequency response)
+			1 is maximum
+			
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BassPedalRackPlugin/PluginEditor.cpp	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,224 @@
+/*
+  ==============================================================================
+
+    This file was auto-generated by the Introjucer!
+
+    It contains the basic startup code for a Juce application.
+
+  ==============================================================================
+*/
+
+#include "PluginProcessor.h"
+#include "PluginEditor.h"
+
+
+//==============================================================================
+BassPedalRackProcessorEditor::BassPedalRackProcessorEditor (BassPedalRackProcessor* ownerFilter)
+    : AudioProcessorEditor (ownerFilter),
+
+	  
+	  lowCutLabel_("","LowCut:"),
+	  lowCutSlider_("lowcut"),
+	  highCutLabel_("","HighCut:"),
+	  highCutSlider_("highcut"),
+	  
+	  indexLabel_("", "Index:"),
+      indexSlider_("index"),	  
+      gain1Label_("", "Gain1:"),
+      gain1Slider_("gain1"),
+	  gain2Label_("", "Gain2:"),
+      gain2Slider_("gain2"),
+	  gain3Label_("", "Gain3:"),
+      gain3Slider_("gain3"),
+	  gain4Label_("", "Gain4:"),
+      gain4Slider_("gain4"),
+	  gain5Label_("", "Gain5:"),
+      gain5Slider_("gain5"),
+	  gain6Label_("", "Gain6:"),
+      gain6Slider_("gain6"),
+	  gain7Label_("", "Gain7:"),
+      gain7Slider_("gain7"),
+	  gain8Label_("", "Gain8:"),
+      gain8Slider_("gain8"),
+	  gain9Label_("", "Gain9:"),
+      gain9Slider_("gain9"),
+	  
+	  mixLabel_("", "Mix:"),
+      mixSlider_("mix"),
+	  
+	  gainTreLabel_("", "Treble:"),
+      gainTreSlider_("treble"),
+	  gainLowLabel_("", "Low:"),
+      gainLowSlider_("low"),
+	  gainMidLabel_("", "Mid:"),
+      gainMidSlider_("mid"),
+	  
+	  gainLabel_("", "Gain:"),
+      gainSlider_("gain")
+{
+    // This is where our plugin's editor size is set.
+    // setSize(170, 80);
+    
+    // Set up the sliders
+    addAndMakeVisible(&lowCutSlider_); lowCutSlider_.setSliderStyle(Slider::Rotary); lowCutSlider_.addListener(this);
+	lowCutSlider_.setRange(0, 10, 1); lowCutLabel_.attachToComponent(&lowCutSlider_, false); lowCutLabel_.setFont(Font (11.0f));
+	
+	addAndMakeVisible(&highCutSlider_); highCutSlider_.setSliderStyle(Slider::Rotary); highCutSlider_.addListener(this);
+	highCutSlider_.setRange(0, 10, 1); highCutLabel_.attachToComponent(&highCutSlider_, false); highCutLabel_.setFont(Font (11.0f));
+
+    addAndMakeVisible(&indexSlider_); indexSlider_.setSliderStyle(Slider::Rotary); indexSlider_.addListener(this);
+    indexSlider_.setRange(0.0, 5.0, 0.01); indexLabel_.attachToComponent(&indexSlider_, false); indexLabel_.setFont(Font (11.0f));
+
+	addAndMakeVisible(&gain1Slider_); gain1Slider_.setSliderStyle(Slider::Rotary); gain1Slider_.addListener(this);
+    gain1Slider_.setRange(0.0, 5.0, 0.01); gain1Label_.attachToComponent(&gain1Slider_, false); gain1Label_.setFont(Font (11.0f));
+	addAndMakeVisible(&gain2Slider_); gain2Slider_.setSliderStyle(Slider::Rotary); gain2Slider_.addListener(this);
+    gain2Slider_.setRange(0.0, 5.0, 0.01); gain2Label_.attachToComponent(&gain2Slider_, false); gain2Label_.setFont(Font (11.0f));
+	addAndMakeVisible(&gain3Slider_); gain3Slider_.setSliderStyle(Slider::Rotary); gain3Slider_.addListener(this);
+    gain3Slider_.setRange(0.0, 5.0, 0.01); gain3Label_.attachToComponent(&gain3Slider_, false); gain3Label_.setFont(Font (11.0f));
+	addAndMakeVisible(&gain4Slider_); gain4Slider_.setSliderStyle(Slider::Rotary); gain4Slider_.addListener(this);
+    gain4Slider_.setRange(0.0, 5.0, 0.01); gain4Label_.attachToComponent(&gain4Slider_, false); gain4Label_.setFont(Font (11.0f));
+	addAndMakeVisible(&gain5Slider_); gain5Slider_.setSliderStyle(Slider::Rotary); gain5Slider_.addListener(this);
+    gain5Slider_.setRange(0.0, 5.0, 0.01); gain5Label_.attachToComponent(&gain5Slider_, false); gain5Label_.setFont(Font (11.0f)); 
+	addAndMakeVisible(&gain6Slider_); gain6Slider_.setSliderStyle(Slider::Rotary); gain6Slider_.addListener(this);
+    gain6Slider_.setRange(0.0, 5.0, 0.01); gain6Label_.attachToComponent(&gain6Slider_, false); gain6Label_.setFont(Font (11.0f));
+	addAndMakeVisible(&gain7Slider_); gain7Slider_.setSliderStyle(Slider::Rotary); gain7Slider_.addListener(this);
+    gain7Slider_.setRange(0.0, 5.0, 0.01); gain7Label_.attachToComponent(&gain7Slider_, false); gain7Label_.setFont(Font (11.0f));
+	addAndMakeVisible(&gain8Slider_); gain8Slider_.setSliderStyle(Slider::Rotary); gain8Slider_.addListener(this);
+    gain8Slider_.setRange(0.0, 5.0, 0.01); gain8Label_.attachToComponent(&gain8Slider_, false); gain8Label_.setFont(Font (11.0f));
+	addAndMakeVisible(&gain9Slider_); gain9Slider_.setSliderStyle(Slider::Rotary); gain9Slider_.addListener(this);
+    gain9Slider_.setRange(0.0, 5.0, 0.01); gain9Label_.attachToComponent(&gain9Slider_, false); gain9Label_.setFont(Font (11.0f));
+
+
+    addAndMakeVisible(&mixSlider_); mixSlider_.setSliderStyle(Slider::Rotary); mixSlider_.addListener(this);
+    mixSlider_.setRange(0.0, 1.0, 0.001); mixLabel_.attachToComponent(&mixSlider_, false); mixLabel_.setFont(Font (11.0f));
+	
+    addAndMakeVisible(&gainTreSlider_); gainTreSlider_.setSliderStyle(Slider::Rotary); gainTreSlider_.addListener(this);
+    gainTreSlider_.setRange(0.0, 1.0, 0.001); gainTreLabel_.attachToComponent(&gainTreSlider_, false); gainTreLabel_.setFont(Font (11.0f));
+    addAndMakeVisible(&gainMidSlider_); gainMidSlider_.setSliderStyle(Slider::Rotary); gainMidSlider_.addListener(this);
+    gainMidSlider_.setRange(0.0, 1.0, 0.001); gainMidLabel_.attachToComponent(&gainMidSlider_, false); gainMidLabel_.setFont(Font (11.0f));
+    addAndMakeVisible(&gainLowSlider_); gainLowSlider_.setSliderStyle(Slider::Rotary); gainLowSlider_.addListener(this);
+    gainLowSlider_.setRange(0.0, 1.0, 0.001); gainLowLabel_.attachToComponent(&gainLowSlider_, false); gainLowLabel_.setFont(Font (11.0f));
+	
+    addAndMakeVisible(&gainSlider_); gainSlider_.setSliderStyle(Slider::Rotary); gainSlider_.addListener(this);
+    gainSlider_.setRange(0.0, 10.0, 0.001); gainLabel_.attachToComponent(&gainSlider_, false); gainLabel_.setFont(Font (11.0f));
+    
+    // add the triangular resizer component for the bottom-right of the UI
+    addAndMakeVisible(resizer_ = new ResizableCornerComponent (this, &resizeLimits_));
+    resizeLimits_.setSizeLimits(300, 200, 800, 600);
+    
+    // set our component's initial size to be the last one that was stored in the filter's settings
+    setSize(ownerFilter->lastUIWidth_,
+            ownerFilter->lastUIHeight_);
+    
+    startTimer(50);
+}
+
+BassPedalRackProcessorEditor::~BassPedalRackProcessorEditor()
+{
+}
+
+//==============================================================================
+void BassPedalRackProcessorEditor::paint (Graphics& g)
+{
+    g.fillAll (Colours::grey);
+}
+
+void BassPedalRackProcessorEditor::resized()
+{
+
+	lowCutSlider_.setBounds(20, 20, 150, 40);
+	highCutSlider_.setBounds(200, 20, 150, 40);
+	mixSlider_.setBounds(380, 20, 150, 40);
+	
+	indexSlider_.setBounds(200, 75, 150, 40);
+	gain1Slider_.setBounds(380, 75, 150, 40);
+	gain2Slider_.setBounds(200, 130, 150, 40);
+	gain3Slider_.setBounds(380, 130, 150, 40);
+	gain4Slider_.setBounds(200, 185, 150, 40);
+	gain5Slider_.setBounds(380, 185, 150, 40);
+	gain6Slider_.setBounds(200, 240, 150, 40);
+	gain7Slider_.setBounds(380, 240, 150, 40);
+    gain8Slider_.setBounds(200, 295, 150, 40);
+	gain9Slider_.setBounds(380, 295, 150, 40);
+
+	
+	
+
+	gainTreSlider_.setBounds(20,185,150, 40);
+	gainMidSlider_.setBounds(20,240,150, 40);
+	gainLowSlider_.setBounds(20,295,150, 40);
+
+	gainSlider_.setBounds(20, 75, 150, 40);
+	
+    resizer_->setBounds(getWidth() - 16, getHeight() - 16, 16, 16);
+    
+    getProcessor()->lastUIWidth_ = getWidth();
+    getProcessor()->lastUIHeight_ = getHeight();
+}
+
+//==============================================================================
+// This timer periodically checks whether any of the filter's parameters have changed...
+void BassPedalRackProcessorEditor::timerCallback()
+{
+    BassPedalRackProcessor* ourProcessor = getProcessor();
+    
+	mixSlider_.setValue(ourProcessor->mix_, dontSendNotification);
+	indexSlider_.setValue(ourProcessor->index_, dontSendNotification);
+	gainSlider_.setValue(ourProcessor->gain_, dontSendNotification);
+	lowCutSlider_.setValue(ourProcessor->lowCut_, dontSendNotification);
+	highCutSlider_.setValue(ourProcessor->highCut_, dontSendNotification);
+	gainLowSlider_.setValue(ourProcessor->bassGain_, dontSendNotification);
+	gainMidSlider_.setValue(ourProcessor->midGain_, dontSendNotification);
+	gainTreSlider_.setValue(ourProcessor->trebleGain_, dontSendNotification);
+	gain1Slider_.setValue(ourProcessor->gain1_, dontSendNotification);
+	gain2Slider_.setValue(ourProcessor->gain2_, dontSendNotification);
+	gain3Slider_.setValue(ourProcessor->gain3_, dontSendNotification);
+	gain4Slider_.setValue(ourProcessor->gain4_, dontSendNotification);
+	gain5Slider_.setValue(ourProcessor->gain5_, dontSendNotification);
+	gain6Slider_.setValue(ourProcessor->gain6_, dontSendNotification);
+	gain7Slider_.setValue(ourProcessor->gain7_, dontSendNotification);
+	gain8Slider_.setValue(ourProcessor->gain8_, dontSendNotification);
+	gain9Slider_.setValue(ourProcessor->gain9_, dontSendNotification);
+}
+
+// This is our Slider::Listener callback, when the user drags a slider.
+void BassPedalRackProcessorEditor::sliderValueChanged (Slider* slider)
+{
+    if (slider == &mixSlider_){
+        // It's vital to use setParameterNotifyingHost to change any parameters that are automatable
+        // by the host, rather than just modifying them directly, otherwise the host won't know
+        // that they've changed.
+        getProcessor()->setParameterNotifyingHost (BassPedalRackProcessor::kMixParam,(float)mixSlider_.getValue());}
+	if (slider == &lowCutSlider_){
+        getProcessor()->setParameterNotifyingHost (BassPedalRackProcessor::kLowCutParam,(float)lowCutSlider_.getValue());}
+	if (slider == &highCutSlider_){
+        getProcessor()->setParameterNotifyingHost (BassPedalRackProcessor::kHighCutParam,(float)highCutSlider_.getValue());}
+	if (slider == &indexSlider_){
+        getProcessor()->setParameterNotifyingHost (BassPedalRackProcessor::kIndexParam,(float)indexSlider_.getValue());}
+	if (slider == &gainSlider_){
+        getProcessor()->setParameterNotifyingHost (BassPedalRackProcessor::kGainParam,(float)gainSlider_.getValue());}
+	if (slider == &gainMidSlider_){
+        getProcessor()->setParameterNotifyingHost (BassPedalRackProcessor::kGainMidParam,(float)gainMidSlider_.getValue());}	
+	if (slider == &gainLowSlider_){
+        getProcessor()->setParameterNotifyingHost (BassPedalRackProcessor::kGainLowParam,(float)gainLowSlider_.getValue());}	
+	if (slider == &gainTreSlider_){
+        getProcessor()->setParameterNotifyingHost (BassPedalRackProcessor::kGainTreParam,(float)gainTreSlider_.getValue());}	
+	if (slider == &gain1Slider_){
+		getProcessor()->setParameterNotifyingHost (BassPedalRackProcessor::kGain1Param,(float)gain1Slider_.getValue());}
+	if (slider == &gain2Slider_){
+		getProcessor()->setParameterNotifyingHost (BassPedalRackProcessor::kGain2Param,(float)gain2Slider_.getValue());}
+	if (slider == &gain3Slider_){
+		getProcessor()->setParameterNotifyingHost (BassPedalRackProcessor::kGain3Param,(float)gain3Slider_.getValue());}
+	if (slider == &gain4Slider_){
+		getProcessor()->setParameterNotifyingHost (BassPedalRackProcessor::kGain4Param,(float)gain4Slider_.getValue());}
+	if (slider == &gain5Slider_){
+		getProcessor()->setParameterNotifyingHost (BassPedalRackProcessor::kGain5Param,(float)gain5Slider_.getValue());}
+	if (slider == &gain6Slider_){
+		getProcessor()->setParameterNotifyingHost (BassPedalRackProcessor::kGain6Param,(float)gain6Slider_.getValue());}
+	if (slider == &gain7Slider_){
+		getProcessor()->setParameterNotifyingHost (BassPedalRackProcessor::kGain7Param,(float)gain7Slider_.getValue());}
+	if (slider == &gain8Slider_){
+		getProcessor()->setParameterNotifyingHost (BassPedalRackProcessor::kGain8Param,(float)gain8Slider_.getValue());}
+	if (slider == &gain9Slider_){
+		getProcessor()->setParameterNotifyingHost (BassPedalRackProcessor::kGain9Param,(float)gain9Slider_.getValue());}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BassPedalRackPlugin/PluginEditor.h	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,85 @@
+/*
+  ==============================================================================
+
+    This file was auto-generated by the Introjucer!
+
+    It contains the basic startup code for a Juce application.
+
+  ==============================================================================
+*/
+
+#ifndef __PLUGINEDITOR_H_6E48F605__
+#define __PLUGINEDITOR_H_6E48F605__
+
+#include "../JuceLibraryCode/JuceHeader.h"
+#include "PluginProcessor.h"
+
+
+//==============================================================================
+
+class BassPedalRackProcessorEditor  : public AudioProcessorEditor,
+                                   public SliderListener,
+                                   public Timer
+{
+public:
+    BassPedalRackProcessorEditor (BassPedalRackProcessor* ownerFilter);
+    ~BassPedalRackProcessorEditor();
+
+    //==============================================================================
+    // This is just a standard Juce paint method...
+    void timerCallback();
+    void paint (Graphics& g);
+    void resized();
+    void sliderValueChanged (Slider*);
+    
+private:
+	Label mixLabel_;
+	Slider mixSlider_;
+
+	Label lowCutLabel_;
+	Slider lowCutSlider_;
+
+	Label gainTreLabel_;
+	Slider gainTreSlider_;
+	Label gainLowLabel_;
+	Slider gainLowSlider_;
+	Label gainMidLabel_;
+	Slider gainMidSlider_;
+
+	Label highCutLabel_;
+	Slider highCutSlider_;
+
+	Label gainLabel_;
+    Slider gainSlider_;
+	
+	Label indexLabel_;
+    Slider indexSlider_;
+	Label gain1Label_;
+    Slider gain1Slider_;
+	Label gain2Label_;
+    Slider gain2Slider_;
+	Label gain3Label_;
+    Slider gain3Slider_;
+	Label gain4Label_;
+    Slider gain4Slider_;
+	Label gain5Label_;
+    Slider gain5Slider_;
+	Label gain6Label_;
+    Slider gain6Slider_;
+	Label gain7Label_;
+    Slider gain7Slider_;
+	Label gain8Label_;
+    Slider gain8Slider_;
+	Label gain9Label_;
+    Slider gain9Slider_;
+
+    ScopedPointer<ResizableCornerComponent> resizer_;
+    ComponentBoundsConstrainer resizeLimits_;
+    BassPedalRackProcessor* getProcessor() const
+    {
+        return static_cast <BassPedalRackProcessor*> (getAudioProcessor());
+    }
+};
+
+
+#endif  // __PLUGINEDITOR_H_6E48F605__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BassPedalRackPlugin/PluginProcessor.cpp	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,841 @@
+/*
+  ==============================================================================
+
+    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();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BassPedalRackPlugin/PluginProcessor.h	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,162 @@
+/*
+  ==============================================================================
+
+    This file was auto-generated!
+
+    It contains the basic startup code for a Juce application.
+
+  ==============================================================================
+*/
+
+#ifndef __PLUGINPROCESSOR_H_4693CB6E__
+#define __PLUGINPROCESSOR_H_4693CB6E__
+
+#include "../JuceLibraryCode/JuceHeader.h"
+
+
+//==============================================================================
+/**
+*/
+class BassPedalRackProcessor  : public AudioProcessor
+{
+public:
+    //==============================================================================
+    BassPedalRackProcessor();
+    ~BassPedalRackProcessor();
+
+    //==============================================================================
+    void prepareToPlay (double sampleRate, int samplesPerBlock);
+    void releaseResources();
+
+    void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
+
+    //==============================================================================
+    AudioProcessorEditor* createEditor();
+    bool hasEditor() const;
+
+    //==============================================================================
+    const String getName() const;
+
+    int getNumParameters();
+
+    float getParameter (int index);
+    void setParameter (int index, float newValue);
+
+    const String getParameterName (int index);
+    const String getParameterText (int index);
+
+    const String getInputChannelName (int channelIndex) const;
+    const String getOutputChannelName (int channelIndex) const;
+    bool isInputChannelStereoPair (int index) const;
+    bool isOutputChannelStereoPair (int index) const;
+
+    bool silenceInProducesSilenceOut() const;
+    bool acceptsMidi() const;
+    bool producesMidi() const;
+    
+    double getTailLengthSeconds() const;
+
+    //==============================================================================
+    int getNumPrograms();
+    int getCurrentProgram();
+    void setCurrentProgram (int index);
+    const String getProgramName (int index);
+    void changeProgramName (int index, const String& newName);
+
+    //==============================================================================
+    void getStateInformation (MemoryBlock& destData);
+    void setStateInformation (const void* data, int sizeInBytes);
+    
+    //==============================================================================
+    
+    // these are used to persist the UI's size - the values are stored along with the
+    // filter's other parameters, and the UI component will update them when it gets
+    // resized.
+    int lastUIWidth_, lastUIHeight_;
+
+
+
+    enum Parameters
+    {
+        kMixParam = 0,
+		kLowCutParam,
+		kIndexParam,
+		kGainParam,
+		kHighCutParam,
+		kGainTreParam,
+		kGainMidParam,
+		kGainLowParam,
+		kGain1Param,
+		kGain2Param,
+		kGain3Param,
+		kGain4Param,
+		kGain5Param,
+		kGain6Param,
+		kGain7Param,
+		kGain8Param,
+		kGain9Param,
+        kNumParameters
+    };
+    //Distortion related parameters
+	float index_;		//Distortion index (x = x*index_)
+	//gainN is the gain of the Nth Chebychev polynomial => gain of the Nth harmonic for a sinusoid
+	float gain1_, gain2_, gain3_, gain4_, gain5_, gain6_, gain7_, gain8_, gain9_;
+	
+	float gain_;		//Overall gain of the amp => volume
+	
+	int lowCut_, highCut_;	//indices of the low pass filter (0 is allpass, max is nopass)
+	float mix_;			//Mix between the low and high (0 is only low, 1 is only high)
+	
+	float bassGain_, midGain_, trebleGain_;  //gains for Low, Mid and Treble
+	
+private:
+
+//Variables for tones
+	    //temp variable for polynomial of tone control
+		//lower case for transfer function, capital for filter coefficent
+		//RC is the system's characterstic time (2 and 3 are respectivly square and cube of that)
+	double a1_, a2_, a3_, b1_, b2_, b3_, RC_, RC2_, RC3_, A0,A1,A2,A3,B0,B1,B2,B3;
+	double fsd_, fsd2_, fsd3_;//sampling frequency, then squared and cubed
+	int a0_;
+	    //Circular Buffers
+	double memIn_[3]; //input
+	double memOut_[3]; //output
+	int currInd_; //indice in the circular buffers 
+		//Memory for stereo
+	double tonStackIn_[6];  //input
+	double tonStackOut_[6];  //output
+
+	bool toneStack_, shaper_; //if tone Stack(or shaper) is applied
+	
+//Variables for Chebychev distortion
+	double coeffs_[10]; //Coefficient fo the polynomial
+	float scale_; //scale to attenuate the gain of the distortion
+	
+//Variables for high and low pass filters
+	double lastIn_[151];   //input circular buffer
+	double inputMem_[302]; //Memory for stereo
+	int filterLength_;     //length of the filters
+	int filterInd_;        //indice for the circular buffer
+	
+	
+	//Update distortion coefficients 
+	void changeCoefficients(int kcase); //kcase enable to only update relevant coefficients
+	//Update the tone coefficients
+	void changeToneStack();
+	//Save and load previous buffer for stereo handling
+	void saveMem(int channel);
+	void loadMem(int channel);
+	
+	//Apply low and high pass filter
+	double* applyFilter(float input);
+	//Apply Chebychev Distotion
+	float shaper(float x);
+	//Apply Tone control
+	float applyToneStack(float);
+
+    //==============================================================================
+    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BassPedalRackProcessor);
+	
+};
+
+#endif  // __PLUGINPROCESSOR_H_4693CB6E__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BassPedalRackPlugin/filter.h	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,2825 @@
+/*******************************************************************************
+* FILENAME
+*   highpass_table.h
+*
+* DESCRIPTION
+*   Header File for table of FIR filters 
+*
+*******************************************************************************/
+
+#ifndef HIGHPASS_TABLE_H
+#define HIGHPASS_TABLE_H
+
+
+/*-----------------------------------------------------------------------*/
+/* highpass 1 FIR filter */
+/*-----------------------------------------------------------------------*/
+const double filter_high_1[] = {
+	-0.00017322,
+	-0.00017432,
+	-0.00017717,
+	-0.00018177,
+	-0.00018812,
+	-0.00019621,
+	-0.00020605,
+	-0.00021761,
+	-0.00023088,
+	-0.00024585,
+	-0.00026249,
+	-0.00028078,
+	-0.00030070,
+	-0.00032220,
+	-0.00034527,
+	-0.00036986,
+	-0.00039593,
+	-0.00042344,
+	-0.00045236,
+	-0.00048262,
+	-0.00051418,
+	-0.00054699,
+	-0.00058099,
+	-0.00061612,
+	-0.00065233,
+	-0.00068956,
+	-0.00072773,
+	-0.00076679,
+	-0.00080666,
+	-0.00084728,
+	-0.00088858,
+	-0.00093048,
+	-0.00097292,
+	-0.00101581,
+	-0.00105908,
+	-0.00110267,
+	-0.00114648,
+	-0.00119044,
+	-0.00123447,
+	-0.00127851,
+	-0.00132246,
+	-0.00136624,
+	-0.00140980,
+	-0.00145303,
+	-0.00149587,
+	-0.00153824,
+	-0.00158007,
+	-0.00162127,
+	-0.00166178,
+	-0.00170152,
+	-0.00174042,
+	-0.00177841,
+	-0.00181543,
+	-0.00185140,
+	-0.00188626,
+	-0.00191994,
+	-0.00195240,
+	-0.00198356,
+	-0.00201337,
+	-0.00204179,
+	-0.00206874,
+	-0.00209420,
+	-0.00211811,
+	-0.00214042,
+	-0.00216110,
+	-0.00218011,
+	-0.00219742,
+	-0.00221299,
+	-0.00222679,
+	-0.00223881,
+	-0.00224901,
+	-0.00225739,
+	-0.00226392,
+	-0.00226859,
+	-0.00227140,
+	0.99755456,
+	-0.00227140,
+	-0.00226859,
+	-0.00226392,
+	-0.00225739,
+	-0.00224901,
+	-0.00223881,
+	-0.00222679,
+	-0.00221299,
+	-0.00219742,
+	-0.00218011,
+	-0.00216110,
+	-0.00214042,
+	-0.00211811,
+	-0.00209420,
+	-0.00206874,
+	-0.00204179,
+	-0.00201337,
+	-0.00198356,
+	-0.00195240,
+	-0.00191994,
+	-0.00188626,
+	-0.00185140,
+	-0.00181543,
+	-0.00177841,
+	-0.00174042,
+	-0.00170152,
+	-0.00166178,
+	-0.00162127,
+	-0.00158007,
+	-0.00153824,
+	-0.00149587,
+	-0.00145303,
+	-0.00140980,
+	-0.00136624,
+	-0.00132246,
+	-0.00127851,
+	-0.00123447,
+	-0.00119044,
+	-0.00114648,
+	-0.00110267,
+	-0.00105908,
+	-0.00101581,
+	-0.00097292,
+	-0.00093048,
+	-0.00088858,
+	-0.00084728,
+	-0.00080666,
+	-0.00076679,
+	-0.00072773,
+	-0.00068956,
+	-0.00065233,
+	-0.00061612,
+	-0.00058099,
+	-0.00054699,
+	-0.00051418,
+	-0.00048262,
+	-0.00045236,
+	-0.00042344,
+	-0.00039593,
+	-0.00036986,
+	-0.00034527,
+	-0.00032220,
+	-0.00030070,
+	-0.00028078,
+	-0.00026249,
+	-0.00024585,
+	-0.00023088,
+	-0.00021761,
+	-0.00020605,
+	-0.00019621,
+	-0.00018812,
+	-0.00018177,
+	-0.00017717,
+	-0.00017432,
+	-0.00017432};
+
+/*-----------------------------------------------------------------------*/
+/* highpass 2 FIR filter */
+/*-----------------------------------------------------------------------*/
+const double filter_high_2[] = {
+	-0.00029791,
+	-0.00030106,
+	-0.00030725,
+	-0.00031651,
+	-0.00032888,
+	-0.00034438,
+	-0.00036304,
+	-0.00038487,
+	-0.00040988,
+	-0.00043805,
+	-0.00046939,
+	-0.00050388,
+	-0.00054150,
+	-0.00058222,
+	-0.00062599,
+	-0.00067278,
+	-0.00072254,
+	-0.00077520,
+	-0.00083071,
+	-0.00088899,
+	-0.00094996,
+	-0.00101354,
+	-0.00107963,
+	-0.00114814,
+	-0.00121897,
+	-0.00129200,
+	-0.00136712,
+	-0.00144421,
+	-0.00152314,
+	-0.00160378,
+	-0.00168600,
+	-0.00176966,
+	-0.00185461,
+	-0.00194071,
+	-0.00202780,
+	-0.00211574,
+	-0.00220435,
+	-0.00229349,
+	-0.00238300,
+	-0.00247270,
+	-0.00256244,
+	-0.00265204,
+	-0.00274135,
+	-0.00283019,
+	-0.00291839,
+	-0.00300580,
+	-0.00309225,
+	-0.00317756,
+	-0.00326158,
+	-0.00334415,
+	-0.00342511,
+	-0.00350430,
+	-0.00358156,
+	-0.00365675,
+	-0.00372972,
+	-0.00380033,
+	-0.00386844,
+	-0.00393392,
+	-0.00399663,
+	-0.00405645,
+	-0.00411327,
+	-0.00416697,
+	-0.00421745,
+	-0.00426461,
+	-0.00430834,
+	-0.00434857,
+	-0.00438522,
+	-0.00441821,
+	-0.00444747,
+	-0.00447296,
+	-0.00449461,
+	-0.00451238,
+	-0.00452624,
+	-0.00453616,
+	-0.00454212,
+	0.99515881,
+	-0.00454212,
+	-0.00453616,
+	-0.00452624,
+	-0.00451238,
+	-0.00449461,
+	-0.00447296,
+	-0.00444747,
+	-0.00441821,
+	-0.00438522,
+	-0.00434857,
+	-0.00430834,
+	-0.00426461,
+	-0.00421745,
+	-0.00416697,
+	-0.00411327,
+	-0.00405645,
+	-0.00399663,
+	-0.00393392,
+	-0.00386844,
+	-0.00380033,
+	-0.00372972,
+	-0.00365675,
+	-0.00358156,
+	-0.00350430,
+	-0.00342511,
+	-0.00334415,
+	-0.00326158,
+	-0.00317756,
+	-0.00309225,
+	-0.00300580,
+	-0.00291839,
+	-0.00283019,
+	-0.00274135,
+	-0.00265204,
+	-0.00256244,
+	-0.00247270,
+	-0.00238300,
+	-0.00229349,
+	-0.00220435,
+	-0.00211574,
+	-0.00202780,
+	-0.00194071,
+	-0.00185461,
+	-0.00176966,
+	-0.00168600,
+	-0.00160378,
+	-0.00152314,
+	-0.00144421,
+	-0.00136712,
+	-0.00129200,
+	-0.00121897,
+	-0.00114814,
+	-0.00107963,
+	-0.00101354,
+	-0.00094996,
+	-0.00088899,
+	-0.00083071,
+	-0.00077520,
+	-0.00072254,
+	-0.00067278,
+	-0.00062599,
+	-0.00058222,
+	-0.00054150,
+	-0.00050388,
+	-0.00046939,
+	-0.00043805,
+	-0.00040988,
+	-0.00038487,
+	-0.00036304,
+	-0.00034438,
+	-0.00032888,
+	-0.00031651,
+	-0.00030725,
+	-0.00030106,
+	-0.00030106};
+
+/*-----------------------------------------------------------------------*/
+/* highpass 3 FIR filter */
+/*-----------------------------------------------------------------------*/
+const double filter_high_3[] = {
+	-0.00028555,
+	-0.00029609,
+	-0.00030978,
+	-0.00032689,
+	-0.00034768,
+	-0.00037238,
+	-0.00040124,
+	-0.00043449,
+	-0.00047233,
+	-0.00051497,
+	-0.00056260,
+	-0.00061540,
+	-0.00067352,
+	-0.00073711,
+	-0.00080629,
+	-0.00088117,
+	-0.00096184,
+	-0.00104836,
+	-0.00114080,
+	-0.00123916,
+	-0.00134347,
+	-0.00145370,
+	-0.00156983,
+	-0.00169179,
+	-0.00181951,
+	-0.00195288,
+	-0.00209179,
+	-0.00223608,
+	-0.00238558,
+	-0.00254012,
+	-0.00269947,
+	-0.00286342,
+	-0.00303170,
+	-0.00320406,
+	-0.00338019,
+	-0.00355980,
+	-0.00374256,
+	-0.00392813,
+	-0.00411615,
+	-0.00430626,
+	-0.00449806,
+	-0.00469118,
+	-0.00488519,
+	-0.00507969,
+	-0.00527425,
+	-0.00546844,
+	-0.00566182,
+	-0.00585395,
+	-0.00604439,
+	-0.00623269,
+	-0.00641841,
+	-0.00660111,
+	-0.00678034,
+	-0.00695567,
+	-0.00712666,
+	-0.00729290,
+	-0.00745397,
+	-0.00760947,
+	-0.00775900,
+	-0.00790219,
+	-0.00803867,
+	-0.00816809,
+	-0.00829011,
+	-0.00840443,
+	-0.00851074,
+	-0.00860876,
+	-0.00869825,
+	-0.00877896,
+	-0.00885069,
+	-0.00891324,
+	-0.00896645,
+	-0.00901018,
+	-0.00904431,
+	-0.00906876,
+	-0.00908345,
+	0.99063061,
+	-0.00908345,
+	-0.00906876,
+	-0.00904431,
+	-0.00901018,
+	-0.00896645,
+	-0.00891324,
+	-0.00885069,
+	-0.00877896,
+	-0.00869825,
+	-0.00860876,
+	-0.00851074,
+	-0.00840443,
+	-0.00829011,
+	-0.00816809,
+	-0.00803867,
+	-0.00790219,
+	-0.00775900,
+	-0.00760947,
+	-0.00745397,
+	-0.00729290,
+	-0.00712666,
+	-0.00695567,
+	-0.00678034,
+	-0.00660111,
+	-0.00641841,
+	-0.00623269,
+	-0.00604439,
+	-0.00585395,
+	-0.00566182,
+	-0.00546844,
+	-0.00527425,
+	-0.00507969,
+	-0.00488519,
+	-0.00469118,
+	-0.00449806,
+	-0.00430626,
+	-0.00411615,
+	-0.00392813,
+	-0.00374256,
+	-0.00355980,
+	-0.00338019,
+	-0.00320406,
+	-0.00303170,
+	-0.00286342,
+	-0.00269947,
+	-0.00254012,
+	-0.00238558,
+	-0.00223608,
+	-0.00209179,
+	-0.00195288,
+	-0.00181951,
+	-0.00169179,
+	-0.00156983,
+	-0.00145370,
+	-0.00134347,
+	-0.00123916,
+	-0.00114080,
+	-0.00104836,
+	-0.00096184,
+	-0.00088117,
+	-0.00080629,
+	-0.00073711,
+	-0.00067352,
+	-0.00061540,
+	-0.00056260,
+	-0.00051497,
+	-0.00047233,
+	-0.00043449,
+	-0.00040124,
+	-0.00037238,
+	-0.00034768,
+	-0.00032689,
+	-0.00030978,
+	-0.00029609,
+	-0.00029609};
+
+/*-----------------------------------------------------------------------*/
+/* highpass 4 FIR filter */
+/*-----------------------------------------------------------------------*/
+const double filter_high_4[] = {
+	0.00002422,
+	0.00000988,
+	-0.00000508,
+	-0.00002111,
+	-0.00003868,
+	-0.00005828,
+	-0.00008043,
+	-0.00010564,
+	-0.00013444,
+	-0.00016738,
+	-0.00020497,
+	-0.00024777,
+	-0.00029630,
+	-0.00035109,
+	-0.00041264,
+	-0.00048145,
+	-0.00055800,
+	-0.00064274,
+	-0.00073611,
+	-0.00083849,
+	-0.00095027,
+	-0.00107177,
+	-0.00120330,
+	-0.00134509,
+	-0.00149736,
+	-0.00166028,
+	-0.00183397,
+	-0.00201848,
+	-0.00221384,
+	-0.00242000,
+	-0.00263687,
+	-0.00286431,
+	-0.00310212,
+	-0.00335002,
+	-0.00360772,
+	-0.00387483,
+	-0.00415093,
+	-0.00443555,
+	-0.00472815,
+	-0.00502814,
+	-0.00533490,
+	-0.00564775,
+	-0.00596595,
+	-0.00628875,
+	-0.00661533,
+	-0.00694485,
+	-0.00727644,
+	-0.00760919,
+	-0.00794217,
+	-0.00827442,
+	-0.00860499,
+	-0.00893287,
+	-0.00925709,
+	-0.00957664,
+	-0.00989053,
+	-0.01019777,
+	-0.01049736,
+	-0.01078834,
+	-0.01106976,
+	-0.01134068,
+	-0.01160021,
+	-0.01184746,
+	-0.01208160,
+	-0.01230184,
+	-0.01250741,
+	-0.01269760,
+	-0.01287175,
+	-0.01302927,
+	-0.01316958,
+	-0.01329221,
+	-0.01339672,
+	-0.01348273,
+	-0.01354995,
+	-0.01359814,
+	-0.01362712,
+	0.98639451,
+	-0.01362712,
+	-0.01359814,
+	-0.01354995,
+	-0.01348273,
+	-0.01339672,
+	-0.01329221,
+	-0.01316958,
+	-0.01302927,
+	-0.01287175,
+	-0.01269760,
+	-0.01250741,
+	-0.01230184,
+	-0.01208160,
+	-0.01184746,
+	-0.01160021,
+	-0.01134068,
+	-0.01106976,
+	-0.01078834,
+	-0.01049736,
+	-0.01019777,
+	-0.00989053,
+	-0.00957664,
+	-0.00925709,
+	-0.00893287,
+	-0.00860499,
+	-0.00827442,
+	-0.00794217,
+	-0.00760919,
+	-0.00727644,
+	-0.00694485,
+	-0.00661533,
+	-0.00628875,
+	-0.00596595,
+	-0.00564775,
+	-0.00533490,
+	-0.00502814,
+	-0.00472815,
+	-0.00443555,
+	-0.00415093,
+	-0.00387483,
+	-0.00360772,
+	-0.00335002,
+	-0.00310212,
+	-0.00286431,
+	-0.00263687,
+	-0.00242000,
+	-0.00221384,
+	-0.00201848,
+	-0.00183397,
+	-0.00166028,
+	-0.00149736,
+	-0.00134509,
+	-0.00120330,
+	-0.00107177,
+	-0.00095027,
+	-0.00083849,
+	-0.00073611,
+	-0.00064274,
+	-0.00055800,
+	-0.00048145,
+	-0.00041264,
+	-0.00035109,
+	-0.00029630,
+	-0.00024777,
+	-0.00020497,
+	-0.00016738,
+	-0.00013444,
+	-0.00010564,
+	-0.00008043,
+	-0.00005828,
+	-0.00003868,
+	-0.00002111,
+	-0.00000508,
+	0.00000988,
+	0.00000988};
+
+/*-----------------------------------------------------------------------*/
+/* highpass 5 FIR filter */
+/*-----------------------------------------------------------------------*/
+const double filter_high_5[] = {
+	0.00030894,
+	0.00030598,
+	0.00030484,
+	0.00030528,
+	0.00030699,
+	0.00030957,
+	0.00031257,
+	0.00031546,
+	0.00031764,
+	0.00031846,
+	0.00031719,
+	0.00031308,
+	0.00030528,
+	0.00029294,
+	0.00027514,
+	0.00025096,
+	0.00021941,
+	0.00017953,
+	0.00013033,
+	0.00007081,
+	-0.00000000,
+	-0.00008307,
+	-0.00017935,
+	-0.00028972,
+	-0.00041506,
+	-0.00055618,
+	-0.00071381,
+	-0.00088865,
+	-0.00108129,
+	-0.00129225,
+	-0.00152196,
+	-0.00177074,
+	-0.00203881,
+	-0.00232629,
+	-0.00263317,
+	-0.00295934,
+	-0.00330455,
+	-0.00366843,
+	-0.00405049,
+	-0.00445011,
+	-0.00486655,
+	-0.00529894,
+	-0.00574629,
+	-0.00620748,
+	-0.00668128,
+	-0.00716637,
+	-0.00766129,
+	-0.00816451,
+	-0.00867438,
+	-0.00918920,
+	-0.00970717,
+	-0.01022644,
+	-0.01074509,
+	-0.01126117,
+	-0.01177268,
+	-0.01227762,
+	-0.01277396,
+	-0.01325968,
+	-0.01373276,
+	-0.01419123,
+	-0.01463312,
+	-0.01505655,
+	-0.01545966,
+	-0.01584070,
+	-0.01619797,
+	-0.01652988,
+	-0.01683493,
+	-0.01711175,
+	-0.01735908,
+	-0.01757579,
+	-0.01776088,
+	-0.01791350,
+	-0.01803294,
+	-0.01811866,
+	-0.01817025,
+	0.98212344,
+	-0.01817025,
+	-0.01811866,
+	-0.01803294,
+	-0.01791350,
+	-0.01776088,
+	-0.01757579,
+	-0.01735908,
+	-0.01711175,
+	-0.01683493,
+	-0.01652988,
+	-0.01619797,
+	-0.01584070,
+	-0.01545966,
+	-0.01505655,
+	-0.01463312,
+	-0.01419123,
+	-0.01373276,
+	-0.01325968,
+	-0.01277396,
+	-0.01227762,
+	-0.01177268,
+	-0.01126117,
+	-0.01074509,
+	-0.01022644,
+	-0.00970717,
+	-0.00918920,
+	-0.00867438,
+	-0.00816451,
+	-0.00766129,
+	-0.00716637,
+	-0.00668128,
+	-0.00620748,
+	-0.00574629,
+	-0.00529894,
+	-0.00486655,
+	-0.00445011,
+	-0.00405049,
+	-0.00366843,
+	-0.00330455,
+	-0.00295934,
+	-0.00263317,
+	-0.00232629,
+	-0.00203881,
+	-0.00177074,
+	-0.00152196,
+	-0.00129225,
+	-0.00108129,
+	-0.00088865,
+	-0.00071381,
+	-0.00055618,
+	-0.00041506,
+	-0.00028972,
+	-0.00017935,
+	-0.00008307,
+	-0.00000000,
+	0.00007081,
+	0.00013033,
+	0.00017953,
+	0.00021941,
+	0.00025096,
+	0.00027514,
+	0.00029294,
+	0.00030528,
+	0.00031308,
+	0.00031719,
+	0.00031846,
+	0.00031764,
+	0.00031546,
+	0.00031257,
+	0.00030957,
+	0.00030699,
+	0.00030528,
+	0.00030484,
+	0.00030598,
+	0.00030598};
+
+/*-----------------------------------------------------------------------*/
+/* highpass 6 FIR filter */
+/*-----------------------------------------------------------------------*/
+const double filter_high_6[] = {
+	-0.00004832,
+	-0.00001974,
+	0.00001016,
+	0.00004214,
+	0.00007696,
+	0.00011536,
+	0.00015807,
+	0.00020577,
+	0.00025903,
+	0.00031834,
+	0.00038406,
+	0.00045641,
+	0.00053543,
+	0.00062097,
+	0.00071267,
+	0.00080996,
+	0.00091205,
+	0.00101788,
+	0.00112617,
+	0.00123539,
+	0.00134376,
+	0.00144928,
+	0.00154970,
+	0.00164260,
+	0.00172532,
+	0.00179507,
+	0.00184889,
+	0.00188374,
+	0.00189647,
+	0.00188389,
+	0.00184281,
+	0.00177008,
+	0.00166260,
+	0.00151740,
+	0.00133166,
+	0.00110279,
+	0.00082839,
+	0.00050639,
+	0.00013502,
+	-0.00028714,
+	-0.00076110,
+	-0.00128747,
+	-0.00186639,
+	-0.00249754,
+	-0.00318011,
+	-0.00391281,
+	-0.00469382,
+	-0.00552083,
+	-0.00639100,
+	-0.00730102,
+	-0.00824709,
+	-0.00922496,
+	-0.01022995,
+	-0.01125697,
+	-0.01230057,
+	-0.01335498,
+	-0.01441418,
+	-0.01547188,
+	-0.01652165,
+	-0.01755695,
+	-0.01857115,
+	-0.01955766,
+	-0.02050993,
+	-0.02142155,
+	-0.02228627,
+	-0.02309812,
+	-0.02385140,
+	-0.02454078,
+	-0.02516135,
+	-0.02570863,
+	-0.02617867,
+	-0.02656804,
+	-0.02687389,
+	-0.02709398,
+	-0.02722668,
+	0.97266661,
+	-0.02722668,
+	-0.02709398,
+	-0.02687389,
+	-0.02656804,
+	-0.02617867,
+	-0.02570863,
+	-0.02516135,
+	-0.02454078,
+	-0.02385140,
+	-0.02309812,
+	-0.02228627,
+	-0.02142155,
+	-0.02050993,
+	-0.01955766,
+	-0.01857115,
+	-0.01755695,
+	-0.01652165,
+	-0.01547188,
+	-0.01441418,
+	-0.01335498,
+	-0.01230057,
+	-0.01125697,
+	-0.01022995,
+	-0.00922496,
+	-0.00824709,
+	-0.00730102,
+	-0.00639100,
+	-0.00552083,
+	-0.00469382,
+	-0.00391281,
+	-0.00318011,
+	-0.00249754,
+	-0.00186639,
+	-0.00128747,
+	-0.00076110,
+	-0.00028714,
+	0.00013502,
+	0.00050639,
+	0.00082839,
+	0.00110279,
+	0.00133166,
+	0.00151740,
+	0.00166260,
+	0.00177008,
+	0.00184281,
+	0.00188389,
+	0.00189647,
+	0.00188374,
+	0.00184889,
+	0.00179507,
+	0.00172532,
+	0.00164260,
+	0.00154970,
+	0.00144928,
+	0.00134376,
+	0.00123539,
+	0.00112617,
+	0.00101788,
+	0.00091205,
+	0.00080996,
+	0.00071267,
+	0.00062097,
+	0.00053543,
+	0.00045641,
+	0.00038406,
+	0.00031834,
+	0.00025903,
+	0.00020577,
+	0.00015807,
+	0.00011536,
+	0.00007696,
+	0.00004214,
+	0.00001016,
+	-0.00001974,
+	-0.00001974};
+
+/*-----------------------------------------------------------------------*/
+/* highpass 7 FIR filter */
+/*-----------------------------------------------------------------------*/
+const double filter_high_7[] = {
+	-0.00025654,
+	-0.00028542,
+	-0.00031466,
+	-0.00034444,
+	-0.00037472,
+	-0.00040523,
+	-0.00043544,
+	-0.00046456,
+	-0.00049152,
+	-0.00051499,
+	-0.00053339,
+	-0.00054492,
+	-0.00054762,
+	-0.00053937,
+	-0.00051800,
+	-0.00048132,
+	-0.00042719,
+	-0.00035361,
+	-0.00025882,
+	-0.00014132,
+	-0.00000000,
+	0.00016578,
+	0.00035616,
+	0.00057064,
+	0.00080811,
+	0.00106671,
+	0.00134386,
+	0.00163621,
+	0.00193963,
+	0.00224921,
+	0.00255929,
+	0.00286353,
+	0.00315491,
+	0.00342585,
+	0.00366829,
+	0.00387377,
+	0.00403360,
+	0.00413895,
+	0.00418101,
+	0.00415115,
+	0.00404104,
+	0.00384287,
+	0.00354944,
+	0.00315436,
+	0.00265221,
+	0.00203863,
+	0.00131051,
+	0.00046603,
+	-0.00049514,
+	-0.00157186,
+	-0.00276142,
+	-0.00405950,
+	-0.00546018,
+	-0.00695594,
+	-0.00853772,
+	-0.01019498,
+	-0.01191579,
+	-0.01368696,
+	-0.01549416,
+	-0.01732210,
+	-0.01915472,
+	-0.02097535,
+	-0.02276695,
+	-0.02451233,
+	-0.02619438,
+	-0.02779626,
+	-0.02930169,
+	-0.03069514,
+	-0.03196205,
+	-0.03308902,
+	-0.03406404,
+	-0.03487663,
+	-0.03551801,
+	-0.03598121,
+	-0.03626117,
+	0.96340302,
+	-0.03626117,
+	-0.03598121,
+	-0.03551801,
+	-0.03487663,
+	-0.03406404,
+	-0.03308902,
+	-0.03196205,
+	-0.03069514,
+	-0.02930169,
+	-0.02779626,
+	-0.02619438,
+	-0.02451233,
+	-0.02276695,
+	-0.02097535,
+	-0.01915472,
+	-0.01732210,
+	-0.01549416,
+	-0.01368696,
+	-0.01191579,
+	-0.01019498,
+	-0.00853772,
+	-0.00695594,
+	-0.00546018,
+	-0.00405950,
+	-0.00276142,
+	-0.00157186,
+	-0.00049514,
+	0.00046603,
+	0.00131051,
+	0.00203863,
+	0.00265221,
+	0.00315436,
+	0.00354944,
+	0.00384287,
+	0.00404104,
+	0.00415115,
+	0.00418101,
+	0.00413895,
+	0.00403360,
+	0.00387377,
+	0.00366829,
+	0.00342585,
+	0.00315491,
+	0.00286353,
+	0.00255929,
+	0.00224921,
+	0.00193963,
+	0.00163621,
+	0.00134386,
+	0.00106671,
+	0.00080811,
+	0.00057064,
+	0.00035616,
+	0.00016578,
+	-0.00000000,
+	-0.00014132,
+	-0.00025882,
+	-0.00035361,
+	-0.00042719,
+	-0.00048132,
+	-0.00051800,
+	-0.00053937,
+	-0.00054762,
+	-0.00054492,
+	-0.00053339,
+	-0.00051499,
+	-0.00049152,
+	-0.00046456,
+	-0.00043544,
+	-0.00040523,
+	-0.00037472,
+	-0.00034444,
+	-0.00031466,
+	-0.00028542,
+	-0.00028542};
+
+/*-----------------------------------------------------------------------*/
+/* highpass 8 FIR filter */
+/*-----------------------------------------------------------------------*/
+const double filter_high_8[] = {
+	-0.00009565,
+	-0.00003942,
+	0.00002031,
+	0.00008373,
+	0.00015084,
+	0.00022136,
+	0.00029459,
+	0.00036929,
+	0.00044361,
+	0.00051505,
+	0.00058048,
+	0.00063615,
+	0.00067783,
+	0.00070096,
+	0.00070084,
+	0.00067290,
+	0.00061295,
+	0.00051750,
+	0.00038405,
+	0.00021142,
+	-0.00000000,
+	-0.00024803,
+	-0.00052849,
+	-0.00083511,
+	-0.00115951,
+	-0.00149130,
+	-0.00181821,
+	-0.00212640,
+	-0.00240083,
+	-0.00262575,
+	-0.00278524,
+	-0.00286387,
+	-0.00284735,
+	-0.00272325,
+	-0.00248171,
+	-0.00211611,
+	-0.00162369,
+	-0.00100612,
+	-0.00026991,
+	0.00057331,
+	0.00150662,
+	0.00250787,
+	0.00354986,
+	0.00460080,
+	0.00562485,
+	0.00658294,
+	0.00743365,
+	0.00813435,
+	0.00864234,
+	0.00891616,
+	0.00891689,
+	0.00860945,
+	0.00796394,
+	0.00695677,
+	0.00557174,
+	0.00380099,
+	0.00164568,
+	-0.00088358,
+	-0.00376642,
+	-0.00697286,
+	-0.01046356,
+	-0.01419048,
+	-0.01809773,
+	-0.02212273,
+	-0.02619750,
+	-0.03025027,
+	-0.03420712,
+	-0.03799378,
+	-0.04153746,
+	-0.04476867,
+	-0.04762303,
+	-0.05004288,
+	-0.05197885,
+	-0.05339107,
+	-0.05425033,
+	0.94533834,
+	-0.05425033,
+	-0.05339107,
+	-0.05197885,
+	-0.05004288,
+	-0.04762303,
+	-0.04476867,
+	-0.04153746,
+	-0.03799378,
+	-0.03420712,
+	-0.03025027,
+	-0.02619750,
+	-0.02212273,
+	-0.01809773,
+	-0.01419048,
+	-0.01046356,
+	-0.00697286,
+	-0.00376642,
+	-0.00088358,
+	0.00164568,
+	0.00380099,
+	0.00557174,
+	0.00695677,
+	0.00796394,
+	0.00860945,
+	0.00891689,
+	0.00891616,
+	0.00864234,
+	0.00813435,
+	0.00743365,
+	0.00658294,
+	0.00562485,
+	0.00460080,
+	0.00354986,
+	0.00250787,
+	0.00150662,
+	0.00057331,
+	-0.00026991,
+	-0.00100612,
+	-0.00162369,
+	-0.00211611,
+	-0.00248171,
+	-0.00272325,
+	-0.00284735,
+	-0.00286387,
+	-0.00278524,
+	-0.00262575,
+	-0.00240083,
+	-0.00212640,
+	-0.00181821,
+	-0.00149130,
+	-0.00115951,
+	-0.00083511,
+	-0.00052849,
+	-0.00024803,
+	-0.00000000,
+	0.00021142,
+	0.00038405,
+	0.00051750,
+	0.00061295,
+	0.00067290,
+	0.00070084,
+	0.00070096,
+	0.00067783,
+	0.00063615,
+	0.00058048,
+	0.00051505,
+	0.00044361,
+	0.00036929,
+	0.00029459,
+	0.00022136,
+	0.00015084,
+	0.00008373,
+	0.00002031,
+	-0.00003942,
+	-0.00003942};
+
+/*-----------------------------------------------------------------------*/
+/* highpass 9 FIR filter */
+/*-----------------------------------------------------------------------*/
+const double filter_high_9[] = {
+	0.00033619,
+	0.00032240,
+	0.00029386,
+	0.00025008,
+	0.00019063,
+	0.00011541,
+	0.00002488,
+	-0.00007956,
+	-0.00019534,
+	-0.00031847,
+	-0.00044341,
+	-0.00056312,
+	-0.00066919,
+	-0.00075225,
+	-0.00080248,
+	-0.00081029,
+	-0.00076716,
+	-0.00066648,
+	-0.00050448,
+	-0.00028095,
+	-0.00000000,
+	0.00032960,
+	0.00069420,
+	0.00107554,
+	0.00145123,
+	0.00179579,
+	0.00208189,
+	0.00228200,
+	0.00237024,
+	0.00232432,
+	0.00212757,
+	0.00177079,
+	0.00125380,
+	0.00058668,
+	-0.00020963,
+	-0.00110323,
+	-0.00205202,
+	-0.00300503,
+	-0.00390455,
+	-0.00468890,
+	-0.00529572,
+	-0.00566569,
+	-0.00574645,
+	-0.00549650,
+	-0.00488887,
+	-0.00391439,
+	-0.00258413,
+	-0.00093109,
+	0.00098924,
+	0.00309948,
+	0.00530221,
+	0.00748295,
+	0.00951439,
+	0.01126149,
+	0.01258749,
+	0.01336035,
+	0.01345940,
+	0.01278194,
+	0.01124934,
+	0.00881232,
+	0.00545517,
+	0.00119864,
+	-0.00389883,
+	-0.00974149,
+	-0.01619843,
+	-0.02310740,
+	-0.03028025,
+	-0.03750966,
+	-0.04457702,
+	-0.05126097,
+	-0.05734632,
+	-0.06263288,
+	-0.06694380,
+	-0.07013303,
+	-0.07209153,
+	0.92758750,
+	-0.07209153,
+	-0.07013303,
+	-0.06694380,
+	-0.06263288,
+	-0.05734632,
+	-0.05126097,
+	-0.04457702,
+	-0.03750966,
+	-0.03028025,
+	-0.02310740,
+	-0.01619843,
+	-0.00974149,
+	-0.00389883,
+	0.00119864,
+	0.00545517,
+	0.00881232,
+	0.01124934,
+	0.01278194,
+	0.01345940,
+	0.01336035,
+	0.01258749,
+	0.01126149,
+	0.00951439,
+	0.00748295,
+	0.00530221,
+	0.00309948,
+	0.00098924,
+	-0.00093109,
+	-0.00258413,
+	-0.00391439,
+	-0.00488887,
+	-0.00549650,
+	-0.00574645,
+	-0.00566569,
+	-0.00529572,
+	-0.00468890,
+	-0.00390455,
+	-0.00300503,
+	-0.00205202,
+	-0.00110323,
+	-0.00020963,
+	0.00058668,
+	0.00125380,
+	0.00177079,
+	0.00212757,
+	0.00232432,
+	0.00237024,
+	0.00228200,
+	0.00208189,
+	0.00179579,
+	0.00145123,
+	0.00107554,
+	0.00069420,
+	0.00032960,
+	-0.00000000,
+	-0.00028095,
+	-0.00050448,
+	-0.00066648,
+	-0.00076716,
+	-0.00081029,
+	-0.00080248,
+	-0.00075225,
+	-0.00066919,
+	-0.00056312,
+	-0.00044341,
+	-0.00031847,
+	-0.00019534,
+	-0.00007956,
+	0.00002488,
+	0.00011541,
+	0.00019063,
+	0.00025008,
+	0.00029386,
+	0.00032240,
+	0.00032240};
+
+/*-----------------------------------------------------------------------*/
+/* lowpass 1 FIR filter */
+/*-----------------------------------------------------------------------*/
+const double filter_low_1[] = {
+	0.00094747,
+	0.00095348,
+	0.00096905,
+	0.00099421,
+	0.00102895,
+	0.00107323,
+	0.00112702,
+	0.00119025,
+	0.00126284,
+	0.00134471,
+	0.00143573,
+	0.00153578,
+	0.00164470,
+	0.00176233,
+	0.00188850,
+	0.00202299,
+	0.00216560,
+	0.00231609,
+	0.00247423,
+	0.00263975,
+	0.00281238,
+	0.00299183,
+	0.00317780,
+	0.00336998,
+	0.00356804,
+	0.00377164,
+	0.00398043,
+	0.00419406,
+	0.00441215,
+	0.00463434,
+	0.00486022,
+	0.00508942,
+	0.00532153,
+	0.00555614,
+	0.00579283,
+	0.00603121,
+	0.00627084,
+	0.00651129,
+	0.00675216,
+	0.00699300,
+	0.00723339,
+	0.00747290,
+	0.00771111,
+	0.00794758,
+	0.00818191,
+	0.00841366,
+	0.00864243,
+	0.00886780,
+	0.00908937,
+	0.00930674,
+	0.00951951,
+	0.00972732,
+	0.00992977,
+	0.01012651,
+	0.01031719,
+	0.01050145,
+	0.01067896,
+	0.01084941,
+	0.01101248,
+	0.01116788,
+	0.01131533,
+	0.01145457,
+	0.01158532,
+	0.01170737,
+	0.01182049,
+	0.01192448,
+	0.01201914,
+	0.01210430,
+	0.01217981,
+	0.01224554,
+	0.01230135,
+	0.01234716,
+	0.01238287,
+	0.01240843,
+	0.01242378,
+	0.01242890,
+	0.01242378,
+	0.01240843,
+	0.01238287,
+	0.01234716,
+	0.01230135,
+	0.01224554,
+	0.01217981,
+	0.01210430,
+	0.01201914,
+	0.01192448,
+	0.01182049,
+	0.01170737,
+	0.01158532,
+	0.01145457,
+	0.01131533,
+	0.01116788,
+	0.01101248,
+	0.01084941,
+	0.01067896,
+	0.01050145,
+	0.01031719,
+	0.01012651,
+	0.00992977,
+	0.00972732,
+	0.00951951,
+	0.00930674,
+	0.00908937,
+	0.00886780,
+	0.00864243,
+	0.00841366,
+	0.00818191,
+	0.00794758,
+	0.00771111,
+	0.00747290,
+	0.00723339,
+	0.00699300,
+	0.00675216,
+	0.00651129,
+	0.00627084,
+	0.00603121,
+	0.00579283,
+	0.00555614,
+	0.00532153,
+	0.00508942,
+	0.00486022,
+	0.00463434,
+	0.00441215,
+	0.00419406,
+	0.00398043,
+	0.00377164,
+	0.00356804,
+	0.00336998,
+	0.00317780,
+	0.00299183,
+	0.00281238,
+	0.00263975,
+	0.00247423,
+	0.00231609,
+	0.00216560,
+	0.00202299,
+	0.00188850,
+	0.00176233,
+	0.00164470,
+	0.00153578,
+	0.00143573,
+	0.00134471,
+	0.00126284,
+	0.00119025,
+	0.00112702,
+	0.00107323,
+	0.00102895,
+	0.00099421,
+	0.00096905,
+	0.00095348,
+	0.00095348};
+
+/*-----------------------------------------------------------------------*/
+/* lowpass 2 FIR filter */
+/*-----------------------------------------------------------------------*/
+const double filter_low_2[] = {
+	0.00083374,
+	0.00084256,
+	0.00085987,
+	0.00088579,
+	0.00092041,
+	0.00096380,
+	0.00101603,
+	0.00107712,
+	0.00114709,
+	0.00122594,
+	0.00131365,
+	0.00141018,
+	0.00151546,
+	0.00162940,
+	0.00175191,
+	0.00188287,
+	0.00202212,
+	0.00216951,
+	0.00232485,
+	0.00248795,
+	0.00265858,
+	0.00283651,
+	0.00302148,
+	0.00321322,
+	0.00341143,
+	0.00361582,
+	0.00382605,
+	0.00404179,
+	0.00426269,
+	0.00448838,
+	0.00471849,
+	0.00495262,
+	0.00519037,
+	0.00543132,
+	0.00567506,
+	0.00592115,
+	0.00616916,
+	0.00641863,
+	0.00666911,
+	0.00692016,
+	0.00717129,
+	0.00742206,
+	0.00767200,
+	0.00792063,
+	0.00816749,
+	0.00841211,
+	0.00865404,
+	0.00889280,
+	0.00912795,
+	0.00935903,
+	0.00958560,
+	0.00980721,
+	0.01002344,
+	0.01023387,
+	0.01043809,
+	0.01063570,
+	0.01082631,
+	0.01100955,
+	0.01118506,
+	0.01135249,
+	0.01151150,
+	0.01166180,
+	0.01180307,
+	0.01193503,
+	0.01205743,
+	0.01217003,
+	0.01227259,
+	0.01236491,
+	0.01244681,
+	0.01251813,
+	0.01257871,
+	0.01262845,
+	0.01266724,
+	0.01269500,
+	0.01271168,
+	0.01271724,
+	0.01271168,
+	0.01269500,
+	0.01266724,
+	0.01262845,
+	0.01257871,
+	0.01251813,
+	0.01244681,
+	0.01236491,
+	0.01227259,
+	0.01217003,
+	0.01205743,
+	0.01193503,
+	0.01180307,
+	0.01166180,
+	0.01151150,
+	0.01135249,
+	0.01118506,
+	0.01100955,
+	0.01082631,
+	0.01063570,
+	0.01043809,
+	0.01023387,
+	0.01002344,
+	0.00980721,
+	0.00958560,
+	0.00935903,
+	0.00912795,
+	0.00889280,
+	0.00865404,
+	0.00841211,
+	0.00816749,
+	0.00792063,
+	0.00767200,
+	0.00742206,
+	0.00717129,
+	0.00692016,
+	0.00666911,
+	0.00641863,
+	0.00616916,
+	0.00592115,
+	0.00567506,
+	0.00543132,
+	0.00519037,
+	0.00495262,
+	0.00471849,
+	0.00448838,
+	0.00426269,
+	0.00404179,
+	0.00382605,
+	0.00361582,
+	0.00341143,
+	0.00321322,
+	0.00302148,
+	0.00283651,
+	0.00265858,
+	0.00248795,
+	0.00232485,
+	0.00216951,
+	0.00202212,
+	0.00188287,
+	0.00175191,
+	0.00162940,
+	0.00151546,
+	0.00141018,
+	0.00131365,
+	0.00122594,
+	0.00114709,
+	0.00107712,
+	0.00101603,
+	0.00096380,
+	0.00092041,
+	0.00088579,
+	0.00085987,
+	0.00084256,
+	0.00084256};
+
+/*-----------------------------------------------------------------------*/
+/* lowpass 3 FIR filter */
+/*-----------------------------------------------------------------------*/
+const double filter_low_3[] = {
+	0.00043674,
+	0.00045286,
+	0.00047380,
+	0.00049997,
+	0.00053176,
+	0.00056954,
+	0.00061368,
+	0.00066453,
+	0.00072240,
+	0.00078762,
+	0.00086048,
+	0.00094123,
+	0.00103012,
+	0.00112738,
+	0.00123319,
+	0.00134772,
+	0.00147110,
+	0.00160343,
+	0.00174480,
+	0.00189525,
+	0.00205478,
+	0.00222338,
+	0.00240099,
+	0.00258753,
+	0.00278287,
+	0.00298686,
+	0.00319931,
+	0.00341999,
+	0.00364865,
+	0.00388501,
+	0.00412874,
+	0.00437948,
+	0.00463687,
+	0.00490048,
+	0.00516987,
+	0.00544457,
+	0.00572409,
+	0.00600791,
+	0.00629548,
+	0.00658624,
+	0.00687961,
+	0.00717497,
+	0.00747170,
+	0.00776918,
+	0.00806675,
+	0.00836375,
+	0.00865952,
+	0.00895338,
+	0.00924465,
+	0.00953265,
+	0.00981671,
+	0.01009613,
+	0.01037026,
+	0.01063841,
+	0.01089994,
+	0.01115420,
+	0.01140055,
+	0.01163838,
+	0.01186708,
+	0.01208608,
+	0.01229482,
+	0.01249276,
+	0.01267939,
+	0.01285423,
+	0.01301683,
+	0.01316676,
+	0.01330362,
+	0.01342707,
+	0.01353677,
+	0.01363244,
+	0.01371383,
+	0.01378071,
+	0.01383291,
+	0.01387030,
+	0.01389277,
+	0.01390027,
+	0.01389277,
+	0.01387030,
+	0.01383291,
+	0.01378071,
+	0.01371383,
+	0.01363244,
+	0.01353677,
+	0.01342707,
+	0.01330362,
+	0.01316676,
+	0.01301683,
+	0.01285423,
+	0.01267939,
+	0.01249276,
+	0.01229482,
+	0.01208608,
+	0.01186708,
+	0.01163838,
+	0.01140055,
+	0.01115420,
+	0.01089994,
+	0.01063841,
+	0.01037026,
+	0.01009613,
+	0.00981671,
+	0.00953265,
+	0.00924465,
+	0.00895338,
+	0.00865952,
+	0.00836375,
+	0.00806675,
+	0.00776918,
+	0.00747170,
+	0.00717497,
+	0.00687961,
+	0.00658624,
+	0.00629548,
+	0.00600791,
+	0.00572409,
+	0.00544457,
+	0.00516987,
+	0.00490048,
+	0.00463687,
+	0.00437948,
+	0.00412874,
+	0.00388501,
+	0.00364865,
+	0.00341999,
+	0.00319931,
+	0.00298686,
+	0.00278287,
+	0.00258753,
+	0.00240099,
+	0.00222338,
+	0.00205478,
+	0.00189525,
+	0.00174480,
+	0.00160343,
+	0.00147110,
+	0.00134772,
+	0.00123319,
+	0.00112738,
+	0.00103012,
+	0.00094123,
+	0.00086048,
+	0.00078762,
+	0.00072240,
+	0.00066453,
+	0.00061368,
+	0.00056954,
+	0.00053176,
+	0.00049997,
+	0.00047380,
+	0.00045286,
+	0.00045286};
+
+/*-----------------------------------------------------------------------*/
+/* lowpass 4 FIR filter */
+/*-----------------------------------------------------------------------*/
+const double filter_low_4[] = {
+	-0.00002835,
+	-0.00001156,
+	0.00000595,
+	0.00002470,
+	0.00004526,
+	0.00006820,
+	0.00009412,
+	0.00012362,
+	0.00015733,
+	0.00019587,
+	0.00023987,
+	0.00028995,
+	0.00034674,
+	0.00041085,
+	0.00048288,
+	0.00056340,
+	0.00065298,
+	0.00075215,
+	0.00086141,
+	0.00098123,
+	0.00111204,
+	0.00125422,
+	0.00140813,
+	0.00157406,
+	0.00175226,
+	0.00194291,
+	0.00214616,
+	0.00236208,
+	0.00259069,
+	0.00283195,
+	0.00308574,
+	0.00335190,
+	0.00363018,
+	0.00392029,
+	0.00422185,
+	0.00453443,
+	0.00485754,
+	0.00519060,
+	0.00553301,
+	0.00588407,
+	0.00624305,
+	0.00660915,
+	0.00698152,
+	0.00735926,
+	0.00774144,
+	0.00812705,
+	0.00851509,
+	0.00890448,
+	0.00929414,
+	0.00968296,
+	0.01006979,
+	0.01045350,
+	0.01083291,
+	0.01120686,
+	0.01157418,
+	0.01193371,
+	0.01228430,
+	0.01262482,
+	0.01295414,
+	0.01327118,
+	0.01357489,
+	0.01386423,
+	0.01413823,
+	0.01439595,
+	0.01463651,
+	0.01485908,
+	0.01506289,
+	0.01524721,
+	0.01541141,
+	0.01555492,
+	0.01567721,
+	0.01577787,
+	0.01585653,
+	0.01591292,
+	0.01594683,
+	0.01595815,
+	0.01594683,
+	0.01591292,
+	0.01585653,
+	0.01577787,
+	0.01567721,
+	0.01555492,
+	0.01541141,
+	0.01524721,
+	0.01506289,
+	0.01485908,
+	0.01463651,
+	0.01439595,
+	0.01413823,
+	0.01386423,
+	0.01357489,
+	0.01327118,
+	0.01295414,
+	0.01262482,
+	0.01228430,
+	0.01193371,
+	0.01157418,
+	0.01120686,
+	0.01083291,
+	0.01045350,
+	0.01006979,
+	0.00968296,
+	0.00929414,
+	0.00890448,
+	0.00851509,
+	0.00812705,
+	0.00774144,
+	0.00735926,
+	0.00698152,
+	0.00660915,
+	0.00624305,
+	0.00588407,
+	0.00553301,
+	0.00519060,
+	0.00485754,
+	0.00453443,
+	0.00422185,
+	0.00392029,
+	0.00363018,
+	0.00335190,
+	0.00308574,
+	0.00283195,
+	0.00259069,
+	0.00236208,
+	0.00214616,
+	0.00194291,
+	0.00175226,
+	0.00157406,
+	0.00140813,
+	0.00125422,
+	0.00111204,
+	0.00098123,
+	0.00086141,
+	0.00075215,
+	0.00065298,
+	0.00056340,
+	0.00048288,
+	0.00041085,
+	0.00034674,
+	0.00028995,
+	0.00023987,
+	0.00019587,
+	0.00015733,
+	0.00012362,
+	0.00009412,
+	0.00006820,
+	0.00004526,
+	0.00002470,
+	0.00000595,
+	-0.00001156,
+	-0.00001156};
+
+/*-----------------------------------------------------------------------*/
+/* lowpass 5 FIR filter */
+/*-----------------------------------------------------------------------*/
+const double filter_low_5[] = {
+	-0.00032178,
+	-0.00031869,
+	-0.00031751,
+	-0.00031797,
+	-0.00031974,
+	-0.00032243,
+	-0.00032555,
+	-0.00032856,
+	-0.00033083,
+	-0.00033169,
+	-0.00033037,
+	-0.00032608,
+	-0.00031796,
+	-0.00030511,
+	-0.00028657,
+	-0.00026138,
+	-0.00022853,
+	-0.00018699,
+	-0.00013574,
+	-0.00007375,
+	0.00000000,
+	0.00008652,
+	0.00018680,
+	0.00030176,
+	0.00043231,
+	0.00057928,
+	0.00074347,
+	0.00092557,
+	0.00112621,
+	0.00134594,
+	0.00158519,
+	0.00184430,
+	0.00212351,
+	0.00242293,
+	0.00274257,
+	0.00308228,
+	0.00344183,
+	0.00382083,
+	0.00421876,
+	0.00463499,
+	0.00506873,
+	0.00551908,
+	0.00598501,
+	0.00646536,
+	0.00695885,
+	0.00746409,
+	0.00797957,
+	0.00850369,
+	0.00903475,
+	0.00957096,
+	0.01011045,
+	0.01065129,
+	0.01119149,
+	0.01172901,
+	0.01226177,
+	0.01278769,
+	0.01330465,
+	0.01381054,
+	0.01430328,
+	0.01478079,
+	0.01524105,
+	0.01568206,
+	0.01610193,
+	0.01649879,
+	0.01687090,
+	0.01721660,
+	0.01753433,
+	0.01782265,
+	0.01808026,
+	0.01830597,
+	0.01849874,
+	0.01865770,
+	0.01878211,
+	0.01887139,
+	0.01892512,
+	0.01894306,
+	0.01892512,
+	0.01887139,
+	0.01878211,
+	0.01865770,
+	0.01849874,
+	0.01830597,
+	0.01808026,
+	0.01782265,
+	0.01753433,
+	0.01721660,
+	0.01687090,
+	0.01649879,
+	0.01610193,
+	0.01568206,
+	0.01524105,
+	0.01478079,
+	0.01430328,
+	0.01381054,
+	0.01330465,
+	0.01278769,
+	0.01226177,
+	0.01172901,
+	0.01119149,
+	0.01065129,
+	0.01011045,
+	0.00957096,
+	0.00903475,
+	0.00850369,
+	0.00797957,
+	0.00746409,
+	0.00695885,
+	0.00646536,
+	0.00598501,
+	0.00551908,
+	0.00506873,
+	0.00463499,
+	0.00421876,
+	0.00382083,
+	0.00344183,
+	0.00308228,
+	0.00274257,
+	0.00242293,
+	0.00212351,
+	0.00184430,
+	0.00158519,
+	0.00134594,
+	0.00112621,
+	0.00092557,
+	0.00074347,
+	0.00057928,
+	0.00043231,
+	0.00030176,
+	0.00018680,
+	0.00008652,
+	0.00000000,
+	-0.00007375,
+	-0.00013574,
+	-0.00018699,
+	-0.00022853,
+	-0.00026138,
+	-0.00028657,
+	-0.00030511,
+	-0.00031796,
+	-0.00032608,
+	-0.00033037,
+	-0.00033169,
+	-0.00033083,
+	-0.00032856,
+	-0.00032555,
+	-0.00032243,
+	-0.00031974,
+	-0.00031797,
+	-0.00031751,
+	-0.00031869,
+	-0.00031869};
+
+/*-----------------------------------------------------------------------*/
+/* lowpass 6 FIR filter */
+/*-----------------------------------------------------------------------*/
+const double filter_low_6[] = {
+	0.00004813,
+	0.00001967,
+	-0.00001012,
+	-0.00004198,
+	-0.00007666,
+	-0.00011492,
+	-0.00015747,
+	-0.00020498,
+	-0.00025804,
+	-0.00031712,
+	-0.00038260,
+	-0.00045467,
+	-0.00053338,
+	-0.00061859,
+	-0.00070994,
+	-0.00080687,
+	-0.00090856,
+	-0.00101399,
+	-0.00112187,
+	-0.00123067,
+	-0.00133863,
+	-0.00144374,
+	-0.00154378,
+	-0.00163632,
+	-0.00171873,
+	-0.00178821,
+	-0.00184183,
+	-0.00187654,
+	-0.00188922,
+	-0.00187669,
+	-0.00183577,
+	-0.00176332,
+	-0.00165624,
+	-0.00151160,
+	-0.00132658,
+	-0.00109857,
+	-0.00082523,
+	-0.00050446,
+	-0.00013450,
+	0.00028604,
+	0.00075820,
+	0.00128255,
+	0.00185926,
+	0.00248799,
+	0.00316796,
+	0.00389787,
+	0.00467589,
+	0.00549974,
+	0.00636658,
+	0.00727312,
+	0.00821558,
+	0.00918972,
+	0.01019087,
+	0.01121396,
+	0.01225358,
+	0.01330397,
+	0.01435911,
+	0.01541277,
+	0.01645854,
+	0.01748988,
+	0.01850021,
+	0.01948295,
+	0.02043158,
+	0.02133971,
+	0.02220114,
+	0.02300988,
+	0.02376028,
+	0.02444704,
+	0.02506523,
+	0.02561042,
+	0.02607866,
+	0.02646654,
+	0.02677123,
+	0.02699047,
+	0.02712267,
+	0.02716685,
+	0.02712267,
+	0.02699047,
+	0.02677123,
+	0.02646654,
+	0.02607866,
+	0.02561042,
+	0.02506523,
+	0.02444704,
+	0.02376028,
+	0.02300988,
+	0.02220114,
+	0.02133971,
+	0.02043158,
+	0.01948295,
+	0.01850021,
+	0.01748988,
+	0.01645854,
+	0.01541277,
+	0.01435911,
+	0.01330397,
+	0.01225358,
+	0.01121396,
+	0.01019087,
+	0.00918972,
+	0.00821558,
+	0.00727312,
+	0.00636658,
+	0.00549974,
+	0.00467589,
+	0.00389787,
+	0.00316796,
+	0.00248799,
+	0.00185926,
+	0.00128255,
+	0.00075820,
+	0.00028604,
+	-0.00013450,
+	-0.00050446,
+	-0.00082523,
+	-0.00109857,
+	-0.00132658,
+	-0.00151160,
+	-0.00165624,
+	-0.00176332,
+	-0.00183577,
+	-0.00187669,
+	-0.00188922,
+	-0.00187654,
+	-0.00184183,
+	-0.00178821,
+	-0.00171873,
+	-0.00163632,
+	-0.00154378,
+	-0.00144374,
+	-0.00133863,
+	-0.00123067,
+	-0.00112187,
+	-0.00101399,
+	-0.00090856,
+	-0.00080687,
+	-0.00070994,
+	-0.00061859,
+	-0.00053338,
+	-0.00045467,
+	-0.00038260,
+	-0.00031712,
+	-0.00025804,
+	-0.00020498,
+	-0.00015747,
+	-0.00011492,
+	-0.00007666,
+	-0.00004198,
+	-0.00001012,
+	0.00001967,
+	0.00001967};
+
+/*-----------------------------------------------------------------------*/
+/* lowpass 7 FIR filter */
+/*-----------------------------------------------------------------------*/
+const double filter_low_7[] = {
+	0.00025614,
+	0.00028498,
+	0.00031418,
+	0.00034391,
+	0.00037414,
+	0.00040460,
+	0.00043477,
+	0.00046384,
+	0.00049076,
+	0.00051419,
+	0.00053256,
+	0.00054408,
+	0.00054677,
+	0.00053854,
+	0.00051720,
+	0.00048057,
+	0.00042653,
+	0.00035307,
+	0.00025842,
+	0.00014110,
+	-0.00000000,
+	-0.00016553,
+	-0.00035561,
+	-0.00056976,
+	-0.00080686,
+	-0.00106506,
+	-0.00134179,
+	-0.00163369,
+	-0.00193663,
+	-0.00224573,
+	-0.00255534,
+	-0.00285911,
+	-0.00315004,
+	-0.00342056,
+	-0.00366262,
+	-0.00386778,
+	-0.00402737,
+	-0.00413256,
+	-0.00417455,
+	-0.00414474,
+	-0.00403480,
+	-0.00383693,
+	-0.00354396,
+	-0.00314949,
+	-0.00264812,
+	-0.00203549,
+	-0.00130848,
+	-0.00046531,
+	0.00049437,
+	0.00156943,
+	0.00275716,
+	0.00405323,
+	0.00545174,
+	0.00694519,
+	0.00852453,
+	0.01017923,
+	0.01189739,
+	0.01366582,
+	0.01547023,
+	0.01729535,
+	0.01912514,
+	0.02094295,
+	0.02273178,
+	0.02447447,
+	0.02615392,
+	0.02775333,
+	0.02925644,
+	0.03064774,
+	0.03191268,
+	0.03303791,
+	0.03401143,
+	0.03482277,
+	0.03546316,
+	0.03592564,
+	0.03620517,
+	0.03629868,
+	0.03620517,
+	0.03592564,
+	0.03546316,
+	0.03482277,
+	0.03401143,
+	0.03303791,
+	0.03191268,
+	0.03064774,
+	0.02925644,
+	0.02775333,
+	0.02615392,
+	0.02447447,
+	0.02273178,
+	0.02094295,
+	0.01912514,
+	0.01729535,
+	0.01547023,
+	0.01366582,
+	0.01189739,
+	0.01017923,
+	0.00852453,
+	0.00694519,
+	0.00545174,
+	0.00405323,
+	0.00275716,
+	0.00156943,
+	0.00049437,
+	-0.00046531,
+	-0.00130848,
+	-0.00203549,
+	-0.00264812,
+	-0.00314949,
+	-0.00354396,
+	-0.00383693,
+	-0.00403480,
+	-0.00414474,
+	-0.00417455,
+	-0.00413256,
+	-0.00402737,
+	-0.00386778,
+	-0.00366262,
+	-0.00342056,
+	-0.00315004,
+	-0.00285911,
+	-0.00255534,
+	-0.00224573,
+	-0.00193663,
+	-0.00163369,
+	-0.00134179,
+	-0.00106506,
+	-0.00080686,
+	-0.00056976,
+	-0.00035561,
+	-0.00016553,
+	-0.00000000,
+	0.00014110,
+	0.00025842,
+	0.00035307,
+	0.00042653,
+	0.00048057,
+	0.00051720,
+	0.00053854,
+	0.00054677,
+	0.00054408,
+	0.00053256,
+	0.00051419,
+	0.00049076,
+	0.00046384,
+	0.00043477,
+	0.00040460,
+	0.00037414,
+	0.00034391,
+	0.00031418,
+	0.00028498,
+	0.00028498};
+
+/*-----------------------------------------------------------------------*/
+/* lowpass 8 FIR filter */
+/*-----------------------------------------------------------------------*/
+const double filter_low_8[] = {
+	0.00009588,
+	0.00003952,
+	-0.00002036,
+	-0.00008394,
+	-0.00015121,
+	-0.00022191,
+	-0.00029532,
+	-0.00037020,
+	-0.00044471,
+	-0.00051633,
+	-0.00058192,
+	-0.00063773,
+	-0.00067951,
+	-0.00070270,
+	-0.00070258,
+	-0.00067457,
+	-0.00061447,
+	-0.00051878,
+	-0.00038500,
+	-0.00021195,
+	0.00000000,
+	0.00024864,
+	0.00052980,
+	0.00083718,
+	0.00116239,
+	0.00149501,
+	0.00182273,
+	0.00213168,
+	0.00240679,
+	0.00263227,
+	0.00279216,
+	0.00287098,
+	0.00285442,
+	0.00273001,
+	0.00248787,
+	0.00212136,
+	0.00162772,
+	0.00100862,
+	0.00027058,
+	-0.00057473,
+	-0.00151036,
+	-0.00251409,
+	-0.00355868,
+	-0.00461222,
+	-0.00563882,
+	-0.00659928,
+	-0.00745211,
+	-0.00815454,
+	-0.00866380,
+	-0.00893830,
+	-0.00893903,
+	-0.00863083,
+	-0.00798372,
+	-0.00697404,
+	-0.00558557,
+	-0.00381043,
+	-0.00164976,
+	0.00088577,
+	0.00377578,
+	0.00699017,
+	0.01048954,
+	0.01422571,
+	0.01814267,
+	0.02217766,
+	0.02626255,
+	0.03032538,
+	0.03429206,
+	0.03808812,
+	0.04164059,
+	0.04487983,
+	0.04774127,
+	0.05016713,
+	0.05210790,
+	0.05352364,
+	0.05438503,
+	0.05467417,
+	0.05438503,
+	0.05352364,
+	0.05210790,
+	0.05016713,
+	0.04774127,
+	0.04487983,
+	0.04164059,
+	0.03808812,
+	0.03429206,
+	0.03032538,
+	0.02626255,
+	0.02217766,
+	0.01814267,
+	0.01422571,
+	0.01048954,
+	0.00699017,
+	0.00377578,
+	0.00088577,
+	-0.00164976,
+	-0.00381043,
+	-0.00558557,
+	-0.00697404,
+	-0.00798372,
+	-0.00863083,
+	-0.00893903,
+	-0.00893830,
+	-0.00866380,
+	-0.00815454,
+	-0.00745211,
+	-0.00659928,
+	-0.00563882,
+	-0.00461222,
+	-0.00355868,
+	-0.00251409,
+	-0.00151036,
+	-0.00057473,
+	0.00027058,
+	0.00100862,
+	0.00162772,
+	0.00212136,
+	0.00248787,
+	0.00273001,
+	0.00285442,
+	0.00287098,
+	0.00279216,
+	0.00263227,
+	0.00240679,
+	0.00213168,
+	0.00182273,
+	0.00149501,
+	0.00116239,
+	0.00083718,
+	0.00052980,
+	0.00024864,
+	0.00000000,
+	-0.00021195,
+	-0.00038500,
+	-0.00051878,
+	-0.00061447,
+	-0.00067457,
+	-0.00070258,
+	-0.00070270,
+	-0.00067951,
+	-0.00063773,
+	-0.00058192,
+	-0.00051633,
+	-0.00044471,
+	-0.00037020,
+	-0.00029532,
+	-0.00022191,
+	-0.00015121,
+	-0.00008394,
+	-0.00002036,
+	0.00003952,
+	0.00003952};
+
+/*-----------------------------------------------------------------------*/
+/* lowpass 9 FIR filter */
+/*-----------------------------------------------------------------------*/
+const double filter_low_9[] = {
+	-0.00033605,
+	-0.00032227,
+	-0.00029374,
+	-0.00024997,
+	-0.00019055,
+	-0.00011536,
+	-0.00002487,
+	0.00007952,
+	0.00019526,
+	0.00031834,
+	0.00044323,
+	0.00056289,
+	0.00066892,
+	0.00075194,
+	0.00080215,
+	0.00080995,
+	0.00076684,
+	0.00066621,
+	0.00050427,
+	0.00028084,
+	-0.00000000,
+	-0.00032946,
+	-0.00069392,
+	-0.00107509,
+	-0.00145063,
+	-0.00179505,
+	-0.00208103,
+	-0.00228107,
+	-0.00236926,
+	-0.00232336,
+	-0.00212670,
+	-0.00177006,
+	-0.00125328,
+	-0.00058643,
+	0.00020954,
+	0.00110278,
+	0.00205118,
+	0.00300380,
+	0.00390295,
+	0.00468697,
+	0.00529355,
+	0.00566337,
+	0.00574409,
+	0.00549424,
+	0.00488686,
+	0.00391278,
+	0.00258306,
+	0.00093071,
+	-0.00098883,
+	-0.00309821,
+	-0.00530003,
+	-0.00747988,
+	-0.00951048,
+	-0.01125686,
+	-0.01258232,
+	-0.01335486,
+	-0.01345387,
+	-0.01277669,
+	-0.01124472,
+	-0.00880870,
+	-0.00545293,
+	-0.00119815,
+	0.00389723,
+	0.00973749,
+	0.01619178,
+	0.02309791,
+	0.03026781,
+	0.03749425,
+	0.04455871,
+	0.05123992,
+	0.05732277,
+	0.06260716,
+	0.06691631,
+	0.07010422,
+	0.07206192,
+	0.07272208,
+	0.07206192,
+	0.07010422,
+	0.06691631,
+	0.06260716,
+	0.05732277,
+	0.05123992,
+	0.04455871,
+	0.03749425,
+	0.03026781,
+	0.02309791,
+	0.01619178,
+	0.00973749,
+	0.00389723,
+	-0.00119815,
+	-0.00545293,
+	-0.00880870,
+	-0.01124472,
+	-0.01277669,
+	-0.01345387,
+	-0.01335486,
+	-0.01258232,
+	-0.01125686,
+	-0.00951048,
+	-0.00747988,
+	-0.00530003,
+	-0.00309821,
+	-0.00098883,
+	0.00093071,
+	0.00258306,
+	0.00391278,
+	0.00488686,
+	0.00549424,
+	0.00574409,
+	0.00566337,
+	0.00529355,
+	0.00468697,
+	0.00390295,
+	0.00300380,
+	0.00205118,
+	0.00110278,
+	0.00020954,
+	-0.00058643,
+	-0.00125328,
+	-0.00177006,
+	-0.00212670,
+	-0.00232336,
+	-0.00236926,
+	-0.00228107,
+	-0.00208103,
+	-0.00179505,
+	-0.00145063,
+	-0.00107509,
+	-0.00069392,
+	-0.00032946,
+	-0.00000000,
+	0.00028084,
+	0.00050427,
+	0.00066621,
+	0.00076684,
+	0.00080995,
+	0.00080215,
+	0.00075194,
+	0.00066892,
+	0.00056289,
+	0.00044323,
+	0.00031834,
+	0.00019526,
+	0.00007952,
+	-0.00002487,
+	-0.00011536,
+	-0.00019055,
+	-0.00024997,
+	-0.00029374,
+	-0.00032227,
+	-0.00032227};
+
+#endif
+/*-----------------------------------------------------------------------*/
+/* End of highpass_table.h                                                */
+/*-----------------------------------------------------------------------*/
Binary file Sirtassa/311CLNOF.WAV has changed
Binary file Sirtassa/311CLNOF.mid has changed
Binary file Sirtassa/Lussier_bassoon.mid has changed
Binary file Sirtassa/Lussier_bassoon.wav has changed
Binary file Sirtassa/Lussier_mix.wav has changed
Binary file Sirtassa/Lussier_trumpet.mid has changed
Binary file Sirtassa/Lussier_trumpet.wav has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sirtassa/Sirtassa.m	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,257 @@
+%% Default Values
+%Audio and score information
+if(~exist('midiCell','var'))
+    midiCell = cell(2,1);
+    midiCell{1} = 'Lussier_bassoon.mid';
+    midiCell{2} = 'Lussier_trumpet.mid';
+    mixName = 'Lussier_mix.wav';
+    %mixName = '311CLNOF.WAV';
+    %midiCell{1} = '311CLNOF.mid';
+end
+if(~exist('blockSize','var'))   blockSize = 2048;   end
+if(~exist('overlap','var'))     overlap = 2;        end
+%Maximum frequency of the filter
+if(~exist('bandPassFilterMaxFreq','var'))    bandPassFilterMaxFreq = 10000; end
+%Number of band pass filters in the filter
+if(~exist('nbBandPassFilters','var'))    nbBandPassFilters = 20;end
+%Maximum updates per frame
+if(~exist('maxUpdates','var'))    maxUpdates = 2;end
+%Number of partials in the model
+if(~exist('nbPartials','var'))    nbPartials = 8;end
+if(~exist('plotRefinedScore','var'))    plotRefinedScore = 0;end
+if(~exist('plotPartial','var'))    plotPartial = 0;end
+if(~exist('plotFilter','var'))    plotFilter = 0;end
+%Nummber of instrument in the mix.
+nbInstrument = length(midiCell);
+fftSize = blockSize;
+
+%Weights of the harmonic series
+partialsWeights = ones(nbPartials,nbInstrument);
+
+colors = 'rwm';
+%% Initialisation
+hopSize =blockSize/overlap;                   %Hopsize
+HFFTS = fftSize/2+1;                    %Size of the usefull part of the fft (half+1)
+[audio, fs] = wavread(mixName);
+
+% zeropadding the audio length
+audio(end:end+hopSize-mod(length(audio),hopSize)) = 0;
+audioLength = length(audio);
+
+scoreLength = audioLength/hopSize - overlap+1; %Number of frames
+wdw = hamming(blockSize);
+
+tic
+%% Create filters
+filterBasis = createBPFilters(bandPassFilterMaxFreq,nbBandPassFilters,fftSize,fftSize/fs);
+filterCoefficients = ones(nbBandPassFilters,nbInstrument);
+%% Creating the score
+originalScore = createScore(scoreLength,midiCell,fs/hopSize,fftSize/fs);
+originalScore(scoreLength+1:end,:) = [];
+gains = double(originalScore'>0);
+%% Creating spectrogram
+magnitude = zeros(fftSize, scoreLength);
+phase = zeros(fftSize, scoreLength);
+audioVector = zeros(fftSize,1);
+for curFrame = 1:scoreLength
+    audioVector(1:blockSize) = audio(hopSize*(curFrame-1)+1:hopSize*(curFrame-1)+blockSize,1).*wdw;
+    spectrogramVector = fft(audioVector);
+    magnitude(:,curFrame) = abs(spectrogramVector);
+    phase(:,curFrame) = angle(spectrogramVector);
+end
+magnitude(HFFTS+1:end,:) = [];
+phase(HFFTS+1:end,:) = [];
+maxSizeWindows = 400;
+hammingWindows = cell(1,maxSizeWindows);
+for len = 1:maxSizeWindows
+    hammingWindows{len} = hamming(len);
+end
+
+%% Refine Score and create Excitation Spectrum
+refinedScore = originalScore;   %score to be refiened
+basicSpec = zeros(HFFTS, scoreLength);        %Basic theoretical spectrogram
+excitationSpectrums = cell(nbInstrument,scoreLength);   %cell for each frame
+largerES = cell(nbInstrument,scoreLength);   %cell for each frame
+
+for ins = 1:nbInstrument                %for each isntrument
+    for curFrame = 1: scoreLength        %for each frame
+        excitationSpectrums{ins,curFrame} = sparse(zeros(HFFTS,nbPartials));
+        largerES{ins,curFrame} = sparse(zeros(HFFTS,nbPartials));
+        if(originalScore(curFrame,ins))        %if there is a note
+            %Refine score and creates Excitation Spectrum
+            [refinedScore(curFrame,ins), width] = refineScore(magnitude(:,curFrame),originalScore(curFrame,ins));
+            excitationSpectrums{ins,curFrame} = sparse(createExcitationSpectrums(refinedScore(curFrame,ins),HFFTS,nbPartials,partialsWeights(:,ins),width,hammingWindows));
+            largerES{ins,curFrame} = sparse(createExcitationSpectrums(refinedScore(curFrame,ins),HFFTS,nbPartials,partialsWeights(:,ins),2*width,hammingWindows));
+        end
+        basicSpec(:,curFrame) = basicSpec(:,curFrame) + (excitationSpectrums{ins,curFrame}*partialsWeights(:,ins))*gains(ins,curFrame); %Spectrogram without update
+    end
+end
+%% Plot spectrogram and add original and refined score
+if (plotRefinedScore)
+    figure(1),imagesc(log(10*magnitude(1:fftSize/16,:)+1)), axis xy
+    plotableScore = originalScore+1;
+    plotableScore(plotableScore==1) = 0;
+    hold on ,plot(plotableScore,'.k'),
+    
+    for harm = 1 : nbPartials
+        for ins = nbInstrument:-1:1
+            plot(refinedScore(:,ins)*harm+1,['.' colors(ins)]), colorbar
+        end
+    end
+end
+%% Online Processing
+%Values that can be changed by the model.
+maskForChangeableValues = basicSpec > 10^-4;
+maskedSpectrogram = magnitude.*maskForChangeableValues;
+bufferSize = 100;
+nextProcess = 1;
+for curFrame = 1:scoreLength
+    if sum(refinedScore(curFrame,:),2)
+        UpdateGainCoefficientsOL2
+        if (curFrame==nextProcess)
+            first = max(curFrame-bufferSize+1,1);
+            currentMag = magnitude(:,first:curFrame);
+            tmpMaskForChangeableValues = basicSpec(:,first:curFrame) > 10^-4;
+            tmpMaskedSpectrogram = currentMag.*tmpMaskForChangeableValues;
+            len = curFrame-first+1;
+            for  nbUpdates = 1:maxUpdates           %update loop
+                UpdatePartialCoefficientsOL
+                UpdateFilterCoefficientsOL
+                if (plotFilter)
+                    %%%Filter
+                    figure(4),plot(outlook(1:blockSize/8,:)), title('Filter')
+                end
+                if (plotPartial)
+                    %%%Decay
+                    figure(5),stem(partialsWeights), title('Partial Weights')
+                end
+            end
+            nextProcess = min(ceil(curFrame*1.2),scoreLength)
+            %bufferSize = round(max(bufferSize,curFrame*0.5));
+            if (plotFilter)
+                %%%Filter
+                figure(4),plot(outlook(1:blockSize/8,:)), title('Filter')
+            end
+            if (plotPartial)
+                %%%Decay
+                figure(5),stem(partialsWeights), title('Partial Weights')
+                
+            end
+        end
+    end
+end
+timeV = toc;
+fprintf('Time: %6.3g s, %6.2g times real time \t \n ', timeV, timeV*fs/audioLength);
+
+
+% Remodel Spectrogram
+ECA = cell(nbInstrument,1);
+xHat = zeros(HFFTS,scoreLength);
+for ins = 1:nbInstrument
+    ECA{ins} = sparse(zeros(HFFTS,scoreLength));
+    for frame = 1:scoreLength
+        ECA{ins}(:,frame) = filterBasis * filterCoefficients(:,ins).*(largerES{ins,frame}*partialsWeights(:,ins));
+    end
+    xHat = xHat + ECA{ins}.*repmat(gains(ins,:),HFFTS,1);
+end
+%% Final plot
+%%%Spectrogram (comparison with basic and final)
+% % bMax = max(max(log(10*basicSpec+1)));
+% % xMax = max(max(log(10*xHat+1)));
+% % mMax = max(max(log(10*magnitude+1)));
+% % tMax = max([bMax mMax xMax]);
+% % figure(3), subplot(3,1,1), imagesc(log(10*basicSpec(1:hopSize/2,:)+1)), axis xy, linkaxes, caxis([0 tMax]), colorbar, title('Basic Model')
+% % subplot(3,1,2), imagesc(log(10*xHat(1:hopSize/2,:)+1)), axis xy, linkaxes, caxis([0 tMax]), colorbar, title('Optimised Spectrogram')
+% % subplot(3,1,3), imagesc(log(10*magnitude(1:hopSize/2,:)+1)), axis xy, linkaxes, caxis([0 tMax]), colorbar, title('Actual Spectrogram')
+% %
+% %
+% % %%%Filter
+% % figure(4),plot(outlook(1:blockSize/8,:)), title('Filter')
+% %
+% % %%%Decay
+% % figure(5),stem(partialsWeights), title('Partial Weights')
+
+%% Writing
+%extraInfo = [sprintf('_%d_%d_%d_%d_%d_%d',blockSize,overlap,maxUpdates,nbPartials,nbBandPassFilters,bandPassFilterMaxFreq) specExp];
+finalScale = zeros(audioLength,1);
+freq = zeros(fftSize,1);
+finalAudio = cell(nbInstrument+1,1);
+finalAudioMasked = cell(nbInstrument,1);
+
+wdw2 = hamming(fftSize);
+nbMaskingTechniques = 4;
+maskingCell = cell(1,nbMaskingTechniques);
+maskingCell{1} = 'raw';
+maskingCell{2} = 'per';
+maskingCell{3} = 'sha';
+maskingCell{4} = '10p';
+finalMask = cell(nbInstrument,nbMaskingTechniques); %4 is the number of different masking techniques
+for ins = 1:nbInstrument
+    finalMask{ins,1} = sparse(zeros(HFFTS,scoreLength));
+    finalMask{ins,4} = sparse(zeros(HFFTS,scoreLength));
+    for curFrame = 1:scoreLength
+        finalMask{ins,1}(:,curFrame) = filterBasis * filterCoefficients(:,ins).*(excitationSpectrums{ins,curFrame}*partialsWeights(:,ins));
+        finalMask{ins,4}(:,curFrame) = filterBasis * filterCoefficients(:,ins).*(largerES{ins,curFrame}*partialsWeights(:,ins));
+    end
+    
+    finalMask{ins,1} = finalMask{ins,1}.*repmat(gains(ins,:),HFFTS,1);
+    finalMask{ins,4} = finalMask{ins,4}.*repmat(gains(ins,:),HFFTS,1);
+    
+    % masking strategy 1
+    finalMask{ins,2} = magnitude .* (finalMask{ins,4} ./ (xHat+eps));
+    
+    % masking strategy 2
+    finalMask{ins,3} = magnitude .* ( (finalMask{ins,4}+eps) ./ (xHat+eps));
+    
+    % masking strategy 3
+    finalMask{ins,4} = magnitude .* ( (finalMask{ins,4}+0.1 * eps) ./ (xHat+eps));
+    
+    finalAudio{ins} = zeros(audioLength,1);
+    finalAudioMasked{ins} = zeros(audioLength,1);
+end
+
+% sonifying the model
+finalAudio{nbInstrument+1} = zeros(audioLength,1);
+%Overlap and add
+for curFrame = 1:scoreLength
+    freq(1:HFFTS) = xHat(:,curFrame).*exp(1i*phase(:,curFrame));
+    freq(HFFTS+1:fftSize) = freq(HFFTS-1:-1:2);
+    faudio = real(ifft(freq)).*wdw2;
+    finalAudio{nbInstrument+1}((curFrame-1)*hopSize+1:(curFrame-1)*hopSize+fftSize,1) = finalAudio{nbInstrument+1}((curFrame-1)*hopSize+1:(curFrame-1)*hopSize+fftSize,1) + faudio;
+    for ins = 1:nbInstrument
+        freq(1:HFFTS) = finalMask{ins,1}(:,curFrame).*exp(1i*phase(:,curFrame));
+        freq(HFFTS+1:fftSize) = freq(HFFTS-1:-1:2);
+        faudio = real(ifft(freq)).*wdw2;
+        finalAudio{ins}((curFrame-1)*hopSize+1:(curFrame-1)*hopSize+fftSize,1) = finalAudio{ins}((curFrame-1)*hopSize+1:(curFrame-1)*hopSize+fftSize,1) + faudio;
+    end
+    finalScale((curFrame-1)*hopSize+1:(curFrame-1)*hopSize+fftSize,1) = finalScale((curFrame-1)*hopSize+1:(curFrame-1)*hopSize+fftSize,1) + wdw2;
+end
+
+for ins = 1:nbInstrument
+    finalAudio{ins} = finalAudio{ins}./finalScale;
+    %    wavwrite(finalAudio{ins},fs,16,[midiCell{ins}(1:4) '_' num2str(ins) '_' maskingCell{1} extraInfo '.wav']);
+end
+finalAudio{nbInstrument+1} = finalAudio{nbInstrument+1}./finalScale;
+%wavwrite(finalAudio{nbInstrument+1},fs,16,[mixName(1:4) '_0_' maskingCell{1} extraInfo '.wav']);
+
+% sonifying the masked version
+%Overlap and add
+for tech = 2:nbMaskingTechniques
+    finalScale = zeros(audioLength,1);
+    for curFrame = 1:scoreLength
+        for ins = 1:nbInstrument
+            freq(1:HFFTS) = finalMask{ins,tech}(:,curFrame).*exp(i*phase(:,curFrame));
+            freq(HFFTS+1:fftSize) = freq(HFFTS-1:-1:2);
+            faudio = real(ifft(freq)).*wdw2;
+            finalAudioMasked{ins}((curFrame-1)*hopSize+1:(curFrame-1)*hopSize+fftSize,1) = finalAudioMasked{ins}((curFrame-1)*hopSize+1:(curFrame-1)*hopSize+fftSize,1) + faudio;
+        end
+        finalScale((curFrame-1)*hopSize+1:(curFrame-1)*hopSize+fftSize,1) = finalScale((curFrame-1)*hopSize+1:(curFrame-1)*hopSize+fftSize,1) + wdw2;
+    end
+    for ins = 1:nbInstrument
+        finalAudioMasked{ins} = finalAudioMasked{ins}./finalScale;
+        %    wavwrite(finalAudioMasked{ins},fs,16,[midiCell{ins}(1:4) '_' num2str(ins) '_' maskingCell{tech} extraInfo '.wav']);
+    end
+end
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sirtassa/UpdateFilterCoefficientsOL.m	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,36 @@
+GEA = cell(nbInstrument,nbBandPassFilters);
+
+
+xHat = sparse(zeros(HFFTS,len));
+
+% Model Spectrogram
+for ins = 1:nbInstrument
+    for filterInd = 1:nbBandPassFilters
+        GEA{ins,filterInd} = sparse(zeros(HFFTS, len));
+        for frame = first:curFrame
+            GEA{ins,filterInd}(:,frame-first+1) = (filterBasis(:,filterInd)*gains(ins,frame)).*(excitationSpectrums{ins,frame}*partialsWeights(:,ins));
+        end
+        xHat = xHat + GEA{ins,filterInd}*filterCoefficients(filterInd,ins);
+    end
+end
+
+%Compute distance and r
+distFilter(nbUpdates) = sum(sum( tmpMaskedSpectrogram .* log((tmpMaskedSpectrogram+eps) ./ (xHat+eps)) - tmpMaskedSpectrogram + xHat));
+r = (currentMag+eps)./(xHat+eps);
+updateFilterCoeff = ones(nbBandPassFilters,nbInstrument);
+
+%Update Filter Coefficients
+for ins = 1:nbInstrument
+    for filterInd = 1:nbBandPassFilters
+        updateFilterCoeff(filterInd,ins) = (sum(sum(GEA{ins,filterInd}.*r))+eps)/(sum(sum(GEA{ins,filterInd}))+eps);
+    end
+end
+clear GEA;
+filterCoefficients = filterCoefficients.*updateFilterCoeff;
+for ins=1:nbInstrument
+    maxValue = max(filterCoefficients(:,ins));
+    filterCoefficients(:,ins) = filterCoefficients(:,ins) / maxValue;
+    gains(ins,:) = gains(ins,:) * maxValue;
+end
+outlook = filterBasis * filterCoefficients;
+%     figure, plot(outlook(1:blockSize/8,:));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sirtassa/UpdateGainCoefficientsOL2.m	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,22 @@
+ECA = zeros(HFFTS,nbInstrument);
+
+for ins = 1:nbInstrument
+   ECA(:,ins) = filterBasis * filterCoefficients(:,ins).*(excitationSpectrums{ins,curFrame}*partialsWeights(:,ins));
+end
+
+xHat = sum(ECA.*repmat(gains(:,curFrame)',HFFTS,1),2);
+
+maskedSpectrogram = magnitude(:,curFrame).* basicSpec(:,curFrame) > 10^-4;
+
+
+%Compute distance and r
+distGain = sum(sum( maskedSpectrogram .* log((maskedSpectrogram+eps) ./ (xHat+eps)) - maskedSpectrogram + xHat));
+r = (magnitude(:,curFrame)+eps)./(xHat+eps);
+
+%Update Gain Coefficients
+updateGainsCoeff = sum(ECA.*repmat(r,1,nbInstrument) +eps,1)./sum(ECA +eps,1);
+
+clear ECA;
+gains(:,curFrame) = gains(:,curFrame).*updateGainsCoeff';
+
+%     figure;plot(gains');
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sirtassa/UpdatePartialCoefficientsOL.m	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,33 @@
+GEH = cell(nbInstrument,nbPartials);
+
+% Remodel Spectrogram
+xHat = zeros(HFFTS,len);
+for ins = 1:nbInstrument
+    for harm = 1:nbPartials
+        GEH{ins,harm} = sparse(zeros(HFFTS, len));
+        for frame = first:curFrame
+            GEH{ins,harm}(:,frame-first+1) = (filterBasis * filterCoefficients(:,ins)*gains(ins,frame)).*excitationSpectrums{ins,frame}(:,harm);
+        end
+        xHat = xHat + GEH{ins,harm}*partialsWeights(harm,ins);
+    end
+end
+
+%Compute distance and r
+distPartial(nbUpdates) = sum(sum( tmpMaskedSpectrogram .* log((tmpMaskedSpectrogram+eps) ./ (xHat+eps)) - tmpMaskedSpectrogram + xHat));
+r = (currentMag+eps)./(xHat+eps);
+
+%Update partialsWeights
+updateGammaCoeff = ones(nbPartials,nbInstrument);
+for ins=1:nbInstrument
+    for harm = 1:nbPartials
+        updateGammaCoeff(harm,ins) = sum(sum(GEH{ins,harm}.*r +eps,1))./sum(sum(GEH{ins,harm} +eps,1));
+    end
+end
+clear GEH
+partialsWeights = partialsWeights.*updateGammaCoeff;
+for ins=1:nbInstrument
+    maxValue = max(partialsWeights(:,ins));
+    partialsWeights(:,ins) = partialsWeights(:,ins) / maxValue;
+    gains(ins,:) = gains(ins,:) * maxValue;
+end
+%     figure;stem(partialsWeights), title(sprintf('Partial Weights (iter%d)',nbUpdates));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sirtassa/createBPFilters.m	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,23 @@
+function filterBasis = createBPFilters(maxFreq,nbBandPassFilters,fftSize,factor)
+melfreq = linspace(0,2595*log10(1 + maxFreq/700),nbBandPassFilters);
+hertzfreq = 700*(10.^(melfreq/2595)-1);
+
+filterBasis = zeros(fftSize/2+1,nbBandPassFilters);
+mid = floor(hertzfreq(1)*factor+1);
+last = floor(hertzfreq(2)*factor+1);
+if (mid~=last)
+    
+    filterBasis(mid:last,1) = 1:-1/(last-mid):0;
+    for ind = 1:length(hertzfreq) -2
+        first = floor(hertzfreq(ind)*factor+1);
+        mid = floor(hertzfreq(ind+1)*factor+1);
+        last = floor(hertzfreq(ind +2)*factor+1);
+        filterBasis(first:mid,ind+1) = 0:1/(mid-first):1;
+        filterBasis(mid:last,ind+1) = 1:-1/(last-mid):0;
+    end
+    first = floor(hertzfreq(end-1)*factor+1);
+    mid = floor(hertzfreq(end)*factor+1);
+    filterBasis(first:mid,end) = 0:1/(mid-first):1;
+% else
+%     error('myApp:filterSize', 'Too many filters for parameters')
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sirtassa/createExcitationSpectrums.m	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,16 @@
+function spec = createExcitationSpectrums(pitch,size,nbPartials,partialsWeights,dif,hammingWindows)
+spec = zeros(size,nbPartials);
+if (pitch)
+    for harm = 1:nbPartials
+        freq  =pitch*harm+1;
+        low = floor(freq-dif/2);
+        low = max(low,1);
+        high = ceil(freq+dif/2);
+        len = high-low+1;
+        
+        spec(low:high,harm) = hammingWindows{len}*partialsWeights(harm);
+        spec(low:high,harm) = spec(low:high,harm)/max(spec(low:high,harm));
+    end
+end
+spec(size+1:end,:)=[];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sirtassa/createScore.m	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,21 @@
+function score = createScore(scoreLength,MIDI,timeFactor,freqFactor)
+
+nbInstrument = length(MIDI);
+instruments = cell(nbInstrument,1);
+for ins = 1:nbInstrument
+    instruments{ins} = midi2nmat( MIDI{ins});
+end
+%Score frame by frame
+score = zeros(scoreLength,nbInstrument);
+
+% instrument : onset, offset, frequency
+for ins = 1:nbInstrument
+    
+    instruments{ins}(:,1) = max(1,round(instruments{ins}(:,6)*timeFactor)-1);
+    instruments{ins}(:,2) = round((instruments{ins}(:,6) + instruments{ins}(:,7))*timeFactor);
+    instruments{ins}(:,3) = 440/32*2.^((instruments{ins}(:,4)-9)/12);
+    instruments{ins}(:,4:end) = [];
+    for j = 1: size(instruments{ins},1)
+        score(instruments{ins}(j,1):instruments{ins}(j,2),ins) = instruments{ins}(j,3)*freqFactor;
+    end
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sirtassa/midi2nmat.m	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,999 @@
+function [nmat,n] = midi2nmat(filename)
+% nmat = midi2nmat(filename)
+% Read midi file FILENAME into Matlab variable NMAT (Beta)
+% Based on Ken Schutte's m-files (readmidi, midiInfo, getTempoChanges)
+% This beta might replace the mex-files used in the previous version of the toolbox as 
+% newer versions of Matlab (7.4+) and various OS's need new compilations 
+% of the mex files. Using the C sources and the compiled mex files provides
+% faster reading of midi files but because the compatibility is limited, this 
+% simple workaround is offered. This beta version is very primitive,
+% though. - Tuomas Eerola
+%
+% KNOWN PROBLEMS: - Tempo changes are handled in a simple way
+%                 - Extra messages are not retained  
+%                 - Channels may not be handled correctly    
+% 
+% For more information on Ken Schutte's functions, see 
+% http://www.kenschutte.com/software
+%
+% CREATED ON 31.12.2007 BY TE (MATLAB 7.4 MacOSX 10.4)
+%
+
+%% USE KEN SCHUTTE'S FUNCTIONS
+m = readmidi(filename);
+n = midiInfo(m,0);
+[tempos, tempos_time] = getTempoChanges(m);
+
+%% CONVERT OUTPUT INTO MIDI TOOLBOX NMAT FORMAT
+nmat(:,6) = n(:,5);
+nmat(:,7) = n(:,6)-n(:,5); % duration
+nmat(:,3) = n(:,2);
+nmat(:,4) = n(:,3);
+nmat(:,5) = n(:,4);
+
+%% CHECK IF MULTIPLE TEMPI
+if isempty(tempos), tempos=500000;end % some files may not contain the tempo, use default in that case
+if length(tempos)>1
+	% here for diff tempi....
+
+	disp('WARNING: Multiple tempi detected, simple recoding of timing (seconds, not beats!)');
+    disp(num2str(60./(tempos./1000000)))
+
+    
+    tc_ind=0;
+    starttime=0;
+	for i=1:length(tempos_time)-1
+	   	tempo_begin = (tempos_time(i+1)-tempos_time(i))/m.ticks_per_quarter_note*tempos(i)/1000000;
+        tempo_begin = tempo_begin+starttime;
+        starttime = tempo_begin;
+        tc_ind=[tc_ind tempo_begin];
+		end
+	nmat2=nmat;
+	for i=1:length(tc_ind)
+		if i==length(tc_ind)
+			time_index = nmat(:,6)>=tc_ind(i);
+		else
+			time_index = nmat(:,6)>=tc_ind(i); %& nmat(:,6)<=tc_ind(i+1);
+		end
+		
+		timeratio = tempos(i)/tempos(1);
+
+% realign timing after tempo changes
+		tmp1 = nmat2(time_index,:);
+		tmp2 = n(time_index,5).*timeratio; tmp2=tmp2(1);
+		realign = tmp1(1,6)-tmp2; % previous onset time
+		nmat2(time_index,6) = (n(time_index,5).*timeratio)+realign;
+		nmat2(time_index,7) = nmat2(time_index,7).*timeratio;
+    end
+	nmat(:,1) = n(:,5)/(tempos(1)/1000000); % beats are not modified according to tempi
+	nmat(:,2) = (n(:,6)-n(:,5))/(tempos(1)/1000000);
+
+else
+	nmat(:,1) = n(:,5)/(tempos(1)/1000000);
+	nmat(:,2) = (n(:,6)-n(:,5))/(tempos(1)/1000000);
+end
+
+% postprocessing...
+
+% IF CHANNEL IS EMPTY
+
+if nmat(:,3)==0
+    nmat(:,3)=1;
+end
+
+%% FUNCTIONS
+
+
+function [Notes,endtime] = midiInfo(midi,outputFormat,tracklist)
+% [Notes,endtime] = midiInfo(midi,outputFormat,tracklist)
+%
+% Takes a midi structre and generates info on notes and messages
+% Can return a matrix of note parameters and/or output/display 
+%   formatted table of messages
+%
+% Inputs:
+%  midi - Matlab structure (created by readmidi.m)
+%  tracklist - which tracks to show ([] for all)
+%  outputFormat
+%   - if it's a string write the formated output to the file
+%   - if 0, don't display or write formatted output
+%   - if 1, just display (default)
+% 
+% outputs:
+%   Notes - a matrix containing a list of notes, ordered by start time
+%     column values are:
+%      1     2    3  4   5  6  7       8
+%     [track chan nn vel t1 t2 msgNum1 msgNum2]
+%   endtime - time of end of track message
+%
+%---------------------------------------------------------------
+% Subversion Revision: 14 (2006-11-28)
+%  minor alterations by TE 2.1.2008
+% This software can be used freely for non-commerical use.
+% Visit http://www.kenschutte.com/software for more
+%   documentation, copyright info, and updates.
+%---------------------------------------------------------------
+
+
+if nargin<3
+  tracklist=[];
+  if nargin<2
+    outputFormat=1;
+  end
+end
+if (isempty(tracklist))
+  tracklist = 1:length(midi.track);
+end
+
+[tempos, tempos_time] = getTempoChanges(midi);
+
+current_tempo = 500000;  % default tempo
+
+fid = -1;
+if (ischar(outputFormat))
+  fid = fopen(outputFormat,'w');
+end
+
+endtime = -1;
+
+% each row:
+%  1     2    3  4   5  6  7       8
+% [track chan nn vel t1 t2 msgNum1 msgNum2]
+Notes = zeros(0,8);
+
+for i=1:length(tracklist)
+  tracknum = tracklist(i);
+  cumtime=0;
+  seconds=0;
+
+  Msg = cell(0);
+  Msg{1,1} = 'chan';
+  Msg{1,2} = 'deltatime';
+  Msg{1,3} = 'time';
+  Msg{1,4} = 'name';
+  Msg{1,5} = 'data';
+
+  runnro=1;
+  
+  for msgNum=1:length(midi.track(tracknum).messages)
+
+    currMsg = midi.track(tracknum).messages(msgNum);
+    
+    midimeta  = currMsg.midimeta;
+    deltatime = currMsg.deltatime;
+    data      = currMsg.data;
+    type      = currMsg.type;
+    chan      = currMsg.chan;
+
+    cumtime = cumtime + deltatime;
+    %current_tempo/midi.ticks_per_quarter_note;
+    %debug = deltatime*1e-6*current_tempo/midi.ticks_per_quarter_note;
+
+    seconds = seconds + deltatime*1e-6*current_tempo/midi.ticks_per_quarter_note;
+    [mx ind] = max(find(cumtime >= tempos_time));
+    
+    %% % ADDED BY TE 1.1.2008
+    if isempty(ind)
+        % do nothing
+    else
+        current_tempo = tempos(ind);
+    end
+    %% end
+    
+    % find start/stop of notes:
+    %    if (strcmp(name,'Note on') && (data(2)>0))
+    % note on with vel>0:
+    if (midimeta==1 && type==144 && data(2)>0)
+      % note on:
+      
+      if isempty(Notes)
+         Notes(1,:) = [tracknum chan data(1) data(2) seconds 0 runnro -1];
+         runnro=runnro+1;
+      else
+%       Notes(end+1,:) = [tracknum chan data(1) data(2) seconds 0 msgNum -1]
+       Notes(end+1,:) = [tracknum chan data(1) data(2) seconds 0 runnro -1];
+       runnro=runnro+1;
+      end
+       %    elseif ((strcmp(name,'Note on') && (data(2)==0)) || strcmp(name,'Note off'))
+       % note on with vel==0 or note off:
+  
+    elseif (midimeta==1 && ( (type==144 && data(2)==0) || type==128 ))
+      
+      % note off:
+      %      % find index, wther tr,chan,and nn match, and not complete
+      
+      ind = find((...
+	  (Notes(:,1)==tracknum) + ...
+	  (Notes(:,2)==chan) + ...
+	  (Notes(:,3)==data(1)) + ...
+	  (Notes(:,8)==-1)...
+	  )==4);
+      
+      if (length(ind)==0)
+	error('ending non-open note?');
+      elseif (length(ind)>1)
+	disp('warning: found multiple matches in endNote, taking first...');
+	ind = ind(1);
+      end
+      
+      % set info on ending:
+      Notes(ind,6) = seconds;
+      Notes(ind,8) = msgNum;
+      
+      % end of track:
+    elseif (midimeta==0 && type==47)
+      if (endtime == -1)
+	endtime = seconds;
+      else
+	disp('two "end of track" messages?');
+	endtime(end+1) = seconds;
+      end
+    
+    
+    end
+    
+    % we could check to make sure it ends with
+    %  'end of track'
+
+    
+    if (outputFormat ~= 0)
+      % get some specific descriptions:
+      name = num2str(type);
+      dataStr = num2str(data);
+
+      if (isempty(chan))
+	Msg{msgNum,1} = '-';
+      else
+	Msg{msgNum,1} = num2str(chan);
+      end
+      
+      Msg{msgNum,2} = num2str(deltatime);
+      Msg{msgNum,3} = formatTime(seconds);
+      
+      if (midimeta==0)
+	Msg{msgNum,4} = 'meta';
+      else
+	Msg{msgNum,4} = '';
+      end
+      
+      [name,dataStr] = getMsgInfo(midimeta, type, data);
+      Msg{msgNum,5} = name;
+      Msg{msgNum,6} = dataStr;
+    end
+    
+    
+  end
+  
+  if (outputFormat ~= 0)
+    printTrackInfo(Msg,tracknum,fid);
+  end
+  
+end
+
+% make this an option!!!
+% - I'm not sure why it's needed...
+% remove start silence:
+
+%_ removed by TE 
+%_first_t = min(Notes(:,5));
+%_Notes(:,5) = Notes(:,5) - first_t;
+%_Notes(:,6) = Notes(:,6) - first_t;
+
+% sort Notes by start time:
+[junk,ord] = sort(Notes(:,5));
+Notes = Notes(ord,:);
+
+
+if (fid ~= -1)
+  fclose(fid);
+end
+
+
+
+
+
+
+
+
+
+
+
+function printTrackInfo(Msg,tracknum,fid)
+
+
+% make cols same length instead of just using \t
+for i=1:size(Msg,2)
+  maxLen(i)=0;
+  for j=1:size(Msg,1)
+    if (length(Msg{j,i})>maxLen(i))
+      maxLen(i) = length(Msg{j,i});
+    end
+  end
+end
+
+
+s='';
+s=[s sprintf('--------------------------------------------------\n')];
+s=[s sprintf('Track %d\n',tracknum)];
+s=[s sprintf('--------------------------------------------------\n')];
+
+if (fid == -1)
+  disp(s)
+else
+  fprintf(fid,'%s',s);
+end
+
+
+for i=1:size(Msg,1)
+  line='';
+  for j=1:size(Msg,2)
+    sp = repmat(' ',1,5+maxLen(j)-length(Msg{i,j}));
+    m = Msg{i,j};
+    m = m(:)';  % ensure column vector
+%    line = [line Msg{i,j} sp];
+    line = [line m sp];
+  end
+  
+  if (fid == -1)
+    disp(line)
+  else
+    fprintf(fid,'%s\n',line);
+  end
+
+end
+
+
+
+function s=formatTime(seconds)
+
+minutes = floor(seconds/60);
+secs = seconds - 60*minutes;
+
+s = sprintf('%d:%2.3f',minutes,secs);
+
+
+
+function [name,dataStr]=getMsgInfo(midimeta, type, data)
+
+% meta events:
+if (midimeta==0)
+  if     (type==0);  name = 'Sequence Number';            len=2;  dataStr = num2str(data);
+  elseif (type==1);  name = 'Text Events';                len=-1; dataStr = char(data);
+  elseif (type==2);  name = 'Copyright Notice';           len=-1; dataStr = char(data);
+  elseif (type==3);  name = 'Sequence/Track Name';        len=-1; dataStr = char(data);
+  elseif (type==4);  name = 'Instrument Name';            len=-1; dataStr = char(data);
+  elseif (type==5);  name = 'Lyric';                      len=-1; dataStr = char(data);
+  elseif (type==6);  name = 'Marker';                     len=-1; dataStr = char(data);
+  elseif (type==7);  name = 'Cue Point';                  len=-1; dataStr = char(data);
+  elseif (type==32); name = 'MIDI Channel Prefix';        len=1;  dataStr = num2str(data);
+  elseif (type==47); name = 'End of Track';               len=0;  dataStr = '';
+  elseif (type==81); name = 'Set Tempo';                  len=3;   
+    val = data(1)*16^4+data(2)*16^2+data(3); dataStr = ['microsec per quarter note: ' num2str(val)];
+  elseif (type==84); name = 'SMPTE Offset';               len=5;   
+      if size(data)==5
+      dataStr = ['[hh mm ss fr ff]=' num2str(data)];
+      else
+     dataStr = ['[hh mm ss fr ff]=' num2str(data')];
+      end
+  elseif (type==88); name = 'Time Signature';             len=4;   
+    dataStr = [num2str(data(1)) '/' num2str(data(2)) ', clock ticks and notated 32nd notes=' num2str(data(3)) '/' num2str(data(4))];
+  elseif (type==89); name = 'Key Signature';              len=2;   
+    % num sharps/flats (flats negative)
+    if (data(1)>=0)
+       %       1   2    3    4   5     6    7   
+      ss={'C','G','D', 'A', 'E','B',  'F#', 'C#'};
+        if data(1)>7
+        dataStr='C'; % ADDED BY TE 1.1.2008
+        else
+      dataStr = ss{data(1)+1};
+        end
+      
+    else
+       %    1   2    3    4   5     6    7   
+       ss={'F','Bb','Eb','Ab','Db','Gb','Cb'};
+       dataStr = ss{abs(data(1))};
+    end
+    if (data(2)==0)
+      dataStr = [dataStr ' Major'];
+    else
+      dataStr = [dataStr ' Minor'];
+    end
+    
+  elseif (type==89); name = 'Sequencer-Specific Meta-event';   len=-1;  
+    dataStr = char(data);
+    % !! last two conflict...
+  
+  else
+    name = ['UNKNOWN META EVENT: ' num2str(type)]; dataStr = num2str(data);
+  end
+  
+% meta 0x21 = MIDI port number, length 1 (? perhaps)
+else
+
+  % channel voice messages:  
+  %  (from event byte with chan removed, eg 0x8n -> 0x80 = 128 for
+  %  note off)
+  if     (type==128);  name = 'Note off';                 len=2; dataStr = ['nn=' num2str(data(1)) '  vel=' num2str(data(2))];
+  elseif (type==144);  name = 'Note on';                  len=2; dataStr = ['nn=' num2str(data(1)) '  vel=' num2str(data(2))];
+  elseif (type==160); name = 'Polyphonic Key Pressure';   len=2; dataStr = ['nn=' num2str(data(1)) '  vel=' num2str(data(2))];
+  elseif (type==176); name = 'Controller Change';         len=2; dataStr = ['ctrl=' controllers(data(1)) '  value=' num2str(data(2))];
+  elseif (type==192); name = 'Program Change';            len=1; dataStr = ['instr=' num2str(data)];
+  elseif (type==208); name = 'Channel Key Pressure';      len=1; dataStr = ['vel=' num2str(data)];
+  elseif (type==224); name = 'Pitch Bend';                len=2; 
+    val = data(1)+data(2)*256;
+    val = base2dec('2000',16) - val;
+    dataStr = ['change=' num2str(val) '?'];
+  
+  % channel mode messages:
+  %  ... unsure about data for these... (do some have a data byte and
+  %  others not?)
+  %
+  % 0xC1 .. 0xC8
+  elseif (type==193);  name = 'All Sounds Off';            dataStr = num2str(data);
+  elseif (type==194);  name = 'Reset All Controllers';     dataStr = num2str(data);
+  elseif (type==195); name = 'Local Control';             dataStr = num2str(data);
+  elseif (type==196); name = 'All Notes Off';             dataStr = num2str(data);
+  elseif (type==197); name = 'Omni Mode Off';             dataStr = num2str(data);
+  elseif (type==198); name = 'Omni Mode On';              dataStr = num2str(data);
+  elseif (type==199); name = 'Mono Mode On';              dataStr = num2str(data);
+  elseif (type==200); name = 'Poly Mode On';              dataStr = num2str(data);
+  
+    % sysex, F0->F7
+  elseif (type==240); name = 'Sysex 0xF0';              dataStr = num2str(data);
+  elseif (type==241); name = 'Sysex 0xF1';              dataStr = num2str(data);
+  elseif (type==242); name = 'Sysex 0xF2';              dataStr = num2str(data);
+  elseif (type==243); name = 'Sysex 0xF3';              dataStr = num2str(data);
+  elseif (type==244); name = 'Sysex 0xF4';              dataStr = num2str(data);
+  elseif (type==245); name = 'Sysex 0xF5';              dataStr = num2str(data);
+  elseif (type==246); name = 'Sysex 0xF6';              dataStr = num2str(data);
+  elseif (type==247); name = 'Sysex 0xF7';              dataStr = num2str(data);
+    
+    % realtime
+    % (i think have no data..?)
+  elseif (type==248); name = 'Real-time 0xF8 - Timing clock';              dataStr = num2str(data);
+  elseif (type==249); name = 'Real-time 0xF9';              dataStr = num2str(data);
+  elseif (type==250); name = 'Real-time 0xFA - Start a sequence';              dataStr = num2str(data);
+  elseif (type==251); name = 'Real-time 0xFB - Continue a sequence';              dataStr = num2str(data);
+  elseif (type==252); name = 'Real-time 0xFC - Stop a sequence';              dataStr = num2str(data);
+  elseif (type==253); name = 'Real-time 0xFD';              dataStr = num2str(data);
+  elseif (type==254); name = 'Real-time 0xFE';              dataStr = num2str(data);
+  elseif (type==255); name = 'Real-time 0xFF';              dataStr = num2str(data);
+  
+
+  else
+    name = ['UNKNOWN MIDI EVENT: ' num2str(type)]; dataStr = num2str(data);
+  end
+
+
+end
+
+function s=controllers(n)
+if (n==1); s='Mod Wheel';
+elseif (n==2); s='Breath Controllery';
+elseif (n==4); s='Foot Controller';
+elseif (n==5); s='Portamento Time';
+elseif (n==6); s='Data Entry MSB';
+elseif (n==7); s='Volume';
+elseif (n==8); s='Balance';
+elseif (n==10); s='Pan';
+elseif (n==11); s='Expression Controller';
+elseif (n==16); s='General Purpose 1';
+elseif (n==17); s='General Purpose 2';
+elseif (n==18); s='General Purpose 3';
+elseif (n==19); s='General Purpose 4';
+elseif (n==64); s='Sustain';
+elseif (n==65); s='Portamento';
+elseif (n==66); s='Sustenuto';
+elseif (n==67); s='Soft Pedal';
+elseif (n==69); s='Hold 2';
+elseif (n==80); s='General Purpose 5';
+elseif (n==81); s='Temp Change (General Purpose 6)';
+elseif (n==82); s='General Purpose 7';
+elseif (n==83); s='General Purpose 8';
+elseif (n==91); s='Ext Effects Depth';
+elseif (n==92); s='Tremelo Depthy';
+elseif (n==93); s='Chorus Depth';
+elseif (n==94); s='Detune Depth (Celeste Depth)';
+elseif (n==95); s='Phaser Depth';
+elseif (n==96); s='Data Increment (Data Entry +1)';
+elseif (n==97); s='Data Decrement (Data Entry -1)';
+elseif (n==98); s='Non-Registered Param LSB';
+elseif (n==99); s='Non-Registered Param MSB';
+elseif (n==100); s='Registered Param LSB';
+elseif (n==101); s='Registered Param MSB';
+else
+  s='UNKNOWN CONTROLLER';
+end
+
+%Channel mode message values
+%Reset All Controllers 	79 	121 	Val ??
+%Local Control 	7A 	122 	Val 0 = off, 7F (127) = on
+%All Notes Off 	7B 	123 	Val must be 0
+%Omni Mode Off 	7C 	124 	Val must be 0
+%Omni Mode On 	7D 	125 	Val must be 0
+%Mono Mode On 	7E 	126 	Val = # of channels, or 0 if # channels equals # voices in receiver
+%Poly Mode On 	7F 	127 	Val must be 0
+
+
+function [tempos,tempos_time]=getTempoChanges(midi)
+% [tempos,tempos_time]=getTempoChanges(midi)
+%
+% input: a midi struct from readmidi.m
+% output:
+%  tempos = tempo values indexed by tempos_time
+%    tempos_time is in units of ticks
+%
+% should tempo changes effect across tracks? across channels?
+%
+%---------------------------------------------------------------
+% Subversion Revision: 14 (2006-01-24)
+%
+% This software can be used freely for non-commerical use.
+% Visit http://www.kenschutte.com/software for more
+%   documentation, copyright info, and updates.
+%---------------------------------------------------------------
+
+
+tempos = [];
+tempos_time = [];
+%tempos_index = [];
+for i=1:length(midi.track)
+  cumtime=0;
+  for j=1:length(midi.track(i).messages)
+    cumtime = cumtime+midi.track(i).messages(j).deltatime;
+%    if (strcmp(midi.track(i).messages(j).name,'Set Tempo'))
+    if (midi.track(i).messages(j).midimeta==0 && midi.track(i).messages(j).type==81)
+        
+      tempos_time(end+1) = cumtime;
+      d = midi.track(i).messages(j).data;
+      tempos(end+1) =  d(1)*16^4 + d(2)*16^2 + d(3);
+    end
+  end
+end
+
+
+function midi = readmidi(filename, rawbytes)
+% midi = readmidi(filename, rawbytes)
+% midi = readmidi(filename)
+%
+% Read MIDI file and store in a Matlab structure
+% (use midiInfo.m to see structure detail)
+%
+% Inputs:
+%  filename - input MIDI file
+%  rawbytes - 0 or 1: Include raw bytes in structure
+%             This info is redundant, but can be
+%             useful for debugging. default=0
+%
+%---------------------------------------------------------------
+% Subversion Revision: 14 (2006-12-03)
+%
+% This software can be used freely for non-commerical use.
+% Visit http://www.kenschutte.com/software for more
+%   documentation, copyright info, and updates.
+%---------------------------------------------------------------
+
+
+
+if (nargin<2)
+  rawbytes=0;
+end
+
+fid = fopen(filename);
+%[A count] = fread(fid,'char');
+[A count] = fread(fid,'uint8');
+fclose(fid);
+
+midi.filename = filename;
+if (rawbytes) midi.rawbytes_all = A; end
+
+
+% realtime events: status: [F8, FF].  no data bytes
+%clock, undefined, start, continue, stop, undefined, active
+%sensing, systerm reset
+
+% file consists of "header chunk" and "track chunks"
+%   4B  'MThd' (header) or 'MTrk' (track)
+%   4B  32-bit unsigned int = number of bytes in chunk, not
+%       counting these first 8
+
+
+% HEADER CHUNK --------------------------------------------------------
+% 4B 'Mthd'
+% 4B length
+% 2B file format
+%    0=single track, 1=multitrack synchronous, 2=multitrack asynchronous
+%    Synchronous formats start all tracks at the same time, while asynchronous formats can start and end any track at any time during the score.
+% 2B track cout (must be 1 for format 0)
+% 2B num delta-time ticks per quarter note
+%
+
+if ~isequal(A(1:4)',[77 84 104 100])  % double('MThd')
+    error('File does not begin with header ID (MThd)');
+end
+
+header_len = decode_int(A(5:8));
+if (header_len == 6)
+else
+    error('Header length != 6 bytes.');
+end
+
+format = decode_int(A(9:10));
+if (format==0 || format==1 || format==2)
+     midi.format = format;
+else    
+    error('Format does not equal 0,1,or 2');
+end
+
+num_tracks = decode_int(A(11:12));
+if (format==0 && num_tracks~=1)
+    error('File is format 0, but num_tracks != 1');
+end
+
+time_unit = decode_int(A(13:14));
+if (bitand(time_unit,2^15)==0)
+  midi.ticks_per_quarter_note = time_unit;
+else
+  error('Header: SMPTE time format found - not currently supported');
+end
+
+if (rawbytes), midi.rawbytes_header = A(1:14); end
+
+% end header parse ----------------------------------------------------
+
+
+
+
+
+
+% BREAK INTO SEPARATE TRACKS ------------------------------------------
+% midi.track(1).data = [byte byte byte ...];
+% midi.track(2).date = ...
+% ...
+%
+% Track Chunks---------
+% 4B 'MTrk'
+% 4B length (after first 8B)
+%
+ctr = 15;
+for i=1:num_tracks
+  
+  if ~isequal(A(ctr:ctr+3)',[77 84 114 107])  % double('MTrk')
+    error(['Track ' num2str(i) ' does not begin with track ID=MTrk']);
+  end
+  ctr = ctr+4;
+  
+  track_len = decode_int(A(ctr:ctr+3));
+  ctr = ctr+4;
+  
+  % have track.rawbytes hold initial 8B also...
+  track_rawbytes{i} = A((ctr-8):(ctr+track_len-1));
+  
+  if (rawbytes)
+    midi.track(i).rawbytes_header = A(ctr-8:ctr-1);
+  end
+  
+  ctr = ctr+track_len;
+end
+% ----------------------------------------------------------------------
+
+
+
+
+
+
+% Events:
+%  - meta events: start with 'FF'
+%  - MIDI events: all others
+
+% MIDI events:
+%  optional command byte + 0,1,or 2 bytes of parameters
+%  "running mode": command byte omitted.
+%
+% all midi command bytes have MSB=1
+% all data for inside midi command have value <= 127 (ie MSB=0)
+% -> so can determine running mode
+% 
+% meta events' data may have any values (meta events have to set
+% len)
+%
+
+
+
+% 'Fn' MIDI commands:
+%  no chan. control the entire system
+%F8 Timing Clock
+%FA start a sequence
+%FB continue a sequence
+%FC stop a sequence
+
+% Meta events:
+%  1B 0xFF
+%  1B event type
+%  1B length of additional data
+%  ?? additional data
+%
+
+
+% "channel mode messages"
+% have same code as "control change": 0xBn
+%  but uses reserved controller numbers 120-127
+%
+
+
+%Midi events consist of an optional command byte 
+% followed by zero, one or two bytes of parameters.
+% In running mode, the command can be omitted, in 
+% which case the last MIDI command specified is 
+% assumed.  The first bit of a command byte is 1, 
+% while the first bit of a parameter is always 0. 
+%   In addition, the last 4 bits of a command 
+%   indicate the channel to which the event should 
+%   be sent; therefore, there are 6 possible 
+%   commands (really 7, but we will discuss the x'Fn' 
+%   commands later) that can be specified.  They are:
+
+
+% parse tracks -----------------------------------------
+for i=1:num_tracks
+  
+  track = track_rawbytes{i};
+
+  if (rawbytes); midi.track(i).rawbytes = track; end
+  
+  msgCtr = 1;
+  ctr=9;  % first 8B were MTrk and length
+  while (ctr < length(track_rawbytes{i}))
+
+    clear currMsg;
+    currMsg.used_running_mode = 0;
+    % note:
+    %  .used_running_mode is necessary only to 
+    %  be able to reconstruct a file _exactly_ from 
+    %  the 'midi' structure.  this is helpful for 
+    %  debugging since write(read(filename)) can be 
+    %  tested for exact replication...
+    %
+    
+    ctr_start_msg = ctr;
+    
+    [deltatime,ctr] = decode_var_length(track, ctr);
+    
+    % ?
+    %if (rawbytes)
+    %  currMsg.rawbytes_deltatime = track(ctr_start_msg:ctr-1);
+    %end
+    
+    % deltaime must be 1-4 bytes long.
+    % could check here...
+    
+    
+    % CHECK FOR META EVENTS ------------------------
+    % 'FF'
+    if track(ctr)==255
+
+      type = track(ctr+1);
+      
+      ctr = ctr+2;
+
+      % get variable length 'length' field
+      [len,ctr] = decode_var_length(track, ctr);
+
+      % note: some meta events have pre-determined lengths...
+      %  we could try verifiying they are correct here.
+
+      thedata = track(ctr:ctr+len-1);
+      chan = [];
+      
+      ctr = ctr + len;      
+
+      midimeta = 0;
+    
+    else 
+      midimeta = 1;
+      % MIDI EVENT ---------------------------
+      
+
+
+      
+      % check for running mode:
+      if (track(ctr)<128)
+
+	% make it re-do last command:
+	%ctr = ctr - 1;
+	%track(ctr) = last_byte;
+	currMsg.used_running_mode = 1;
+	
+	B = last_byte;
+	nB = track(ctr); % ?
+	
+      else
+      
+	B  = track(ctr);
+	nB = track(ctr+1);
+
+	ctr = ctr + 1;
+
+      end
+      
+      % nibbles:
+      %B  = track(ctr);
+      %nB = track(ctr+1);
+
+      
+      Hn = bitshift(B,-4);
+      Ln = bitand(B,15);
+
+      chan = [];
+      
+      msg_type = midi_msg_type(B,nB);
+
+      % DEBUG:
+      if (i==2)
+	  if (msgCtr==1)
+	    disp(msg_type);
+	  end
+      end
+      
+      
+      switch msg_type
+      
+       case 'channel_mode'
+	
+	% UNSURE: if all channel mode messages have 2 data byes (?)
+	type = bitshift(Hn,4) + (nB-120+1);
+	thedata = track(ctr:ctr+1);
+	chan = Ln;
+	
+	ctr = ctr + 2;
+	
+	% ---- channel voice messages:
+       case 'channel_voice'
+	
+	type = bitshift(Hn,4);
+	len = channel_voice_msg_len(type); % var length data:
+	thedata = track(ctr:ctr+len-1);
+	chan = Ln;
+
+	% DEBUG:
+	if (i==2)
+	  if (msgCtr==1)
+	    disp([999  Hn type])
+	  end
+	end
+	
+	ctr = ctr + len;
+	
+       case 'sysex'
+	
+	% UNSURE: do sysex events (F0-F7) have 
+	%  variable length 'length' field?
+	
+	[len,ctr] = decode_var_length(track, ctr);
+	
+	type = B;
+	thedata = track(ctr:ctr+len-1);
+	chan = [];
+	
+	ctr = ctr + len;
+	
+       case 'sys_realtime'
+	
+	% UNSURE: I think these are all just one byte
+	type = B;
+	thedata = [];
+	chan = [];
+	
+      end
+      
+      last_byte = Ln + bitshift(Hn,4);
+      
+    end % end midi event 'if'
+
+    
+    currMsg.deltatime = deltatime;
+    currMsg.midimeta = midimeta;
+    currMsg.type = type;
+    currMsg.data = thedata;
+    currMsg.chan = chan;
+    
+    if (rawbytes)
+      currMsg.rawbytes = track(ctr_start_msg:ctr-1);
+    end
+    
+    midi.track(i).messages(msgCtr) = currMsg;
+    msgCtr = msgCtr + 1;
+
+    
+  end % end loop over rawbytes
+end % end loop over tracks
+
+
+function val=decode_int(A)
+
+val = 0;
+for i=1:length(A)
+  val = val + bitshift(A(length(A)-i+1), 8*(i-1));
+end
+
+
+function len=channel_voice_msg_len(type)
+
+if     (type==128); len=2;
+elseif (type==144); len=2;
+elseif (type==160); len=2;
+elseif (type==176); len=2;
+elseif (type==192); len=1;
+elseif (type==208); len=1;
+elseif (type==224); len=2;
+else
+  disp(type); error('bad channel voice message type');
+end
+
+
+%
+% decode variable length field (often deltatime)
+%
+%  return value and new position of pointer into 'bytes'
+%
+function [val,ptr] = decode_var_length(bytes, ptr)
+
+keepgoing=1;
+binarystring = '';
+while (keepgoing)
+  % check MSB:
+  %  if MSB=1, then delta-time continues into next byte...
+  if(~bitand(bytes(ptr),128))
+    keepgoing=0;
+  end
+  % keep appending last 7 bits from each byte in the deltatime:
+  binbyte = ['00000000' dec2base(bytes(ptr),2)];
+  binarystring = [binarystring binbyte(end-6:end)];
+  ptr=ptr+1;
+end
+val = base2dec(binarystring,2);
+
+
+
+
+%
+% Read first 2 bytes of msg and 
+%  determine the type
+%  (most require only 1st byte)
+%
+% str is one of:
+%  'channel_mode'
+%  'channel_voice'
+%  'sysex'
+%  'sys_realtime'
+%
+function str=midi_msg_type(B,nB)
+
+Hn = bitshift(B,-4);
+Ln = bitand(B,7);
+
+% ---- channel mode messages:
+%if (Hn==11 && nB>=120 && nB<=127)
+if (Hn==11 && nB>=122 && nB<=127)
+  str = 'channel_mode';
+
+  % ---- channel voice messages:
+elseif (Hn>=8 && Hn<=14)
+  str = 'channel_voice';
+  
+  %  ---- sysex events:
+elseif (Hn==15 && Ln>=0 && Ln<=7)
+  str = 'sysex';
+
+  % system real-time messages
+elseif (Hn==15 && Ln>=8 && Ln<=15)
+  % UNSURE: how can you tell between 0xFF system real-time
+  %   message and 0xFF meta event?
+  %   (now, it will always be processed by meta)
+  str = 'sys_realtime';
+  
+else
+  % don't think it can get here...
+  error('bad midi message');
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sirtassa/refineScore.m	Tue Sep 03 12:53:16 2013 +0100
@@ -0,0 +1,35 @@
+function [binNb, width]  = refineScore(mag,binNb)
+
+toneFactor = 2^(1/12);
+
+firstBin = floor((binNb+1)/toneFactor)-2;
+lastBin = ceil((binNb+1)*toneFactor)+2;
+firstBin = max(firstBin,1);
+width =0;
+if (firstBin<lastBin-1)
+    %pitch refinment
+    [maxB,indMax ]= max(mag(firstBin:lastBin));
+    maxIdx = firstBin+indMax-1;
+    if (maxB <0.9)
+    binNb =0;
+    elseif (maxIdx ~= lastBin && maxIdx ~= firstBin)
+        a = log(mag(maxIdx-1));
+        b = log(mag(maxIdx));
+        c = log(mag(maxIdx+1));
+        binNb = (maxIdx + (a - c)/(2*(a-2*b+c)))-1;
+        minIdx = floor(binNb);
+        maxIdx = ceil(binNb);
+        while(minIdx>0&&mag(minIdx)>0.1*maxB)
+            minIdx = minIdx-1;
+        end
+        while(mag(maxIdx)>0.1*maxB)
+            maxIdx = maxIdx+1;
+        end
+        width = 2*min( maxIdx -binNb+1,binNb- minIdx+1);
+        width = max(width,3);
+    else
+%         plot(mag(1:maxIdx+10))
+%         close all;
+    end
+end
+