changeset 0:3dcbd77efc94

added files for OF project
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Fri, 21 Sep 2012 16:35:17 +0100
parents
children 5a94f002e5ef
files src/PeakProcessor.cpp src/PeakProcessor.h src/PreciseOnsetLocator.cpp src/PreciseOnsetLocator.h src/btrack_plus/.DS_Store src/btrack_plus/OnsetDetectionFunction.cpp src/btrack_plus/OnsetDetectionFunction.h src/btrack_plus/accFFT.cpp src/btrack_plus/accFFT.h src/main.cpp src/testApp.cpp src/testApp.h
diffstat 12 files changed, 2017 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/PeakProcessor.cpp	Fri Sep 21 16:35:17 2012 +0100
@@ -0,0 +1,134 @@
+/*
+ *  PeakProcessor.cpp
+ *  peakOnsetDetector
+ *
+ *  Created by Andrew on 07/09/2012.
+ *  Copyright 2012 QMUL. All rights reserved.
+ *
+ */
+
+#include "PeakProcessor.h"
+
+PeakProcessor::PeakProcessor(){
+	
+	recentDFsamples.assign(vectorSize, 0.0);
+	recentDFonsetFound.assign(vectorSize, false);
+	recentDFslopeValues.assign(vectorSize, 0.0);
+	
+	numberOfDetectionValuesToTest = 10;
+	currentFrame = 0;
+	cutoffForRepeatOnsetsFrames = 4;
+	detectionTriggerRatio = 0.5f;
+	detectionTriggerThreshold = 0.1;
+	bestSlopeMedian = 1;
+	thresholdRelativeToMedian = 1.1;
+	slopeFallenBelowMedian = true;
+	lastSlopeOnsetFrame = 0;
+}
+
+PeakProcessor::~PeakProcessor(){
+	
+	recentDFsamples.clear();
+	recentDFonsetFound.clear();
+	recentDFslopeValues.clear();
+}
+
+
+bool PeakProcessor::peakProcessing(const double& newDFval){
+	recentDFsamples.erase (recentDFsamples.begin(), recentDFsamples.begin()+1);//erase first val
+	recentDFsamples.push_back(newDFval);
+	
+	double slopeVal = getBestSlopeValue(newDFval);
+	
+	newOnsetFound = checkForSlopeOnset(slopeVal);
+
+	
+	printf("slope %f median %f det median %f\n", slopeVal, bestSlopeMedian, detectionTriggerThreshold);
+	if (newOnsetFound){
+		printf("BANG!\n");
+		
+	}
+	
+	recentDFslopeValues.erase (recentDFslopeValues.begin(), recentDFslopeValues.begin()+1);//erase first val
+	recentDFslopeValues.push_back(slopeVal);
+	
+	recentDFonsetFound.erase (recentDFonsetFound.begin(), recentDFonsetFound.begin()+1);//erase first val
+	recentDFonsetFound.push_back(newOnsetFound);
+	
+	
+	//printf("\n");
+	//	for (int i = 0;i < recentDFsamples.size();i++){
+	//		printf("rdf[%i] %f\n", i, recentDFsamples[i]);
+	//	}
+	//printf("SLOPE %f\n", slopeVal);
+	
+	return newOnsetFound;
+}
+
+
+double PeakProcessor::getBestSlopeValue(const float& dfvalue){
+	
+	//the idea is we want a high slope
+	double bestValue = 0;
+	
+	for (int i = 1;i < min(numberOfDetectionValuesToTest, (int)recentDFsamples.size() - 1);i++){
+		double angle = 0;
+		int otherIndex = recentDFsamples.size() - i + 1;
+		double testValue = 0;
+		
+		if (otherIndex > 0 && recentDFsamples[otherIndex] > 0 
+			&& recentDFsamples[otherIndex] < dfvalue
+			){
+			angle = atan((float)(i * dfvalue)/ (numberOfDetectionValuesToTest*(dfvalue-recentDFsamples[otherIndex])) );
+			testValue = (dfvalue - recentDFsamples[otherIndex]) * cos(angle);
+		}
+		
+		if (testValue > bestValue)
+			bestValue = testValue;
+	}
+	
+	return bestValue;
+	
+}
+
+
+
+bool PeakProcessor :: checkForSlopeOnset(const float& bestValue){
+	bool onsetDetected = false;
+	//check for onset relative to our processed slope function
+	//a mix between increase in value and the gradient of that increase
+	
+	currentFrame++;
+	
+	if (bestValue > bestSlopeMedian * thresholdRelativeToMedian && //better than recent average 
+		(currentFrame - lastSlopeOnsetFrame) > cutoffForRepeatOnsetsFrames //after cutoff time
+		&& slopeFallenBelowMedian // has had onset and fall away again
+		&& bestValue > detectionTriggerThreshold * detectionTriggerRatio //longer term ratio of winning onsets 
+		){
+		//	printf("frame diff between onsets %6.1f", (1000*framesToSeconds(currentFrame - lastMedianOnsetFrame)) );
+		onsetDetected = true;
+		lastSlopeOnsetFrame = currentFrame;
+		slopeFallenBelowMedian = false;
+		
+		updateDetectionTriggerThreshold(bestValue);
+	}
+	
+	
+	if (bestValue > bestSlopeMedian){
+		bestSlopeMedian += (bestValue - bestSlopeMedian)*0.04;//was 1.1
+	}
+	else{
+		bestSlopeMedian *= 0.99;
+		slopeFallenBelowMedian = true;;
+	}
+	
+	//bestSlopeMedian += 0.02* (bestValue - bestSlopeMedian);
+	
+	return onsetDetected;
+}
+
+void PeakProcessor :: updateDetectionTriggerThreshold(const float& val){
+	float detectionAdaptSpeed = 0.05;//moving average, roughly last twenty onsets
+	detectionTriggerThreshold *= 1- detectionAdaptSpeed;
+	detectionTriggerThreshold += (val * detectionAdaptSpeed);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/PeakProcessor.h	Fri Sep 21 16:35:17 2012 +0100
@@ -0,0 +1,39 @@
+/*
+ *  PeakProcessor.h
+ *  peakOnsetDetector
+ *
+ *  Created by Andrew on 07/09/2012.
+ *  Copyright 2012 QMUL. All rights reserved.
+ *
+ */
+
+#ifndef PEAK_PROCESSOR
+#define PEAK_PROCESSOR
+
+#include <vector.h>
+
+class PeakProcessor{
+	public:
+	
+	PeakProcessor();
+	~PeakProcessor();
+	//peak processing requires
+	static const int vectorSize = 512/6; 
+	vector<double> recentDFsamples; 
+	vector<bool> recentDFonsetFound;
+	vector<double> recentDFslopeValues;
+	
+	int numberOfDetectionValuesToTest;
+	bool peakProcessing(const double& newDFval);
+	double getBestSlopeValue(const float& dfvalue);
+	bool checkForSlopeOnset(const float& bestValue);
+	int currentFrame, lastSlopeOnsetFrame, cutoffForRepeatOnsetsFrames;
+	void updateDetectionTriggerThreshold(const float& val);
+	float detectionTriggerThreshold, detectionTriggerRatio;
+	float bestSlopeMedian, thresholdRelativeToMedian;
+	bool newOnsetFound, slopeFallenBelowMedian;
+	
+
+	
+};
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/PreciseOnsetLocator.cpp	Fri Sep 21 16:35:17 2012 +0100
@@ -0,0 +1,108 @@
+/*
+ *  PreciseOnsetLocator.cpp
+ *  peakOnsetDetector
+ *
+ *  Created by Andrew on 21/09/2012.
+ *  Copyright 2012 QMUL. All rights reserved.
+ *
+ */
+
+#include "PreciseOnsetLocator.h"
+
+PreciseOnsetLocator::PreciseOnsetLocator(){
+	setup(512);
+}
+
+PreciseOnsetLocator::~PreciseOnsetLocator(){
+	onsetSamples.clear();
+	recentBufferSamples.clear();
+}
+
+
+void PreciseOnsetLocator::setup(const int& size){
+	onsetSamples.clear();
+	recentBufferSamples.clear();
+	bufferSize = size;
+	onsetSamples.assign(bufferSize, 0.0);
+	recentBufferSamples.assign(bufferSize, 0.0);
+}
+
+void PreciseOnsetLocator::storeSamples(double* newSamples){
+	
+	for (int i = 0;i < bufferSize;i++)
+		recentBufferSamples[i] = newSamples[i];
+	
+}
+
+int PreciseOnsetLocator::findExactOnset(double* frame){
+	//store the samples - mainly for viewing actually
+	onsetSamples.clear();
+	for (int i = 0; i < bufferSize;i++) {
+		onsetSamples.push_back(frame[i]);
+	}
+	
+	double energySum = 0;
+	double lastEnergySum, hopsizeLastEnergySum;
+	double energyDifference;
+	int bestEnergyIndex = 0;
+	double bestEnergyDifference = 0;
+	int endIndex = bufferSize;
+	int hopSize;
+	
+	for (int resolution = bufferSize/2;resolution > 1;resolution/=2){
+		printf("resolution %i\n", resolution);
+		
+		bestEnergyDifference = 0;
+		//	printf("previous energy %f", lastEnergySum);
+		//initialise last energySum
+		hopSize = resolution/2;
+		
+		
+		lastEnergySum = getLastEnergySum(bestEnergyIndex, resolution);
+		hopsizeLastEnergySum = getLastEnergySum(bestEnergyIndex + hopSize, resolution);
+		
+		for (int startIndex = bestEnergyIndex;startIndex + resolution <= endIndex;startIndex += hopSize){
+			printf("index %i last energy %f hop energy %f ", startIndex, lastEnergySum, hopsizeLastEnergySum);
+			
+			//sum the energy for this new frame
+			energySum = 0;
+			for (int i = 0;i < resolution;i++){
+				energySum += onsetSamples[startIndex + i] * onsetSamples[startIndex + i];
+			}
+			
+			printf("energysum %f\n", energySum);
+			//check if new max difference
+			energyDifference = energySum - lastEnergySum;
+			if (energyDifference > bestEnergyDifference){
+				bestEnergyDifference = energyDifference;
+				bestEnergyIndex = startIndex;
+			}
+			
+			//store the values for checking in two loops time (because proceeding at resolution/2 each step)
+			//eg 0_to_128 compared to -128_to_0, 64_to_196 compared to -64_to_64, then 128_256 compared with 0_to_128, 
+			lastEnergySum = hopsizeLastEnergySum;// energySum;
+			hopsizeLastEnergySum = energySum;
+			
+		}
+		printf("winning index is %i\n", bestEnergyIndex);
+		endIndex = bestEnergyIndex + resolution;
+		
+	}
+	printf("TOTAL WINNER %i\n", bestEnergyIndex);
+	return bestEnergyIndex;
+	
+}
+
+double PreciseOnsetLocator::getLastEnergySum(const int& startIndex, const int& vectorSize){
+	double lastEnergySum = 0;
+	
+	for (int i = startIndex - vectorSize;i < startIndex;i++){
+		if (i > 0)
+			lastEnergySum += onsetSamples[i] * onsetSamples[i];
+		else {
+			lastEnergySum += recentBufferSamples[bufferSize + i] * recentBufferSamples[bufferSize + i];
+		}
+	}
+	return lastEnergySum;
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/PreciseOnsetLocator.h	Fri Sep 21 16:35:17 2012 +0100
@@ -0,0 +1,36 @@
+/*
+ *  PreciseOnsetLocator.h
+ *  peakOnsetDetector
+ *
+ *  Created by Andrew on 21/09/2012.
+ *  Copyright 2012 QMUL. All rights reserved.
+ *
+ */
+
+
+#ifndef PRECISE_ONSET_LOCATOR
+#define PRECISE_ONSET_LOCATOR
+
+#include <vector.h>
+
+class PreciseOnsetLocator{
+	public:
+	
+	PreciseOnsetLocator();
+	~PreciseOnsetLocator();
+	
+	int bufferSize;
+	
+	vector <double> onsetSamples;//holds the audio samples when onset is found
+	vector <double> recentBufferSamples;
+	
+	double getLastEnergySum(const int& startIndex, const int& vectorSize);
+	int findExactOnset(double* frame);
+
+	int exactOnsetIndex;
+	
+	void setup(const int& size);
+	void storeSamples(double* newSamples);
+		
+};
+#endif
\ No newline at end of file
Binary file src/btrack_plus/.DS_Store has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/btrack_plus/OnsetDetectionFunction.cpp	Fri Sep 21 16:35:17 2012 +0100
@@ -0,0 +1,826 @@
+/*
+ *  OnsetDetectionFunction.cpp
+ *  
+ *
+ *  Created by Adam Stark on 22/03/2011.
+ *  Copyright 2011 Queen Mary University of London. All rights reserved.
+ *
+ */
+
+#include <math.h>
+#include <iostream>
+#include "OnsetDetectionFunction.h"
+#include "accFFT.h"
+using namespace std;
+
+//-------------------------------------------------------------------------------
+// Constructor
+OnsetDetectionFunction :: OnsetDetectionFunction()
+{	
+	// indicate that we have not initialised yet
+	initialised = 0;		
+	
+	// set pi
+	pi = 3.14159265358979;	
+	
+	// initialise with hopsize = 512, framesize = 1024, complex spectral difference DF and hanning window
+	initialise(512,1024,6,1);	
+}
+
+
+//-------------------------------------------------------------------------------
+// Constructor (with arguments)
+OnsetDetectionFunction :: OnsetDetectionFunction(int arg_hsize,int arg_fsize,int arg_df_type,int arg_win_type)
+{	
+	// indicate that we have not initialised yet
+	initialised = 0;		
+	
+	// set pi
+	pi = 3.14159265358979;	
+	
+	// initialise with arguments to constructor
+	initialise(arg_hsize,arg_fsize,arg_df_type,arg_win_type);
+}
+
+
+//--------------------------------------------------------------------------------------
+// Destructor
+OnsetDetectionFunction :: ~OnsetDetectionFunction()
+{
+	// destroy fft plan
+    //fftw_destroy_plan(p);
+	//fftw_free(in); 
+	//fftw_free(out);
+        
+    fft->~accFFT();
+    delete [] in;
+    in = NULL;
+    delete [] out;
+    out = NULL;
+    
+
+	
+	// deallocate memory
+	delete [] frame;
+	frame = NULL;	
+	delete [] window;
+	window = NULL;									
+	delete [] wframe;
+	wframe = NULL;											
+	delete [] mag;
+	mag = NULL;
+	delete [] mag_old;
+	mag_old = NULL;
+	delete [] phase;
+	phase = NULL;
+	delete [] phase_old;
+	phase_old = NULL;	
+	delete [] phase_old_2;
+	phase_old_2 = NULL;
+}
+
+//-------------------------------------------------------------------------------
+// Initialisation
+void OnsetDetectionFunction :: initialise(int arg_hsize,int arg_fsize,int arg_df_type,int arg_win_type)
+{
+	if (initialised == 1) // if we have already initialised some buffers and an FFT plan
+	{
+		//////////////////////////////////
+		// TIDY UP FIRST - If initialise is called after the class has been initialised
+		// then we want to free up memory and cancel existing FFT plans
+	
+		// destroy fft plan
+		//fftw_destroy_plan(p);
+		//fftw_free(in); 
+		//fftw_free(out);
+        
+        fft->~accFFT();
+        delete [] in;
+        in = NULL;
+        delete [] out;
+        out = NULL;
+	
+	
+		// deallocate memory
+		delete [] frame;
+		frame = NULL;	
+		delete [] window;
+		window = NULL;									
+		delete [] wframe;
+		wframe = NULL;											
+		delete [] mag;
+		mag = NULL;
+		delete [] mag_old;
+		mag_old = NULL;
+		delete [] phase;
+		phase = NULL;
+		delete [] phase_old;
+		phase_old = NULL;	
+		delete [] phase_old_2;
+		phase_old_2 = NULL;
+	
+		////// END TIDY UP ///////////////
+		//////////////////////////////////
+	}
+	
+	hopsize = arg_hsize; // set hopsize
+	framesize = arg_fsize; // set framesize
+	
+	df_type = arg_df_type; // set detection function type
+		
+	// initialise buffers
+	frame = new double[framesize];											
+	window = new double[framesize];	
+	wframe = new double[framesize];		
+	
+	mag = new double[framesize];											
+	mag_old = new double[framesize];
+	
+	phase = new double[framesize];
+	phase_old = new double[framesize];
+	phase_old_2 = new double[framesize];
+	
+	
+	// set the window to the specified type
+	switch (arg_win_type){
+		case 0:
+			set_win_rectangular();		// Rectangular window
+			break;	
+		case 1:	
+			set_win_hanning();			// Hanning Window
+			break;
+		case 2:
+			set_win_hamming();			// Hamming Window
+			break;
+		case 3:
+			set_win_blackman();			// Blackman Window
+			break;
+		case 4:
+			set_win_tukey();			// Tukey Window
+			break;
+		default:
+			set_win_hanning();			// DEFAULT: Hanning Window
+	}
+	
+	
+	
+	
+	// initialise previous magnitude spectrum to zero
+	for (int i = 0;i < framesize;i++)
+	{
+		mag_old[i] = 0.0;
+		phase_old[i] = 0.0;
+		phase_old_2[i] = 0.0;
+		frame[i] = 0.0;
+	}
+	
+	energy_sum_old = 0.0;	// initialise previous energy sum value to zero
+	
+	/*  Init fft */
+	//in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * framesize);		// complex array to hold fft data
+	//out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * framesize);	// complex array to hold fft data
+	//p = fftw_plan_dft_1d(framesize, in, out, FFTW_FORWARD, FFTW_ESTIMATE);	// FFT plan initialisation
+
+    in = new double[framesize];
+    out = new fft_complex[framesize];
+
+    //out = new double[2][framesize];
+    fft = new accFFT(framesize,1);
+	
+	initialised = 1;
+}
+
+//--------------------------------------------------------------------------------------
+// set the detection function type to that specified by the argument
+void OnsetDetectionFunction :: set_df_type(int arg_df_type)
+{
+	df_type = arg_df_type; // set detection function type
+}
+
+
+//--------------------------------------------------------------------------------------
+// calculates a single detection function sample from a single audio frame.
+double OnsetDetectionFunction :: getDFsample(double inputbuffer[])
+{	
+	double df_sample;
+		
+	// shift audio samples back in frame by hop size
+	for (int i = 0; i < (framesize-hopsize);i++)
+	{
+		frame[i] = frame[i+hopsize];
+	}
+	
+	// add new samples to frame from input buffer
+	int j = 0;
+	for (int i = (framesize-hopsize);i < framesize;i++)
+	{
+		frame[i] = inputbuffer[j];
+		j++;
+	}
+		
+	switch (df_type){
+		case 0:
+			df_sample = energy_envelope();	// calculate energy envelope detection function sample
+			break;	
+		case 1:
+			df_sample = energy_difference();	// calculate half-wave rectified energy difference detection function sample
+			break;
+		case 2:
+			df_sample = spectral_difference();	// calculate spectral difference detection function sample
+			break;
+		case 3:
+			df_sample = spectral_difference_hwr(); // calculate spectral difference detection function sample (half wave rectified)
+			break;
+		case 4:
+			df_sample = phase_deviation();		// calculate phase deviation detection function sample (half wave rectified)
+			break;
+		case 5:
+			df_sample = complex_spectral_difference(); // calcualte complex spectral difference detection function sample
+			break;
+		case 6:
+			df_sample = complex_spectral_difference_hwr();  // calcualte complex spectral difference detection function sample (half-wave rectified)
+			break;
+		case 7:
+			df_sample = high_frequency_content(); // calculate high frequency content detection function sample
+			break;
+		case 8:
+			df_sample = high_frequency_spectral_difference(); // calculate high frequency spectral difference detection function sample
+			break;
+		case 9:
+			df_sample = high_frequency_spectral_difference_hwr(); // calculate high frequency spectral difference detection function (half-wave rectified)
+			break;
+		default:
+			df_sample = 1.0;
+	}
+		
+	return df_sample;
+}
+
+
+//--------------------------------------------------------------------------------------
+// performs the fft, storing the complex result in 'out'
+void OnsetDetectionFunction :: perform_FFT()
+{
+	int fsize2 = (framesize/2);
+	
+    
+	// window frame
+	//for (int i = 0;i < fsize2;i++)
+    for (int i = 0;i < framesize;i++)
+	{
+        in[i] = frame[i]*window[i];
+        
+        //in[i] = frame[i+fsize2]*window[i+fsize2];
+        //in[i+fsize2] = frame[i] * window[i];
+        
+        /*
+		in[i][0] = frame[i+fsize2] * window[i+fsize2];
+		in[i][1] = 0.0;
+		in[i+fsize2][0] = frame[i] * window[i];
+		in[i+fsize2][1] = 0.0;
+         */
+	}
+	
+	// perform the fft
+	//fftw_execute(p);
+    
+    // FIX  
+    fft->forward_FFT_d(in,out);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////// Methods for Detection Functions /////////////////////////////////
+
+//--------------------------------------------------------------------------------------
+// calculates an energy envelope detection function sample
+double OnsetDetectionFunction :: energy_envelope()
+{
+	double sum;
+	
+	sum = 0;	// initialise sum
+	
+	// sum the squares of the samples
+	for (int i = 0;i < framesize;i++)
+	{
+		sum = sum + (frame[i]*frame[i]);
+	}
+	
+	return sum;		// return sum
+}
+
+//--------------------------------------------------------------------------------------
+// calculates a half-wave rectified energy difference detection function sample
+double OnsetDetectionFunction :: energy_difference()
+{
+	double sum;
+	double sample;
+	
+	sum = 0;	// initialise sum
+	
+	// sum the squares of the samples
+	for (int i = 0;i < framesize;i++)
+	{
+		sum = sum + (frame[i]*frame[i]);
+	}
+	
+	sample = sum - energy_sum_old;	// sample is first order difference in energy
+	
+	energy_sum_old = sum;	// store energy value for next calculation
+	
+	if (sample > 0)
+	{
+		return sample;		// return difference
+	}
+	else
+	{
+		return 0;
+	}
+}
+
+//--------------------------------------------------------------------------------------
+// calculates a spectral difference detection function sample
+double OnsetDetectionFunction :: spectral_difference()
+{
+	double diff;
+	double sum;
+	
+	// perform the FFT
+	perform_FFT();
+	
+	// compute first (N/2)+1 mag values
+	for (int i = 0;i < (framesize/2)+1;i++)
+	{
+		mag[i] = sqrt(pow(out[i][0],2) + pow(out[i][1],2));
+	}
+	// mag spec symmetric above (N/2)+1 so copy previous values
+	for (int i = (framesize/2)+1;i < framesize;i++)
+	{
+		mag[i] = mag[framesize-i];		
+	}
+	
+	sum = 0;	// initialise sum to zero
+
+	for (int i = 0;i < framesize;i++)
+	{
+		// calculate difference
+		diff = mag[i] - mag_old[i];
+		
+		// ensure all difference values are positive
+		if (diff < 0)
+		{
+			diff = diff*-1;
+		}
+		
+		// add difference to sum
+		sum = sum+diff;
+		
+		// store magnitude spectrum bin for next detection function sample calculation
+		mag_old[i] = mag[i];
+	}
+	
+	return sum;		
+}
+
+//--------------------------------------------------------------------------------------
+// calculates a spectral difference detection function sample
+double OnsetDetectionFunction :: spectral_difference_hwr()
+{
+	double diff;
+	double sum;
+	
+	// perform the FFT
+	perform_FFT();
+	
+	// compute first (N/2)+1 mag values
+	for (int i = 0;i < (framesize/2)+1;i++)
+	{
+		mag[i] = sqrt(pow(out[i][0],2) + pow(out[i][1],2));
+	}
+	// mag spec symmetric above (N/2)+1 so copy previous values
+	for (int i = (framesize/2)+1;i < framesize;i++)
+	{
+		mag[i] = mag[framesize-i];		
+	}
+	
+	sum = 0;	// initialise sum to zero
+	
+	for (int i = 0;i < framesize;i++)
+	{
+		// calculate difference
+		diff = mag[i] - mag_old[i];
+		
+		// only add up positive differences
+		if (diff > 0)
+		{
+			// add difference to sum
+			sum = sum+diff;
+		}
+		
+		
+		
+		// store magnitude spectrum bin for next detection function sample calculation
+		mag_old[i] = mag[i];
+	}
+	
+	return sum;		
+}
+
+
+//--------------------------------------------------------------------------------------
+// calculates a phase deviation detection function sample
+double OnsetDetectionFunction :: phase_deviation()
+{
+	double dev,pdev;
+	double sum;
+	
+	// perform the FFT
+	perform_FFT();
+	
+	sum = 0; // initialise sum to zero
+	
+	// compute phase values from fft output and sum deviations
+	for (int i = 0;i < framesize;i++)
+	{
+		// calculate phase value
+		phase[i] = atan2(out[i][1],out[i][0]);
+		
+		// calculate magnitude value
+		mag[i] = sqrt(pow(out[i][0],2) + pow(out[i][1],2));
+		
+		
+		// if bin is not just a low energy bin then examine phase deviation
+		if (mag[i] > 0.1)
+		{
+			dev = phase[i] - (2*phase_old[i]) + phase_old_2[i];	// phase deviation
+			pdev = princarg(dev);	// wrap into [-pi,pi] range
+		
+			// make all values positive
+			if (pdev < 0)	
+			{
+				pdev = pdev*-1;
+			}
+						
+			// add to sum
+			sum = sum + pdev;
+		}
+				
+		// store values for next calculation
+		phase_old_2[i] = phase_old[i];
+		phase_old[i] = phase[i];
+	}
+	
+	return sum;		
+}
+
+//--------------------------------------------------------------------------------------
+// calculates a complex spectral difference detection function sample
+double OnsetDetectionFunction :: complex_spectral_difference()
+{
+	double dev,pdev;
+	double sum;
+	double mag_diff,phase_diff;
+	double value;
+	
+	// perform the FFT
+	perform_FFT();
+	
+	sum = 0; // initialise sum to zero
+	
+	// compute phase values from fft output and sum deviations
+	for (int i = 0;i < framesize;i++)
+	{
+		// calculate phase value
+		phase[i] = atan2(out[i][1],out[i][0]);
+		
+		// calculate magnitude value
+		mag[i] = sqrt(pow(out[i][0],2) + pow(out[i][1],2));
+		
+		
+		// phase deviation
+		dev = phase[i] - (2*phase_old[i]) + phase_old_2[i];	
+		
+		// wrap into [-pi,pi] range
+		pdev = princarg(dev);	
+		
+		
+		// calculate magnitude difference (real part of Euclidean distance between complex frames)
+		mag_diff = mag[i] - mag_old[i];
+		
+		// calculate phase difference (imaginary part of Euclidean distance between complex frames)
+		phase_diff = -mag[i]*sin(pdev);
+		
+
+		
+		// square real and imaginary parts, sum and take square root
+		value = sqrt(pow(mag_diff,2) + pow(phase_diff,2));
+	
+			
+		// add to sum
+		sum = sum + value;
+		
+		
+		// store values for next calculation
+		phase_old_2[i] = phase_old[i];
+		phase_old[i] = phase[i];
+		mag_old[i] = mag[i];
+	}
+	
+	return sum;		
+}
+
+//--------------------------------------------------------------------------------------
+// calculates a complex spectral difference detection function sample (half-wave rectified)
+double OnsetDetectionFunction :: complex_spectral_difference_hwr()
+{
+	double dev,pdev;
+	double sum;
+	double mag_diff,phase_diff;
+	double value;
+	
+	// perform the FFT
+	perform_FFT();
+	
+	sum = 0; // initialise sum to zero
+	
+	// compute phase values from fft output and sum deviations
+	for (int i = 0;i < framesize;i++)
+	{
+		// calculate phase value
+		phase[i] = atan2(out[i][1],out[i][0]);
+		
+		// calculate magnitude value
+		mag[i] = sqrt(pow(out[i][0],2) + pow(out[i][1],2));
+		
+		
+		// phase deviation
+		dev = phase[i] - (2*phase_old[i]) + phase_old_2[i];	
+		
+		// wrap into [-pi,pi] range
+		pdev = princarg(dev);	
+		
+		
+		// calculate magnitude difference (real part of Euclidean distance between complex frames)
+		mag_diff = mag[i] - mag_old[i];
+		
+		// if we have a positive change in magnitude, then include in sum, otherwise ignore (half-wave rectification)
+		if (mag_diff > 0)
+		{
+			// calculate phase difference (imaginary part of Euclidean distance between complex frames)
+			phase_diff = -mag[i]*sin(pdev);
+
+			// square real and imaginary parts, sum and take square root
+			value = sqrt(pow(mag_diff,2) + pow(phase_diff,2));
+		
+			// add to sum
+			sum = sum + value;
+		}
+		
+		// store values for next calculation
+		phase_old_2[i] = phase_old[i];
+		phase_old[i] = phase[i];
+		mag_old[i] = mag[i];
+	}
+	
+	return sum;		
+}
+
+
+//--------------------------------------------------------------------------------------
+// calculates a high frequency content detection function sample
+double OnsetDetectionFunction :: high_frequency_content()
+{
+	double sum;
+	double mag_diff;
+	
+	// perform the FFT
+	perform_FFT();
+	
+	sum = 0; // initialise sum to zero
+	
+	// compute phase values from fft output and sum deviations
+	for (int i = 0;i < framesize;i++)
+	{		
+		// calculate magnitude value
+		mag[i] = sqrt(pow(out[i][0],2) + pow(out[i][1],2));
+		
+		
+		sum = sum + (mag[i]*((double) (i+1)));
+		
+		// store values for next calculation
+		mag_old[i] = mag[i];
+	}
+	
+	return sum;		
+}
+
+//--------------------------------------------------------------------------------------
+// calculates a high frequency spectral difference detection function sample
+double OnsetDetectionFunction :: high_frequency_spectral_difference()
+{
+	double sum;
+	double mag_diff;
+	
+	// perform the FFT
+	perform_FFT();
+	
+	sum = 0; // initialise sum to zero
+	
+	// compute phase values from fft output and sum deviations
+	for (int i = 0;i < framesize;i++)
+	{		
+		// calculate magnitude value
+		mag[i] = sqrt(pow(out[i][0],2) + pow(out[i][1],2));
+		
+		// calculate difference
+		mag_diff = mag[i] - mag_old[i];
+		
+		if (mag_diff < 0)
+		{
+			mag_diff = -mag_diff;
+		}
+		
+		sum = sum + (mag_diff*((double) (i+1)));
+		
+		// store values for next calculation
+		mag_old[i] = mag[i];
+	}
+	
+	return sum;		
+}
+
+//--------------------------------------------------------------------------------------
+// calculates a high frequency spectral difference detection function sample (half-wave rectified)
+double OnsetDetectionFunction :: high_frequency_spectral_difference_hwr()
+{
+	double sum;
+	double mag_diff;
+	
+	// perform the FFT
+	perform_FFT();
+	
+	sum = 0; // initialise sum to zero
+	
+	// compute phase values from fft output and sum deviations
+	for (int i = 0;i < framesize;i++)
+	{		
+		// calculate magnitude value
+		mag[i] = sqrt(pow(out[i][0],2) + pow(out[i][1],2));
+		
+		// calculate difference
+		mag_diff = mag[i] - mag_old[i];
+		
+		if (mag_diff > 0)
+		{
+			sum = sum + (mag_diff*((double) (i+1)));
+		}
+
+		// store values for next calculation
+		mag_old[i] = mag[i];
+	}
+	
+	return sum;		
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////// Methods to Calculate Windows ////////////////////////////////////
+
+//--------------------------------------------------------------------------------------
+// HANNING: set the window in the buffer 'window' to a Hanning window
+void OnsetDetectionFunction :: set_win_hanning()
+{
+	double N;		// variable to store framesize minus 1
+	
+	N = (double) (framesize-1);	// framesize minus 1
+	
+	// Hanning window calculation
+	for (int n = 0;n < framesize;n++)
+	{
+		window[n] = 0.5*(1-cos(2*pi*(n/N)));
+	}
+}
+
+//--------------------------------------------------------------------------------------
+// HAMMING: set the window in the buffer 'window' to a Hanning window
+void OnsetDetectionFunction :: set_win_hamming()
+{
+	double N;		// variable to store framesize minus 1
+	double n_val;	// double version of index 'n'
+	
+	N = (double) (framesize-1);	// framesize minus 1
+	n_val = 0;
+	
+	// Hamming window calculation
+	for (int n = 0;n < framesize;n++)
+	{
+		window[n] = 0.54 - (0.46*cos(2*pi*(n_val/N)));
+		n_val = n_val+1;
+	}
+}
+
+//--------------------------------------------------------------------------------------
+// BLACKMAN: set the window in the buffer 'window' to a Blackman window
+void OnsetDetectionFunction :: set_win_blackman()
+{
+	double N;		// variable to store framesize minus 1
+	double n_val;	// double version of index 'n'
+	
+	N = (double) (framesize-1);	// framesize minus 1
+	n_val = 0;
+	
+	// Blackman window calculation
+	for (int n = 0;n < framesize;n++)
+	{
+		window[n] = 0.42 - (0.5*cos(2*pi*(n_val/N))) + (0.08*cos(4*pi*(n_val/N)));
+		n_val = n_val+1;
+	}
+}
+
+//--------------------------------------------------------------------------------------
+// TUKEY: set the window in the buffer 'window' to a Tukey window
+void OnsetDetectionFunction :: set_win_tukey()
+{
+	double N;		// variable to store framesize minus 1
+	double n_val;	// double version of index 'n'
+	double alpha;	// alpha [default value = 0.5];
+	
+	int lim1,lim2;
+	
+	alpha = 0.5;
+	
+	N = (double) (framesize-1);	// framesize minus 1
+		
+	// Tukey window calculation
+	
+	n_val = (double) (-1*((framesize/2)))+1;
+
+	for (int n = 0;n < framesize;n++)	// left taper
+	{
+		if ((n_val >= 0) && (n_val <= (alpha*(N/2))))
+		{
+			window[n] = 1.0;
+		}
+		else if ((n_val <= 0) && (n_val >= (-1*alpha*(N/2))))
+		{
+			window[n] = 1.0;
+		}
+		else
+		{
+			window[n] = 0.5*(1+cos(pi*(((2*n_val)/(alpha*N))-1)));
+		}
+
+		n_val = n_val+1;			 
+	}
+
+}
+
+//--------------------------------------------------------------------------------------
+// RECTANGULAR: set the window in the buffer 'window' to a Rectangular window
+void OnsetDetectionFunction :: set_win_rectangular()
+{
+	// Rectangular window calculation
+	for (int n = 0;n < framesize;n++)
+	{
+		window[n] = 1.0;
+	}
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////// Other Handy Methods //////////////////////////////////////////
+
+//--------------------------------------------------------------------------------------
+// set phase values to the range [-pi,pi]
+double OnsetDetectionFunction :: princarg(double phaseval)
+{	
+	// if phase value is less than or equal to -pi then add 2*pi
+	while (phaseval <= (-pi)) 
+	{
+		phaseval = phaseval + (2*pi);
+	}
+	
+	// if phase value is larger than pi, then subtract 2*pi
+	while (phaseval > pi)
+	{
+		phaseval = phaseval - (2*pi);
+	}
+			
+	return phaseval;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/btrack_plus/OnsetDetectionFunction.h	Fri Sep 21 16:35:17 2012 +0100
@@ -0,0 +1,88 @@
+/*
+ *  OnsetDetectionFunction.h
+ *  
+ *
+ *  Created by Adam Stark on 22/03/2011.
+ *  Copyright 2011 Queen Mary University of London. All rights reserved.
+ *
+ */
+
+#ifndef __RTONSETDF_H
+#define __RTONSETDF_H
+
+//#include "fftw3.h"
+#include "accFFT.h"
+
+typedef double fft_complex[2];
+
+class OnsetDetectionFunction
+{
+public:
+	OnsetDetectionFunction();																// Constructor
+	OnsetDetectionFunction(int arg_hsize,int arg_fsize,int arg_df_type,int arg_win_type);	// Constructor (with arguments)
+	~OnsetDetectionFunction();																// Destructor
+	void initialise(int arg_hsize,int arg_fsize,int arg_df_type,int arg_win_type);			// Initialisation Function
+	
+	double getDFsample(double inputbuffer[]);												// process input buffer and calculate detection function sample
+	void set_df_type(int arg_df_type);														// set the detection function type
+	
+private:
+	
+	void perform_FFT();																		// perform the FFT on the data in 'frame'
+
+	double energy_envelope();																// calculate energy envelope detection function sample
+	double energy_difference();																// calculate energy difference detection function sample
+	double spectral_difference();															// calculate spectral difference detection function sample
+	double spectral_difference_hwr();														// calculate spectral difference (half wave rectified) detection function sample
+	double phase_deviation();																// calculate phase deviation detection function sample
+	double complex_spectral_difference();													// calculate complex spectral difference detection function sample
+	double complex_spectral_difference_hwr();												// calculate complex spectral difference detection function sample (half-wave rectified)
+	double high_frequency_content();														// calculate high frequency content detection function sample
+	double high_frequency_spectral_difference();											// calculate high frequency spectral difference detection function sample
+	double high_frequency_spectral_difference_hwr();										// calculate high frequency spectral difference detection function sample (half-wave rectified)
+
+	void set_win_rectangular();																// calculate a Rectangular window	
+	void set_win_hanning();																	// calculate a Hanning window
+	void set_win_hamming();																	// calculate a Hamming window
+	void set_win_blackman();																// calculate a Blackman window
+	void set_win_tukey();																	// calculate a Tukey window
+
+	
+	double princarg(double phaseval);														// set phase values between [-pi, pi]
+	
+	
+	double pi;																				// pi, the constant
+	
+	int framesize;																			// audio framesize
+	int hopsize;																			// audio hopsize	
+	int df_type;																			// type of detection function
+	
+    accFFT *fft;
+    fft_complex *out;
+    double *in;
+    
+	//fftw_plan p;																			// create fft plan
+	//fftw_complex *in;																		// to hold complex fft values for input
+	//fftw_complex *out;																		// to hold complex fft values for output
+    
+	
+	int initialised;																		// flag indicating whether buffers and FFT plans have been initialised
+	
+
+	double *frame;																			// audio frame
+	double *window;																			// window
+	double *wframe;																			// windowed frame
+	
+	double energy_sum_old;																	// to hold the previous energy sum value
+	
+	double *mag;																			// magnitude spectrum
+	double *mag_old;																		// previous magnitude spectrum
+	
+	double *phase;																			// FFT phase values
+	double *phase_old;																		// previous phase values
+	double *phase_old_2;																	// second order previous phase values
+
+};
+
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/btrack_plus/accFFT.cpp	Fri Sep 21 16:35:17 2012 +0100
@@ -0,0 +1,140 @@
+//
+//  accFFT.cpp
+//  AccelerateFFTtool
+//
+//  Created by Adam Stark on 17/07/2012.
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+
+#include "accFFT.h"
+
+
+accFFT :: accFFT(int fft_size,int type)
+{
+    fft_type = type;
+    
+    fftSize = fft_size;           
+    fftSizeOver2 = fftSize/2;
+    log2n = log2f(fftSize);  
+    log2nOver2 = log2n/2;
+    
+    if (fft_type == 0)
+    {
+        split.realp = (float *) malloc(fftSize * sizeof(float));
+        split.imagp = (float *) malloc(fftSize * sizeof(float));
+        
+        // allocate the fft object once
+        fftSetup = vDSP_create_fftsetup(log2n, FFT_RADIX2);
+        if (fftSetup == NULL) {
+            //printf("FFT Setup failed\n");
+        }
+    }
+    else if (fft_type == 1) 
+    {
+        d_split.realp = (double *) malloc(fftSize * sizeof(double));
+        d_split.imagp = (double *) malloc(fftSize * sizeof(double));
+        
+        // allocate the fft object once
+        fftSetupD = vDSP_create_fftsetupD(log2n, FFT_RADIX2);
+        if (fftSetupD == NULL) {
+            //printf("FFT Setup failed\n");
+        }
+    }
+        
+    
+    
+}
+
+accFFT :: ~accFFT()
+{
+    if (fft_type == 0)
+    {
+        free(split.realp);
+        free(split.imagp);
+        vDSP_destroy_fftsetup(fftSetup);
+    }
+    else if (fft_type == 1)
+    {
+        free(d_split.realp);
+        free(d_split.imagp);
+        vDSP_destroy_fftsetupD(fftSetupD);
+    }
+    
+    
+}
+
+void accFFT :: forward_FFT_f(float *buffer,float *real,float *imag)
+{        
+    //convert to split complex format with evens in real and odds in imag
+    vDSP_ctoz((COMPLEX *) buffer, 2, &split, 1, fftSizeOver2);
+    
+    //calc fft
+    vDSP_fft_zrip(fftSetup, &split, 1, log2n, FFT_FORWARD);
+    
+    // set Nyquist component to imaginary of 0 component
+    split.realp[fftSizeOver2] = split.imagp[0];
+    split.imagp[fftSizeOver2] = 0.0;
+    
+    // set 0 component to zero
+    split.imagp[0] = 0.0;
+    
+    // multiply by 0.5 to get correct output (to do with Apple's FFT implementation)
+    for (i = 0; i <= fftSizeOver2; i++)
+    {
+        split.realp[i] *= 0.5;
+        split.imagp[i] *= 0.5;
+    }
+    
+    // set values above N/2+1 which are complex conjugate mirror image of those below
+    for (i = fftSizeOver2 - 1;i > 0;--i)
+    {
+        split.realp[2*fftSizeOver2 - i] = split.realp[i];
+        split.imagp[2*fftSizeOver2 - i] = -1*split.imagp[i];
+        
+        //cout << split_data.realp[2*fftSizeOver2 - i] << "   " << split_data.imagp[2*fftSizeOver2 - i] << "i" << endl;
+    }
+    
+    for (i = 0;i < fftSize;i++)
+    {
+        real[i] = split.realp[i];
+        imag[i] = split.imagp[i];
+    }
+}
+
+
+
+void accFFT :: forward_FFT_d(double *buffer,fft_complex *out)
+{        
+    //convert to split complex format with evens in real and odds in imag
+    vDSP_ctozD((DOUBLE_COMPLEX *) buffer, 2, &d_split, 1, fftSizeOver2);
+    
+    //calc fft
+    vDSP_fft_zripD(fftSetupD, &d_split, 1, log2n, FFT_FORWARD);
+    
+    // set Nyquist component to imaginary of 0 component
+    d_split.realp[fftSizeOver2] = d_split.imagp[0];
+    d_split.imagp[fftSizeOver2] = 0.0;
+    
+    // set 0 component to zero
+    d_split.imagp[0] = 0.0;
+    
+    // multiply by 0.5 to get correct output (to do with Apple's FFT implementation)
+    for (i = 0; i <= fftSizeOver2; i++)
+    {
+        d_split.realp[i] *= 0.5;
+        d_split.imagp[i] *= 0.5;
+    }
+    
+    // set values above N/2+1 which are complex conjugate mirror image of those below
+    for (i = fftSizeOver2 - 1;i > 0;--i)
+    {
+        d_split.realp[2*fftSizeOver2 - i] = d_split.realp[i];
+        d_split.imagp[2*fftSizeOver2 - i] = -1*d_split.imagp[i];
+    }
+    
+    for (i = 0;i < fftSize;i++)
+    {
+        out[i][0] = d_split.realp[i]; 
+        out[i][1] = d_split.imagp[i];
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/btrack_plus/accFFT.h	Fri Sep 21 16:35:17 2012 +0100
@@ -0,0 +1,41 @@
+//
+//  accFFT.h
+//  AccelerateFFTtool
+//
+//  Created by Adam Stark on 17/07/2012.
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+
+#ifndef AccelerateFFTtool_accFFT_h
+#define AccelerateFFTtool_accFFT_h
+
+#include <Accelerate/Accelerate.h>
+
+typedef double fft_complex[2];
+
+class accFFT {
+public:
+    accFFT(int fft_size,int type);       // constructor
+    ~accFFT();                  // destructor
+    void forward_FFT_f(float *buffer,float *real,float *imag); // forward fft (float)
+    void forward_FFT_d(double *buffer,fft_complex *out); // forward fft (double)
+    
+
+    
+private:
+    size_t              fftSize;
+    size_t              fftSizeOver2;
+    size_t              log2n;
+    size_t              log2nOver2;
+    size_t               i;                  
+    
+    FFTSetup            fftSetup;
+    FFTSetupD           fftSetupD;
+    COMPLEX_SPLIT       split;
+    DOUBLE_COMPLEX_SPLIT d_split;
+    
+    int                  fft_type;
+    
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main.cpp	Fri Sep 21 16:35:17 2012 +0100
@@ -0,0 +1,16 @@
+#include "ofMain.h"
+#include "testApp.h"
+#include "ofAppGlutWindow.h"
+
+//========================================================================
+int main( ){
+
+    ofAppGlutWindow window;
+	ofSetupOpenGL(&window, 1024,768, OF_WINDOW);			// <-------- setup the GL context
+
+	// this kicks off the running of my app
+	// can be OF_WINDOW or OF_FULLSCREEN
+	// pass in width and height too:
+	ofRunApp( new testApp());
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/testApp.cpp	Fri Sep 21 16:35:17 2012 +0100
@@ -0,0 +1,505 @@
+#include "testApp.h"
+
+
+//--------------------------------------------------------------
+void testApp::setup(){	 
+	
+	ofSetVerticalSync(true);
+	ofSetCircleResolution(80);
+	ofBackground(54, 54, 54);	
+	
+	// 0 output channels, 
+	// 2 input channels
+	// 44100 samples per second
+	// 256 samples per buffer
+	// 4 num buffers (latency)
+	
+	soundStream.listDevices();
+	soundStream.setDeviceID(0);//this now uses the audio input rather than mic input for mac 
+	//outputStream.setDeviceID(1);
+	
+	//if you want to set a different device id 
+	//soundStream.setDeviceID(0); //bear in mind the device id corresponds to all audio devices, including  input-only and output-only devices.
+	
+	bufferSize = 512;
+	
+	left.assign(bufferSize, 0.0);
+	right.assign(bufferSize, 0.0);
+	volHistory.assign(400, 0.0);
+	
+	bufferCounter	= 0;
+	drawCounter		= 0;
+	smoothedVol     = 0.0;
+	scaledVol		= 0.0;
+
+	soundStream.setup(this, 0, 2, 44100, bufferSize, 4);
+
+	//peak analysis
+	onsetSamples.assign(bufferSize, 0.0);
+//	recentBufferSamples.assign(bufferSize, 0.0);
+	holdOn = false;
+	exactOnsetIndex = 0;
+	
+	precisionLocator.setup(bufferSize);
+	
+}
+
+//--------------------------------------------------------------
+void testApp::update(){
+	//lets scale the vol up to a 0-1 range 
+	scaledVol = ofMap(smoothedVol, 0.0, 0.17, 0.0, 1.0, true);
+
+	//lets record the volume into an array
+	volHistory.push_back( scaledVol );
+	
+	//if we are bigger the the size we want to record - lets drop the oldest value
+	if( volHistory.size() >= 400 ){
+		volHistory.erase(volHistory.begin(), volHistory.begin()+1);
+	}
+}
+
+//--------------------------------------------------------------
+void testApp::draw(){
+	
+	ofSetColor(225);
+	ofDrawBitmapString("AUDIO INPUT EXAMPLE " + ofToString(exactOnsetIndex), 32, 32);
+	ofDrawBitmapString("press 's' to unpause the audio\n'e' to pause the audio", 31, 92);
+	
+	ofNoFill();
+	
+	// draw the left channel:
+	ofPushStyle();
+		ofPushMatrix();
+		ofTranslate(32, 120, 0);
+			
+		ofSetColor(225);
+		ofDrawBitmapString("Left Channel", 4, 18);
+		
+		ofSetLineWidth(1);	
+		ofRect(0, 0, 512, 200);
+
+		ofSetColor(245, 58, 135);
+		ofSetLineWidth(3);
+					
+			ofBeginShape();
+			for (int i = 0; i < left.size(); i++){
+				ofVertex(i, 100 -left[i]*180.0f);
+			}
+			ofEndShape(false);
+			
+		ofPopMatrix();
+	ofPopStyle();
+
+	// draw the right channel:
+	ofPushStyle();
+		ofPushMatrix();
+		ofTranslate(32, 320, 0);
+			
+		ofSetColor(225);
+		ofDrawBitmapString("Onset DF function", 4, 18);
+		
+		ofSetLineWidth(1);	
+		ofRect(0, 0, 512, 200);
+
+		ofSetColor(245, 58, 135);
+		ofSetLineWidth(3);
+					
+			ofBeginShape();
+			for (int i = 0; i < peakProcess.recentDFsamples.size(); i++){
+				int height = 100 - peakProcess.recentDFsamples[i]*10;
+				ofVertex(i*6, height);
+			//	if (recentDFonsetFound[i]){
+			//		ofCircle(32+i*6, 376+height , 10);
+			//	}
+//				ofVertex(i*2, 100 -right[i]*180.0f);
+			}
+			ofEndShape(false);
+			
+		ofPopMatrix();
+	ofPopStyle();
+	
+	//slope values
+	ofPushStyle();
+	ofPushMatrix();
+	ofTranslate(32, 320, 0);
+	
+	ofSetLineWidth(1);	
+	
+	ofSetColor(25, 124, 235);
+	ofSetLineWidth(3);
+	
+	ofBeginShape();
+	for (int i = 0; i < peakProcess.recentDFsamples.size(); i++){
+		int height = 100 - peakProcess.recentDFslopeValues[i]*10;
+		ofVertex(i*6, height);
+	
+	}
+	ofEndShape(false);
+	
+	ofPopMatrix();
+	ofPopStyle();
+	
+	
+	//ONSETS
+	ofPushStyle();
+	ofPushMatrix();
+	ofTranslate(32, 320, 0);
+	
+	ofSetColor(25, 224, 135);
+	ofSetLineWidth(3);
+	
+	ofBeginShape();
+	for (int i = 0; i < peakProcess.recentDFsamples.size(); i++){
+		if (peakProcess.recentDFonsetFound[i])
+		ofVertex(i*6, 0);
+		else {
+			ofVertex(i*6, 100);
+		}
+	}
+	ofEndShape(false);
+	
+	ofPopMatrix();
+	ofPopStyle();
+	
+	//ONSET Samples
+	ofPushStyle();
+	ofPushMatrix();
+	ofTranslate(32, 520, 0);
+	
+	ofSetColor(245, 224, 235);
+	ofSetLineWidth(3);
+	
+	ofBeginShape();
+	for (int i = 0; i < precisionLocator.onsetSamples.size(); i++){
+		int height = 100 + 100 * precisionLocator.onsetSamples[i];
+		ofVertex(i, height);
+	}
+	ofEndShape(false);
+	
+	ofSetColor(240,0,0);
+	ofLine(exactOnsetIndex, 0, exactOnsetIndex, 200);//stripe where on
+	
+	ofPopMatrix();
+	ofPopStyle();
+	
+	
+	// draw the average volume:
+	ofPushStyle();
+		ofPushMatrix();
+		ofTranslate(565, 120, 0);
+			
+		ofSetColor(225);
+		ofDrawBitmapString("Scaled average vol (0-100): " + ofToString(scaledVol * 100.0, 0), 4, 18);
+		ofRect(0, 0, 400, 400);
+		
+		ofSetColor(245, 58, 135);
+		ofFill();		
+		ofCircle(200, 200, scaledVol * 190.0f);
+		
+		//lets draw the volume history as a graph
+		ofBeginShape();
+		for (int i = 0; i < volHistory.size(); i++){
+			if( i == 0 ) ofVertex(i, 400);
+
+			ofVertex(i, 400 - volHistory[i] * 70);
+			
+			if( i == volHistory.size() -1 ) ofVertex(i, 400);
+		}
+		ofEndShape(false);		
+			
+		ofPopMatrix();
+	ofPopStyle();
+	
+	drawCounter++;
+	
+	ofSetColor(225);
+	string reportString = "buffers received: "+ofToString(bufferCounter)+"\ndraw routines called: "+ofToString(drawCounter)+"\nticks: " + ofToString(soundStream.getTickCount());
+	ofDrawBitmapString(reportString, 32, 89);
+		
+	
+	if (peakProcess.newOnsetFound){
+		ofSetColor(255,0,0);
+		ofCircle(200,200,200);
+	}
+}
+
+//--------------------------------------------------------------
+void testApp::audioIn(float * input, int bufferSize, int nChannels){	
+	
+	float curVol = 0.0;
+	
+	// samples are "interleaved"
+	int numCounted = 0;
+	
+	double frame[bufferSize];
+	
+	for (int i = 0;i < bufferSize;i++){
+		frame[i] = (double) input[i*2];
+	}
+	
+	double df_sample = (float) odf.getDFsample(frame);
+	
+	bool peakFound = peakProcess.peakProcessing(df_sample);//our new fn to look for DF onset events
+
+	//when we find a peak, we get the precise location of it
+	if (peakFound && !holdOn){
+		exactOnsetIndex = precisionLocator.findExactOnset(&frame[0]);
+	}
+	
+	//need to store these continually to help in location process
+	precisionLocator.storeSamples(&frame[0]);
+	
+	
+	//lets go through each sample and calculate the root mean square which is a rough way to calculate volume	
+	for (int i = 0; i < bufferSize; i++){
+
+		//recentBufferSamples[i] = frame[i];//store the last buffer in case needed for exact onset detection
+		
+		
+		
+		
+		left[i]		= input[i*2]*0.5;
+		right[i]	= input[i*2+1]*0.5;
+
+		curVol += left[i] * left[i];
+		curVol += right[i] * right[i];
+		numCounted+=2;
+		 
+	}
+	
+	//this is how we get the mean of rms :) 
+	curVol /= (float)numCounted;
+	
+	// this is how we get the root of rms :) 
+	curVol = sqrt( curVol );
+	
+	smoothedVol *= 0.93;
+	smoothedVol += 0.07 * curVol;
+	
+	bufferCounter++;
+	
+}
+/*
+int testApp::findExactOnset(){
+	double energySum = 0;
+	double lastEnergySum, hopsizeLastEnergySum;
+	double energyDifference;
+	int bestEnergyIndex = 0;
+	double bestEnergyDifference = 0;
+	int endIndex = bufferSize;
+	int hopSize;
+	
+	for (int resolution = bufferSize/2;resolution > 1;resolution/=2){
+		printf("resolution %i\n", resolution);
+	///	for (int i = bufferSize - resolution;i < bufferSize;i++){
+	//		lastEnergySum += recentBufferSamples[i] * recentBufferSamples[i];
+	//	}
+		
+		bestEnergyDifference = 0;
+	//	printf("previous energy %f", lastEnergySum);
+		//initialise last energySum
+		hopSize = resolution/2;
+		
+
+		lastEnergySum = getLastEnergySum(bestEnergyIndex, resolution);
+		hopsizeLastEnergySum = getLastEnergySum(bestEnergyIndex + hopSize, resolution);
+		
+		for (int startIndex = bestEnergyIndex;startIndex + resolution <= endIndex;startIndex += hopSize){
+			printf("index %i last energy %f hop energy %f ", startIndex, lastEnergySum, hopsizeLastEnergySum);
+			
+				//sum the energy for this new frame
+				energySum = 0;
+				for (int i = 0;i < resolution;i++){
+					energySum += onsetSamples[startIndex + i] * onsetSamples[startIndex + i];
+				}
+			
+			printf("energysum %f\n", energySum);
+			//check if new max difference
+			energyDifference = energySum - lastEnergySum;
+			if (energyDifference > bestEnergyDifference){
+				bestEnergyDifference = energyDifference;
+				bestEnergyIndex = startIndex;
+			}
+			
+			//store the values for checking in two loops time (because proceeding at resolution/2 each step)
+			//eg 0_to_128 compared to -128_to_0, 64_to_196 compared to -64_to_64, then 128_256 compared with 0_to_128, 
+			lastEnergySum = hopsizeLastEnergySum;// energySum;
+			hopsizeLastEnergySum = energySum;
+		
+		}
+		printf("winning index is %i\n", bestEnergyIndex);
+		endIndex = bestEnergyIndex + resolution;
+		
+	}
+	printf("TOTAL WINNER %i\n", bestEnergyIndex);
+	return bestEnergyIndex;
+	
+}
+
+double testApp::getLastEnergySum(const int& startIndex, const int& vectorSize){
+	double lastEnergySum = 0;
+	
+	for (int i = startIndex - vectorSize;i < startIndex;i++){
+		if (i > 0)
+			lastEnergySum += onsetSamples[i] * onsetSamples[i];
+		else {
+			lastEnergySum += recentBufferSamples[bufferSize + i] * recentBufferSamples[bufferSize + i];
+		}
+	}
+	return lastEnergySum;
+
+}
+*/
+/*
+bool testApp::peakProcessing(const double& newDFval){
+	recentDFsamples.erase (recentDFsamples.begin(), recentDFsamples.begin()+1);//erase first val
+	recentDFsamples.push_back(newDFval);
+	
+	double slopeVal = getBestSlopeValue(newDFval);
+	
+	newOnsetFound = checkForSlopeOnset(slopeVal);
+	printf("slope %f median %f det median %f\n", slopeVal, bestSlopeMedian, detectionTriggerThreshold);
+	
+	if (newOnsetFound)
+		printf("BANG!\n");
+	
+	recentDFslopeValues.erase (recentDFslopeValues.begin(), recentDFslopeValues.begin()+1);//erase first val
+	recentDFslopeValues.push_back(slopeVal);
+	
+	recentDFonsetFound.erase (recentDFonsetFound.begin(), recentDFonsetFound.begin()+1);//erase first val
+	recentDFonsetFound.push_back(newOnsetFound);
+
+	
+	//printf("\n");
+//	for (int i = 0;i < recentDFsamples.size();i++){
+//		printf("rdf[%i] %f\n", i, recentDFsamples[i]);
+//	}
+	//printf("SLOPE %f\n", slopeVal);
+}
+
+
+double testApp::getBestSlopeValue(const float& dfvalue){
+	
+	//the idea is we want a high slope
+	double bestValue = 0;
+	
+	for (int i = 1;i < min(numberOfDetectionValuesToTest, (int)recentDFsamples.size() - 1);i++){
+		double angle = 0;
+		int otherIndex = recentDFsamples.size() - i + 1;
+		double testValue = 0;
+		
+		if (otherIndex > 0 && recentDFsamples[otherIndex] > 0 
+			&& recentDFsamples[otherIndex] < dfvalue
+			){
+			angle = atan((float)(i * dfvalue)/ (numberOfDetectionValuesToTest*(dfvalue-recentDFsamples[otherIndex])) );
+			testValue = (dfvalue - recentDFsamples[otherIndex]) * cos(angle);
+		}
+		
+		if (testValue > bestValue)
+			bestValue = testValue;
+	}
+	
+	return bestValue;
+	
+}
+
+
+
+bool testApp :: checkForSlopeOnset(const float& bestValue){
+	bool onsetDetected = false;
+	//check for onset relative to our processed slope function
+	//a mix between increase in value and the gradient of that increase
+	
+	currentFrame++;
+	
+	if (bestValue > bestSlopeMedian * thresholdRelativeToMedian && //better than recent average 
+		(currentFrame - lastSlopeOnsetFrame) > cutoffForRepeatOnsetsFrames //after cutoff time
+		&& slopeFallenBelowMedian // has had onset and fall away again
+		&& bestValue > detectionTriggerThreshold * detectionTriggerRatio //longer term ratio of winning onsets 
+		){
+		//	printf("frame diff between onsets %6.1f", (1000*framesToSeconds(currentFrame - lastMedianOnsetFrame)) );
+		onsetDetected = true;
+		lastSlopeOnsetFrame = currentFrame;
+		slopeFallenBelowMedian = false;
+		
+		updateDetectionTriggerThreshold(bestValue);
+	}
+	
+	
+	if (bestValue > bestSlopeMedian){
+		bestSlopeMedian += (bestValue - bestSlopeMedian)*0.04;//was 1.1
+	}
+	else{
+		bestSlopeMedian *= 0.99;
+		slopeFallenBelowMedian = true;;
+	}
+	
+	//bestSlopeMedian += 0.02* (bestValue - bestSlopeMedian);
+	
+
+	
+	return onsetDetected;
+}
+
+void testApp :: updateDetectionTriggerThreshold(const float& val){
+	float detectionAdaptSpeed = 0.05;//moving average, roughly last twenty onsets
+	detectionTriggerThreshold *= 1- detectionAdaptSpeed;
+	detectionTriggerThreshold += (val * detectionAdaptSpeed);
+}
+
+*/
+//--------------------------------------------------------------
+void testApp::keyPressed  (int key){ 
+	if( key == 's' ){
+		soundStream.start();
+	}
+	
+	if( key == 'e' ){
+		soundStream.stop();
+	}
+	
+	if (key == 'h'){
+		holdOn = !holdOn;
+	}
+}
+
+//--------------------------------------------------------------
+void testApp::keyReleased(int key){ 
+	
+}
+
+//--------------------------------------------------------------
+void testApp::mouseMoved(int x, int y ){
+	
+}
+
+//--------------------------------------------------------------
+void testApp::mouseDragged(int x, int y, int button){
+	
+}
+
+//--------------------------------------------------------------
+void testApp::mousePressed(int x, int y, int button){
+	
+}
+
+//--------------------------------------------------------------
+void testApp::mouseReleased(int x, int y, int button){
+
+}
+
+//--------------------------------------------------------------
+void testApp::windowResized(int w, int h){
+
+}
+
+//--------------------------------------------------------------
+void testApp::gotMessage(ofMessage msg){
+
+}
+
+//--------------------------------------------------------------
+void testApp::dragEvent(ofDragInfo dragInfo){ 
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/testApp.h	Fri Sep 21 16:35:17 2012 +0100
@@ -0,0 +1,84 @@
+#ifndef _TEST_APP
+#define _TEST_APP
+
+
+#include "ofMain.h"
+
+#include "OnsetDetectionFunction.h"
+#include "PeakProcessor.h"
+#include "PreciseOnsetLocator.h"
+
+class testApp : public ofBaseApp{
+	
+	public:
+		
+		void setup();
+		void update();
+		void draw();
+		
+		void keyPressed(int key);
+		void keyReleased(int key);
+		void mouseMoved(int x, int y );
+		void mouseDragged(int x, int y, int button);
+		void mousePressed(int x, int y, int button);
+		void mouseReleased(int x, int y, int button);
+		void windowResized(int w, int h);
+		void dragEvent(ofDragInfo dragInfo);
+		void gotMessage(ofMessage msg);
+				
+		void audioIn(float * input, int bufferSize, int nChannels); 
+	
+		vector <float> left;
+		vector <float> right;
+		vector <float> volHistory;
+		
+		int 	bufferCounter;
+		int 	drawCounter;
+		
+		float smoothedVol;
+		float scaledVol;
+		
+		ofSoundStream soundStream;
+	
+		OnsetDetectionFunction odf;
+	
+	PeakProcessor peakProcess;
+	
+	PreciseOnsetLocator precisionLocator;
+	
+	bool holdOn;
+	int bufferSize;
+	int exactOnsetIndex;
+	vector <double> onsetSamples;//holds the audio samples when onset is found
+//	vector <double> recentBufferSamples;
+	
+/*
+ //peak processing requires
+		static const int vectorSize = 512/6; 
+		vector<double> recentDFsamples; 
+		vector<bool> recentDFonsetFound;
+		vector<double> recentDFslopeValues;
+	
+	int numberOfDetectionValuesToTest;
+	bool peakProcessing(const double& newDFval);
+	double getBestSlopeValue(const float& dfvalue);
+	bool checkForSlopeOnset(const float& bestValue);
+	int currentFrame, lastSlopeOnsetFrame, cutoffForRepeatOnsetsFrames;
+	void updateDetectionTriggerThreshold(const float& val);
+	float detectionTriggerThreshold, detectionTriggerRatio;
+	float bestSlopeMedian, thresholdRelativeToMedian;
+	bool newOnsetFound, slopeFallenBelowMedian;
+ */
+/*	
+
+
+	
+	double getLastEnergySum(const int& startIndex, const int& vectorSize);
+	int findExactOnset();
+
+ */
+};
+
+
+#endif	
+