view DrumTimingLoader_OF/ofxAubioOnsetDetection/ofxAubioOnsetDetection.cpp @ 3:303edbbcf1bd tip

updated ofxAubioOnsetDetection file
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Sun, 24 Nov 2013 08:15:17 +0000
parents 82352cfc0b23
children
line wrap: on
line source
/*
 *  ofxAubioOnsetDetection.cpp
 *  ofxOnsetDetection
 *
 *  Created by Andrew on 24/11/2011.
 *  Copyright 2011 QMUL. All rights reserved.
 *
 */

#include "ofxAubioOnsetDetection.h"


//@ do: fix up reset - maybe think of using vectors

//tracktypes:
//there are three types
//0 and 2 - the onset only type
//1 - bass - ie.e uses aubio pitch
//3 - harmonic - such as guitar represented by a chromagram following the onset

//we calculate these by logging the time then filling up a window for the calculation.



ofxAubioOnsetDetection::ofxAubioOnsetDetection(){
	//onsetDetector = new AubioOnsetDetector();
	onsetDetector.initialise();
	
	initialiseValues();
	
	printf("ofxAubioOnsetDetector made\n");
	
	amplitudeNumber = 256;//number of amplitudes shown on screen
	maximumAubioPitch = 220;//max pitch shown inside window
	minimumAubioPitch = 55.0/2.0;
	trackType = 0;
		

	printf("max val on making is %f\n", onsetDetector.maximumDetectionValue);
}


ofxAubioOnsetDetection::~ofxAubioOnsetDetection(){
//	delete onsetDetector;
	printf("DELETE ONSET CALLED\n");
//	delete qmOnsetDetector;
}

void ofxAubioOnsetDetection::initialiseValues(){
	printf("ONSET DETECTOR INITIALISED\n");
	//	useMedianOnsetDetection = true;
	onsetIndex = 0;
	frameCountIndex = 0;
	playPositionFrames = 0;
	playPosition = 0;
	
	screenWidth = ofGetWidth();
	screenHeight = ofGetHeight();
	
	//each file has onset window to be displayed in
	window.setToRelativeSize(0.1, 0.1, 0.8, 0.3);
	//fullScreen.setToRelativeSize(0,0,1,1);
	
	drawParams.width = 5;
	drawParams.maximumValue = 10;
	drawParams.minimumValue = 0;
	drawParams.difference = 10;
	drawParams.scale_factor = 30;
	
	setDrawParams();
}

void ofxAubioOnsetDetection::reset(){
	onsetIndex = 0;
	frameCountIndex = 0;
	
	for (int i = 0;i < NUM_DETECTION_SAMPLES;i++){
		onsetFunction[i] = 0;
		medianOnsetFunction[i] = 0;
		highSlopeOnsetFunction[i] = 0;
		
	}
	
	
	highSlopeOnsetsFrames.clear();
	highSlopeOnsetsMillis.clear();//The high slope onsets are the ones stored as chromaOnsets
	//(i.e. have associated chroma and pitch to them)
	chromaOnsets.clear();
	
	onsetDetector.resetValues();
	
	printf("Resetting the ofxAubioOnsetDetector\n");
}


void ofxAubioOnsetDetection::processFrame(double* frame, const int& n){
	//bool onsetFound = false;
	// aubio onset detector then processes current frame - returns bool true when new detection is output
	//if buffer full and new result is processed (buffer is 1024 with hopsize 512 - can be set to other values)
	
	//for other class OnsetDetectionFunction : dfSample = qmonsetDetector.getDFsample(frame);
		
	//printf("process using double\n"); - NOT USING
	
	if (onsetDetector.processframe(frame, n)){

		rawOnsetFunction[onsetIndex] = onsetDetector.rawDetectionValue;
		medianOnsetFunction[onsetIndex] = onsetDetector.medianDetectionValue;
//		aubioOnsetFunction[onsetIndex] = ??;
		highSlopeOnsetFunction[onsetIndex] = onsetDetector.bestSlopeValue;
		aubioLongTermAverage[onsetIndex] = onsetDetector.aubioLongTermAverage;
		
		//	outlet_float(x->detectionFunctionOutlet, x->onsetDetector.peakPickedDetectionValue);
		
		if (onsetDetector.aubioOnsetFound){
			aubioOnsetRecorded[onsetIndex] = true;
		}
		else{
			aubioOnsetRecorded[onsetIndex] = false;//anr chnage late on
		}
		
		
		if (onsetDetector.anrMedianProcessedOnsetFound){
			onsetFound = true;
			medianOnsetRecorded[onsetIndex] = true;
		}else{
			onsetFound = false;
			medianOnsetRecorded[onsetIndex] = false;
		}
		
		if (onsetDetector.anrBestSlopeOnset){
			highSlopeOnsetRecorded[onsetIndex] = true;
			highSlopeOnsetsFrames.push_back(frameCountIndex);
			highSlopeOnsetsMillis.push_back(framesToMillis(frameCountIndex));
			
			printf("onset frame %i is time %f \n", frameCountIndex, framesToMillis(frameCountIndex));
			
			
			chromaOnsetPtr = new ChromaOnset();
			chromaOnsetPtr ->frameTime = frameCountIndex;
			chromaOnsetPtr->millisTime = framesToMillis(frameCountIndex);
			chromaOnsetPtr->onsetIndex = onsetIndex;
			chromaOnsets.push_back(*chromaOnsetPtr);
			
			
		}
		else{
			highSlopeOnsetRecorded[onsetIndex] = false;
		}
		
		frameCountIndex++;//this one never loops
		onsetIndex++;
		if (onsetIndex == NUM_DETECTION_SAMPLES)
			onsetIndex = 0;//this loops round
		
	}//end if new aubio onset detection result
	
	printf("N is %i\n", n);
	float* tmpFrame;
	vector<float> tmpFloatvector;
	for (int i = 0;i < n;i++){
		//tmpFrame[i] = frame[i];
		tmpFloatvector.push_back(frame[i]);
	}
	
	checkChromaAndPitch(&tmpFloatvector[0], n);
	
	
 }

void ofxAubioOnsetDetection::checkChromaAndPitch(float* tmpFrame, const int& n){
	//new method for pitch
	//calculate always
	pitchDetector.addToBuffer(tmpFrame, n);
	
	//process frames into each onset's chromagram analyser
	for (int i = 0;i < chromaOnsets.size();i++){
		
		//aubio pitch using yin
		if (trackType == 1 && !chromaOnsets[i].aubioPitchFound ){//not yet done
			
			
			//dont actually need to add this to the frame anymore!
		//	chromaOnsets[i].onsetFrame.addToFrame(tmpFrame, n);//add to frame in the chromaOnset class
		//	chromaOnsets[i].onsetFrame.frameCounter += n;
			chromaOnsets[i].pitchFrameCounter += n;
			
			//used to use chromaOnsets[i].pitchFrameCounter
		//	printf("adding to frame for onset %i at frametime %i\n", i, frameCountIndex);
			if (chromaOnsets[i].pitchFrameCounter >= pitchDetector.bufsize){//enough to calculate yin with using aubio pitch detection
				
				printf("frame %i onset frame counter %i chromacounter %i\n", chromaOnsets[i].onsetFrame.sizeOfFrame, chromaOnsets[i].onsetFrame.frameCounter, chromaOnsets[i].pitchFrameCounter );
				
				
				//float originalPitchMethod = pitchDetector.doPitchDetection(&chromaOnsets[i].onsetFrame.frame[0], pitchDetector.bufsize);
				chromaOnsets[i].aubioPitch = pitchDetector.getPitch();//used to be originalPitchMethod;
				
				chromaOnsets[i].aubioPitchFound = true;
				chromaOnsets[i].onsetFrame.deleteFrame();
		//		printf("Aubio Pitch recieved for onset %i is %f\n", i, chromaOnsets[i].aubioPitch);
				
			
				
			
			}
				
		}
		
		
		//chroma
		if (chromaOnsets[i].processFrame(tmpFrame, n) && trackType == 1){
			//!= 3 : i.e. true when we dont need so we delete immediately
			//printf("onset %i (frametime %i) chroma is newly calculated at frame %i\n", i, chromaOnsets[i].frameTime, frameCountIndex);
			chromaOnsets[i].printInfo();
			chromaOnsets[i].deleteChromagram();
		}
		
	}//end for all onsets
}

void ofxAubioOnsetDetection::processFrame(float* frame, const int& n){
	//bool onsetFound = false;
	// aubio onset detector then processes current frame - returns bool true when new detection is output
	//if buffer full and new result is processed (buffer is 1024 with hopsize 512 - can be set to other values)
	
	//for other class OnsetDetectionFunction : dfSample = qmonsetDetector.getDFsample(frame);
	
//	printf("process using float\n");
	//THIS ONE IS USED!
	
	if (onsetDetector.processframe(frame, n)){
		
		rawOnsetFunction[onsetIndex] = onsetDetector.rawDetectionValue;
		medianOnsetFunction[onsetIndex] = onsetDetector.medianDetectionValue;
		//		aubioOnsetFunction[onsetIndex] = ??;
		highSlopeOnsetFunction[onsetIndex] = onsetDetector.bestSlopeValue;
		aubioLongTermAverage[onsetIndex] = onsetDetector.aubioLongTermAverage;
		
		//	outlet_float(x->detectionFunctionOutlet, x->onsetDetector.peakPickedDetectionValue);
		
		if (onsetDetector.aubioOnsetFound){
			aubioOnsetRecorded[onsetIndex] = true;
		}
		else{
			aubioOnsetRecorded[onsetIndex] = false;
		}
		
		
		if (onsetDetector.anrMedianProcessedOnsetFound){
			onsetFound = true;
			medianOnsetRecorded[onsetIndex] = true;
		}else{
			onsetFound = false;
			medianOnsetRecorded[onsetIndex] = false;
		}
		
		if (onsetDetector.anrBestSlopeOnset){
			//do
			highSlopeOnsetRecorded[onsetIndex] = true;
			
			printf("Frame index %i ", frameCountIndex);
			int exactOnsetIndex = precisionLocator.findExactOnset(&frame[0], n);//divide by 512.0 or bufferSize to get [0,1] value
			printf("Exact index %i ", exactOnsetIndex);
			
			highSlopeOnsetsFrames.push_back(frameCountIndex);
			
			//actually we need to go forwards not back
//			float exactOffset = -1.0*framesToMillis((float)(n - exactOnsetIndex)/512.0); - not this 
			float exactOffset = framesToMillis((float)(exactOnsetIndex)/n);	//so counting frames after the beginning of the frame
			//since index n will be the start of the n_th frame
			
			
			float millistime = framesToMillis(frameCountIndex);
			float finalPreciseTime = millistime + exactOffset;//i.e. with offset due to energy analysis of frame
			printf("exact offset %f millis %f final time %f\n", exactOffset, millistime, finalPreciseTime);
			highSlopeOnsetsMillis.push_back(finalPreciseTime);
			
			
			//did use the above but all info held in ChromaOnset class
		
			/*
			 ChromaOnset c;
			 c.frameTime = frameCountIndex;
			 c.millisTime = framesToMillis(frameCountIndex);
			 c.onsetIndex = onsetIndex;
			 */
			chromaOnsetPtr = new ChromaOnset();
			chromaOnsetPtr->frameTime = frameCountIndex;
			chromaOnsetPtr->onsetIndex = onsetIndex;
			chromaOnsetPtr->millisTime = finalPreciseTime;//framesToMillis(frameCountIndex);
			chromaOnsets.push_back(*chromaOnsetPtr);
			
		//	printf("frame %i is time %f \n", frameCountIndex, framesToMillis(frameCountIndex));
		}
		else{
			highSlopeOnsetRecorded[onsetIndex] = false;
		}
		
		frameCountIndex++;//this one never loops
		onsetIndex++;
		if (onsetIndex == NUM_DETECTION_SAMPLES)
			onsetIndex = 0;//this loops round
		
	}//end if new aubio onset detection result
	
	//need to store these continually to help in location process
	precisionLocator.storeSamples(&frame[0]);
	
	checkChromaAndPitch(frame, n);
	
}



double ofxAubioOnsetDetection::framesToMillis(const double& frameCount){
	return ((frameCount*onsetDetector.hopsize*1000.0)/44100.0);
}

void ofxAubioOnsetDetection::printOnsetList(){
	printf("PRINT ONSET LIST\n");
	for (int i = 0;i < chromaOnsets.size();i++){
		printf("%i:", i);
		chromaOnsets[i].printInfo();
	}
	printf("PRONT COMPLETE\n");
}

#pragma mark -drawRoutines
void ofxAubioOnsetDetection::drawOnsetDetection(){
	
	drawOnsetDetection(0, amplitudeNumber, window);
//	ofDrawBitmapString("amp no"+ofToString(amplitudeNumber),40,40);
	
}//end draw onset fn

void ofxAubioOnsetDetection::drawOnsetDetectionScrolling(){
	
	int startFrame = (int)(playPositionFrames/amplitudeNumber)* amplitudeNumber;
	//setDrawParams();
	
	drawParams.windowStartFrame = startFrame;
	
	drawOutlineAndSetParams(window);
	
	if (trackType == 0 || trackType == 2)
	drawOnsetDetection(startFrame, startFrame+amplitudeNumber, window);

	setDrawParams(window);
	drawChromaOnsetData(startFrame, startFrame+amplitudeNumber, window);
	
	drawScrollLine(startFrame, window);
}//end draw onset fn


void ofxAubioOnsetDetection::drawOutlineAndSetParams(const ofxWindowRegion& screenRegion){	
	ofBackground(0);
	setDrawParams(screenRegion);
	ofSetColor(100,150,250);
	screenRegion.drawOutline();
}


void ofxAubioOnsetDetection::drawOnsetDetection(int startIndex, int endIndex, const ofxWindowRegion& screenRegion){
	

	
	int tmpIndex = onsetIndex;
	float width = screenRegion.width / (float) amplitudeNumber;	
	float maximumValue = onsetDetector.maximumDetectionValue;
	float minimumValue = 0;//minimumDetectionFunction ;
	float difference = maximumValue - minimumValue;
	float scale_factor = screenRegion.height/ difference;
	
	endIndex = min(endIndex, startIndex+amplitudeNumber);
	
//	drawChromaOnsetData(startIndex, endIndex, screenRegion);
	
	for (int Xvalue = startIndex;Xvalue < endIndex; Xvalue++){
		
		int Xindex = Xvalue;//(endIndex - Xvalue) ;
		
		int previousIndex = (Xindex-1);
		if (Xindex < 0){
			Xindex += NUM_DETECTION_SAMPLES;
			if (previousIndex < 0)
				previousIndex += NUM_DETECTION_SAMPLES;
		}
		
		//onsetFunction[] also processed	but not shown - Brossier's?
		
		
		ofSetColor(155);//,200,55);
		
		
		int previousXpos = (int) (screenRegion.x + (width*(Xvalue - startIndex - 1)));
		int Xpos = (int) (screenRegion.x +(width*(Xvalue - startIndex)));		
		
		ofLine(previousXpos, screenRegion.y + screenRegion.height - (scale_factor*(rawOnsetFunction[previousIndex]- minimumValue)), 
			   Xpos,  screenRegion.y + screenRegion.height - (scale_factor*(rawOnsetFunction[Xindex]- minimumValue)) );
		
		
		
		//median of Onset fn	
		ofSetColor(0,105,0);		
		ofLine(previousXpos, screenRegion.y + screenRegion.height - (scale_factor*(medianOnsetFunction[previousIndex]- minimumValue)), 
			   Xpos,  screenRegion.y + screenRegion.height - (scale_factor*(medianOnsetFunction[Xindex]- minimumValue)) );
		
		
		if (medianOnsetRecorded[Xindex] == true){
			ofSetColor(0,255,0);
			ofCircle(Xpos, screenRegion.y + screenRegion.height - (scale_factor*(medianOnsetFunction[Xindex]- minimumValue)) , 4);
		}
		
		
		ofSetColor(0,0,160);
		ofLine(previousXpos, screenRegion.y + screenRegion.height - (scale_factor*(highSlopeOnsetFunction[previousIndex]- minimumValue)), 
			   Xpos,  screenRegion.y + screenRegion.height - (scale_factor*(highSlopeOnsetFunction[Xindex]- minimumValue)) );
		
		//bright blue - slope based onsets
		if (highSlopeOnsetRecorded[Xindex] == true){
			ofSetColor(0,0,255);
			ofCircle(Xpos, screenRegion.y + screenRegion.height - (scale_factor*(highSlopeOnsetFunction[Xindex]- minimumValue)) , 4);
		}
		
		//long term average in dull grey
		ofSetColor(100);
		ofLine(previousXpos, screenRegion.y + screenRegion.height - (scale_factor*(aubioLongTermAverage[previousIndex]- minimumValue)), 
			   Xpos,  screenRegion.y + screenRegion.height - (scale_factor*(aubioLongTermAverage[Xindex]- minimumValue)) );
		
		
		ofSetColor(255,100,0);
		
	}//end for Xvalue (across the recent observations of osc data)
	
	
	//some axis stuff deleted
	
	
//	string tmpInfoString = "(windowed)max val "+ofToString(onsetDetector.maximumDetectionValue,2);
//	tmpInfoString += " diff "+ofToString(difference);	
//	ofDrawBitmapString(tmpInfoString, 100,200);
	
}//end draw onset fn

void ofxAubioOnsetDetection::drawScrollLine(const int& startIndex, const ofxWindowRegion& screenRegion){
	//play position
	float width = screenRegion.width / (float) amplitudeNumber;	
	ofSetColor(255,255,255);
	playPositionFrames = playPosition * frameCountIndex;
	ofLine(screenRegion.x + width*(playPositionFrames-startIndex), screenRegion.y , screenRegion.x + width*(playPositionFrames-startIndex), screenRegion.y + screenRegion.height);
}


void ofxAubioOnsetDetection::drawChromaOnsetData(const int& startIndex, const int& endIndex, const ofxWindowRegion& screenRegion){
	
	int chromaIndex = 0;//chromaOnsets.size()/2;
	while (chromaIndex > 0 && chromaOnsets[chromaIndex].onsetIndex > startIndex)
		chromaIndex--;
	
	while (chromaIndex < chromaOnsets.size() && chromaOnsets[chromaIndex].onsetIndex < startIndex)
		chromaIndex++;
	
	switch (trackType) {
		case 1:
			drawPitchLines(chromaIndex, endIndex, screenRegion);
			break;
		case 3:
				drawChromaStripes(chromaIndex, endIndex, screenRegion);
			break;
		case 0:
			ofSetColor(100,0,0);
			drawOnsetStripes(chromaIndex, endIndex, screenRegion);
			break;
		case 2:
			ofSetColor(100,100,0);
			drawOnsetStripes(chromaIndex, endIndex, screenRegion);
			break;	
	}//end switch
	


}//end draw chroma

void ofxAubioOnsetDetection::drawOnsetStripes(int chromaIndex, const int& frameEndIndex, const ofxWindowRegion& screenRegion){
			
			
	while (chromaIndex < chromaOnsets.size() && chromaOnsets[chromaIndex].chromaCalculated && chromaOnsets[chromaIndex].onsetIndex < frameEndIndex) {
				
				//ofSetColor(255,100,255);
				
				int Xindex = chromaOnsets[chromaIndex].onsetIndex;
				int Xvalue = frameEndIndex - Xindex;
				
		//		for (int j = 0;j < 12;j++){
					
				//	if (!chromaOnsets[chromaIndex].matched)
				//		ofSetColor(0,0,255*chromaOnsets[chromaIndex].chromaValues[11-j], 20);
				//	else
				//		ofSetColor(255*chromaOnsets[chromaIndex].chromaValues[11-j],0,0, 20);
					
					ofRect(screenRegion.x + drawParams.width*(amplitudeNumber - Xvalue), screenRegion.y, 4, screenRegion.height);
		//		}
				
		//		ofCircle(screenRegion.x + drawParams.width*(amplitudeNumber - Xvalue), screenRegion.y + screenRegion.height - (drawParams.scale_factor*(highSlopeOnsetFunction[Xindex]- drawParams.minimumValue)) , 4);
				
				chromaIndex++;
			}
			
}//end draw chroma		
		
void ofxAubioOnsetDetection::drawChromaStripes(int chromaIndex, const int& frameEndIndex, const ofxWindowRegion& screenRegion){
	
	
	while (chromaIndex < chromaOnsets.size() && chromaOnsets[chromaIndex].chromaCalculated && chromaOnsets[chromaIndex].onsetIndex < frameEndIndex) {
		
		ofSetColor(255,100,255);
		
		int Xindex = chromaOnsets[chromaIndex].onsetIndex;
		int Xvalue = frameEndIndex - Xindex;
		
		for (int j = 0;j < 12;j++){
			
			if (!chromaOnsets[chromaIndex].matched)
				ofSetColor(0,0,255*chromaOnsets[chromaIndex].chromaValues[11-j], 20);
			else
				ofSetColor(255*chromaOnsets[chromaIndex].chromaValues[11-j],0,0, 20);
			
			ofRect(screenRegion.x + drawParams.width*(amplitudeNumber - Xvalue), screenRegion.y + screenRegion.height*j/12.0, 20, screenRegion.height/12);
		}
		
		ofCircle(screenRegion.x + drawParams.width*(amplitudeNumber - Xvalue), screenRegion.y + screenRegion.height - (drawParams.scale_factor*(highSlopeOnsetFunction[Xindex]- drawParams.minimumValue)) , 4);
		
		chromaIndex++;
	}
	
}//end draw chroma

void ofxAubioOnsetDetection::drawPitchLines(int chromaIndex, const int& frameEndIndex, const ofxWindowRegion& screenRegion){
	
	ofSetLineWidth(2);
	
	while (chromaIndex < chromaOnsets.size() && chromaOnsets[chromaIndex].chromaCalculated && chromaOnsets[chromaIndex].onsetIndex < frameEndIndex) {
		
		int Xindex = chromaOnsets[chromaIndex].onsetIndex;
		int Xvalue = frameEndIndex - Xindex;
		
		//now do pitch in log freq
		float heightFactor = 0;
		if (chromaOnsets[chromaIndex].aubioPitch > 0)
			heightFactor = log(chromaOnsets[chromaIndex].aubioPitch/minimumAubioPitch) / log(maximumAubioPitch/minimumAubioPitch);
		heightFactor = 1 - heightFactor;
		//red lines for freq
		ofSetColor(255,0,0);
		//ofSetLineWidth(8);
		ofLine(screenRegion.x + drawParams.width*(amplitudeNumber - Xvalue), screenRegion.y + screenRegion.height*heightFactor, 
			   screenRegion.x + drawParams.width*(amplitudeNumber - Xvalue) + 50, screenRegion.y + screenRegion.height*heightFactor);
		
		ofSetColor(255,0,255);
		ofDrawBitmapString(ofToString(chromaOnsets[chromaIndex].aubioPitch, 1) , screenRegion.x + drawParams.width*(amplitudeNumber - Xvalue) + 4, screenRegion.y + screenRegion.height*heightFactor - 4);
		chromaIndex++;
	}
	
	ofSetLineWidth(1);
	
	
}//end draw pitch lines


#pragma mark -setParams
void ofxAubioOnsetDetection::setDrawParams(){
	screenWidth = ofGetWidth();
	screenHeight = ofGetHeight();//justin case
	
	drawParams.width = screenWidth / (float) amplitudeNumber;	
	drawParams.maximumValue = onsetDetector.maximumDetectionValue;
	drawParams.minimumValue = 0;//minimumDetectionFunction ;
	drawParams.difference = drawParams.maximumValue - drawParams.minimumValue;
	drawParams.scale_factor = screenHeight/ drawParams.difference;
	
}

void ofxAubioOnsetDetection::setDrawParams(const ofxWindowRegion& screenRegion){
	
	drawParams.width = screenRegion.width / (float) amplitudeNumber;	
	drawParams.maximumValue = onsetDetector.maximumDetectionValue;
	drawParams.minimumValue = 0;//minimumDetectionFunction ;
	drawParams.difference = drawParams.maximumValue - drawParams.minimumValue;
	drawParams.scale_factor = screenRegion.height/ drawParams.difference;
}


void ofxAubioOnsetDetection::windowResized(const int& w, const int& h){
	screenWidth = ofGetWidth();
	screenHeight = ofGetHeight();
	window.resized(w, h);
	fullScreen.resized(w, h);
}


void ofxAubioOnsetDetection::printChromaInfo(){
	for (int i = 0;i < chromaOnsets.size();i++)
		chromaOnsets[i].printInfo();
	
	printf("max value on printing is %f\n", onsetDetector.maximumDetectionValue);
}

void ofxAubioOnsetDetection::aubioOnsetDetect_energy(){
	onsetDetector.onsetclass_energy();
	printf("Energy based onset detection now used by aubioOnsetDetect~.");
}

void ofxAubioOnsetDetection::aubioOnsetDetect_hfc(){
	/** High Frequency Content onset detection function
	 
	 This method computes the High Frequency Content (HFC) of the input spectral
	 frame. The resulting function is efficient at detecting percussive onsets.
	 
	 Paul Masri. Computer modeling of Sound for Transformation and Synthesis of
	 Musical Signal. PhD dissertation, University of Bristol, UK, 1996.*/

	onsetDetector.onsetclass_hfc();
	printf("High Frequency Content (Masri '96) detection now used by aubioOnsetDetect~.");
}


void ofxAubioOnsetDetection::aubioOnsetDetect_complex(){
	//Complex Domain Method onset detection function 
	//Christopher Duxbury, Mike E. Davies, and Mark B. Sandler. Complex domain
	//onset detection for musical signals. In Proceedings of the Digital Audio
	//Effects Conference, DAFx-03, pages 90-93, London, UK, 2003.
	onsetDetector.onsetclass_complex();
	printf("Complex domain onset detection (Duxbury et al., DaFx '03) now used by aubioOnsetDetect~.");
	
}

void ofxAubioOnsetDetection::aubioOnsetDetect_phase(){
	/** Phase Based Method onset detection function 
	 
	 Juan-Pablo Bello, Mike P. Davies, and Mark B. Sandler. Phase-based note onset
	 detection for music signals. In Proceedings of the IEEE International
	 Conference on Acoustics Speech and Signal Processing, pages 441­444,
	 Hong-Kong, 2003.*/

	onsetDetector.onsetclass_phase();
	printf("Phase-based detection (Bello et al., IEEE '03) now used by aubioOnsetDetect~.");
}

void ofxAubioOnsetDetection::aubioOnsetDetect_specdiff(){
	/* Spectral difference method onset detection function 
	 Jonhatan Foote and Shingo Uchihashi. The beat spectrum: a new approach to
	 rhythm analysis. In IEEE International Conference on Multimedia and Expo
	 (ICME 2001), pages 881­884, Tokyo, Japan, August 2001.
	 */
	//aubio_onsetdetection_type
	//aubio_onsetdetection_free (x->o);
	onsetDetector.onsetclass_specdiff();
	printf("Spectral Difference (Foote and Shingo Uchihashi, ICME '01) detection now used by aubioOnsetDetect~.");
	
	
}

void ofxAubioOnsetDetection::aubioOnsetDetect_kl(){
	//aubio_onsetdetection_type
	//aubio_onsetdetection_free (x->o);
	/** Kullback-Liebler onset detection function 
	 
	 Stephen Hainsworth and Malcom Macleod. Onset detection in music audio
	 signals. In Proceedings of the International Computer Music Conference
	 (ICMC), Singapore, 2003.
	 */
	
	onsetDetector.onsetclass_kl();
	printf("Kullback-Liebler (Hainsworth and McLeod, ICMC '03) detection now used by aubioOnsetDetect~.");
}

void ofxAubioOnsetDetection::aubioOnsetDetect_mkl(){
	/** Modified Kullback-Liebler onset detection function 
	 
	 Paul Brossier, ``Automatic annotation of musical audio for interactive
	 systems'', Chapter 2, Temporal segmentation, PhD thesis, Centre for Digital
	 music, Queen Mary University of London, London, UK, 2003.*/		
	onsetDetector.onsetclass_mkl();
	printf("Modified Kullback-Liebler (Brossier, PhD thesis '03) detection now used by aubioOnsetDetect~.");
}


/*
 axis stuff end
 //label y axis
 int axisHeight, stepSize;
 ofSetColor(255,255,255);
 stepSize = 1000;
 
 while((difference / stepSize) < 3)
 stepSize /= 2;
 
 while ((difference / stepSize) > 7)// maximum 6 numbers to display
 stepSize *= 2;
 
 
 for (axisHeight = 0; axisHeight < maximumDetectionFunction; axisHeight += stepSize){
 ofDrawBitmapString( ofToString((int)axisHeight), ofGetWidth()-50,
 (int) ((TEXT_HEIGHT/2) +(screenHeight - (scale_factor*(axisHeight- minimumValue)))) );
 }
 
 for (axisHeight = max(0, (int)minimumDetectionFunction); axisHeight > min(0, (int)minimumDetectionFunction); axisHeight -= stepSize){
 ofDrawBitmapString( ofToString((int)axisHeight), ofGetWidth()-50,
 (int) ((TEXT_HEIGHT/2) +(screenHeight - (scale_factor*(axisHeight- minimumValue)))) );
 }
 
 //label x axis
 stepSize = 20;//need to make sure not too many of these:
 
 while((amplitudeNumber / stepSize) < 4)
 stepSize /= 2;
 
 while ((amplitudeNumber / stepSize) > 8)
 stepSize *= 2;
 
 int labelIndex = onsetIndex - (onsetIndex % stepSize);
 for (int y = labelIndex; y > onsetIndex - amplitudeNumber; y -= stepSize){
 ofDrawBitmapString( ofToString((int)y), (int) (width*(amplitudeNumber - (onsetIndex - y))), (int) ((TEXT_HEIGHT+2) + (screenHeight - (scale_factor*(0 - minimumValue)))) );
 }
 */






void ofxAubioOnsetDetection::drawOnsetDetection(int startIndex, int endIndex){
	ofBackground(0);
	setDrawParams();
	
	int tmpIndex = onsetIndex;
	float width = screenWidth / (float) amplitudeNumber;	
	float maximumValue = onsetDetector.maximumDetectionValue;
	float minimumValue = 0;//minimumDetectionFunction ;
	float difference = maximumValue - minimumValue;
	float scale_factor = screenHeight/ difference;
	
	//draw axis
	ofSetColor(255,255,255);
	ofDrawBitmapString(ofToString((startIndex)), 20, 20);
	
	ofLine(0, screenHeight - (scale_factor*(0 - minimumValue)), 
		   (int) (width*(amplitudeNumber)),  screenHeight - (scale_factor*(0 - minimumValue)) );
	
	
	
	endIndex = min(endIndex, startIndex+amplitudeNumber);
	
	drawChromaOnsetData(startIndex, endIndex);
	
	for (int Xvalue = startIndex;Xvalue < endIndex; Xvalue++){
		
		int Xindex = Xvalue;//(endIndex - Xvalue) ;
		
		int previousIndex = (Xindex-1);
		if (Xindex < 0){
			Xindex += NUM_DETECTION_SAMPLES;
			if (previousIndex < 0)
				previousIndex += NUM_DETECTION_SAMPLES;
		}
		
		//onsetFunction[] also processed	but not shown - Brossier's?
		
		
		ofSetColor(155);//,200,55);
		
		
		int previousXpos = (int) (width*(Xvalue - startIndex - 1));
		int Xpos = (int) (width*(Xvalue - startIndex));		
		
		ofLine(previousXpos, screenHeight - (scale_factor*(rawOnsetFunction[previousIndex]- minimumValue)), 
			   Xpos,  screenHeight - (scale_factor*(rawOnsetFunction[Xindex]- minimumValue)) );
		
		
		
		//median of Onset fn	
		ofSetColor(0,105,0);		
		ofLine(previousXpos, screenHeight - (scale_factor*(medianOnsetFunction[previousIndex]- minimumValue)), 
			   Xpos,  screenHeight - (scale_factor*(medianOnsetFunction[Xindex]- minimumValue)) );
		
		
		if (medianOnsetRecorded[Xindex] == true){
			ofSetColor(0,255,0);
			ofCircle(Xpos, screenHeight - (scale_factor*(medianOnsetFunction[Xindex]- minimumValue)) , 4);
		}
		
		
		ofSetColor(0,0,160);
		ofLine(previousXpos, screenHeight - (scale_factor*(highSlopeOnsetFunction[previousIndex]- minimumValue)), 
			   Xpos,  screenHeight - (scale_factor*(highSlopeOnsetFunction[Xindex]- minimumValue)) );
		
		//bright blue - slope based onsets
		if (highSlopeOnsetRecorded[Xindex] == true){
			ofSetColor(0,0,255);
			ofCircle(Xpos, screenHeight - (scale_factor*(highSlopeOnsetFunction[Xindex]- minimumValue)) , 4);
		}
		
		//long term average in dull grey
		ofSetColor(100);
		ofLine(previousXpos, screenHeight - (scale_factor*(aubioLongTermAverage[previousIndex]- minimumValue)), 
			   Xpos,  screenHeight - (scale_factor*(aubioLongTermAverage[Xindex]- minimumValue)) );
		
		
		ofSetColor(255,100,0);
		
	}//end for Xvalue (across the recent observations of osc data)
	
	//axis stuff at end
	
	//play position
	ofSetColor(255,255,255);
	playPositionFrames = playPosition * frameCountIndex;
	ofLine(width*(playPositionFrames-startIndex), 0, width*(playPositionFrames-startIndex), screenHeight);
	
	
	//ofDrawBitmapString("max val "+ofToString(onsetDetector.maximumDetectionValue,2), 100,200);
}//end draw onset fn



void ofxAubioOnsetDetection::drawChromaOnsetData(const int& startIndex, const int& endIndex){
	
	int chromaIndex = 0;//chromaOnsets.size()/2;
	while (chromaIndex > 0 && chromaOnsets[chromaIndex].onsetIndex > startIndex)
		chromaIndex--;
	
	while (chromaIndex < chromaOnsets.size() && chromaOnsets[chromaIndex].onsetIndex < startIndex)
		chromaIndex++;
	
	
	while (chromaIndex < chromaOnsets.size() && chromaOnsets[chromaIndex].chromaCalculated && chromaOnsets[chromaIndex].onsetIndex < endIndex) {
		
		ofSetColor(255,100,255);
		
		int Xindex = chromaOnsets[chromaIndex].onsetIndex;
		int Xvalue = endIndex - Xindex;
		
		for (int j = 0;j < 12;j++){
			ofSetColor(0,0,255*chromaOnsets[chromaIndex].chromaValues[11-j], 20);
			ofRect(drawParams.width*(amplitudeNumber - Xvalue), screenHeight*j/12.0, 6, screenHeight/12);
		}
		
		ofCircle(drawParams.width*(amplitudeNumber - Xvalue), screenHeight - (drawParams.scale_factor*(highSlopeOnsetFunction[Xindex]- drawParams.minimumValue)) , 4);
		
		//now do pitch in log freq
		float heightFactor = 0;
		if (chromaOnsets[chromaIndex].aubioPitch > 0)
			heightFactor = log(chromaOnsets[chromaIndex].aubioPitch) / log(maximumAubioPitch);
		heightFactor = 1 - heightFactor;
		ofSetColor(255,0,0);
		//ofSetLineWidth(8);
		ofLine(drawParams.width*(amplitudeNumber - Xvalue), heightFactor*screenHeight, drawParams.width*(amplitudeNumber - Xvalue) + 50, heightFactor*screenHeight);
		
		ofSetColor(0,0,255);
		ofDrawBitmapString(ofToString(chromaOnsets[chromaIndex].aubioPitch, 1) , drawParams.width*(amplitudeNumber - Xvalue), heightFactor*screenHeight-4);
		chromaIndex++;
	}
	
	ofSetColor(255,255,235);
	ofDrawBitmapString("full drawparams width "+ofToString(drawParams.width), 100, 100);
	ofDrawBitmapString("full x"+ofToString(fullScreen.x)+" width "+ofToString(fullScreen.width), 100, 120);
}//end draw chroma



/*
 DRAW CHROMA JUNK
 while (chromaIndex < chromaOnsets.size() && chromaOnsets[chromaIndex].chromaCalculated && chromaOnsets[chromaIndex].onsetIndex < endIndex) {
 
 ofSetColor(255,100,255);
 
 int Xindex = chromaOnsets[chromaIndex].onsetIndex;
 int Xvalue = endIndex - Xindex;
 
 for (int j = 0;j < 12;j++){
 
 if (!chromaOnsets[chromaIndex].matched)
 ofSetColor(0,0,255*chromaOnsets[chromaIndex].chromaValues[11-j], 20);
 else
 ofSetColor(255*chromaOnsets[chromaIndex].chromaValues[11-j],0,0, 20);
 
 ofRect(screenRegion.x + drawParams.width*(amplitudeNumber - Xvalue), screenRegion.y + screenRegion.height*j/12.0, 6, screenRegion.height/12);
 }
 
 ofCircle(screenRegion.x + drawParams.width*(amplitudeNumber - Xvalue), screenRegion.y + screenRegion.height - (drawParams.scale_factor*(highSlopeOnsetFunction[Xindex]- drawParams.minimumValue)) , 4);
 
 //now do pitch in log freq
 float heightFactor = 0;
 if (chromaOnsets[chromaIndex].aubioPitch > 0)
 heightFactor = log(chromaOnsets[chromaIndex].aubioPitch) / log(maximumAubioPitch);
 heightFactor = 1 - heightFactor;
 //red lines for freq
 ofSetColor(255,0,0);
 //ofSetLineWidth(8);
 ofLine(screenRegion.x + drawParams.width*(amplitudeNumber - Xvalue), screenRegion.y + screenRegion.height*heightFactor, 
 screenRegion.x + drawParams.width*(amplitudeNumber - Xvalue) + 50, screenRegion.y + screenRegion.height*heightFactor);
 
 ofSetColor(0,0,255);
 ofDrawBitmapString(ofToString(chromaOnsets[chromaIndex].aubioPitch, 1) , screenRegion.x + drawParams.width*(amplitudeNumber - Xvalue) + 4, screenRegion.y + screenRegion.height*heightFactor - 4);
 chromaIndex++;
 }
 */

//	ofSetColor(255,255,235);
//	ofDrawBitmapString("windowed drawparams width "+ofToString(drawParams.width), 100, 100);
//	ofDrawBitmapString("windowed x"+ofToString(screenRegion.x)+" width "+ofToString(screenRegion.width), 100, 120);