view Source/AubioOnsetDetector.cpp @ 2:b4c899822b4e

added in slope bang using median
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Wed, 19 Oct 2011 21:08:45 +0100
parents 8f67db3c0b01
children 979125db34ab
line wrap: on
line source
/*
 *  AubioOnsetDetector.cpp
 *  aubioonset~
 *
 *  Created by Andrew Robertson on 13/08/2010.
 *  Copyright 2010 __MyCompanyName__. All rights reserved.
 *
 */

#include "AubioOnsetDetector.h"

AubioOnsetDetector :: AubioOnsetDetector(){
	buffersize = 1024;
	hopsize = 512;
		//aubio related setup
		o = new_aubio_onsetdetection(aubio_onset_complex, buffersize, 1);//initially in complex mode
		pv = (aubio_pvoc_t *)new_aubio_pvoc(buffersize, hopsize, 1);
		parms = new_aubio_peakpicker(threshold);
		vec = (fvec_t *)new_fvec(hopsize,1);
		
		threshold = 1;
		threshold2 = -70.;

	resetValues();
	thresholdRelativeToMedian = 1.3;
	cutoffForRepeatOnsetsMillis = 100;
	medianSpeed = 10;
	pos = 0;
}

AubioOnsetDetector :: ~AubioOnsetDetector(){
		aubio_onsetdetection_free (o);
		
}

void AubioOnsetDetector :: resetValues(){
	rawDetectionValue = 1;
	peakPickedDetectionValue = 1;
	medianDetectionValue = 1;
	lastMedianOnsetFrame = 0;
	currentFrame = 0;
	aubioLongTermAverage = 1;
	lastDfValue = 0;
	bestSlopeValue = 0;
	recentValueIndex = 0;
	lastSlopeOnsetFrame = 0;
	bestSlopeMedian = 10;
	slopeFallenBelowMedian = true;
	
	for (int i = 0;i< numberOfDetectionValues;i++)
		recentRawDetectionValues[i] = 1;
	
}


void AubioOnsetDetector :: initialise(){
	//reinitialises our object
		o = new_aubio_onsetdetection(aubio_onset_complex, buffersize, 1);//initially in complex mode
		pv = (aubio_pvoc_t *)new_aubio_pvoc(buffersize, hopsize, 1);
		parms = new_aubio_peakpicker(threshold);
		vec = (fvec_t *)new_fvec(hopsize,1);
		pos = 0;
				fvec_write_sample(vec, 0.234, 0, pos);
				fftgrain  = (cvec_t *)new_cvec(buffersize,1);
				onset = (fvec_t *)new_fvec(1,1);
		}

bool AubioOnsetDetector :: processframe(float frame[], int n){
	bool newFrameResult = false;
	//Paul Brossier's aubioonsetclass~ code ported from Pd
		int j,isonset;
	for (j=0;j<n;j++) {
		// write input to datanew 
		fvec_write_sample(vec, frame[j], 0, pos);//vec->data[0][pos] = frame[j]
		//time for fft
	
			if (pos == hopsize-1) {  //hopsize is 512       
			newFrameResult = true;
			aubioOnsetFound = false;
			// block loop 
			aubio_pvoc_do (pv,vec, fftgrain);
			
			fftgrain->norm[0][0] = fabs(fftgrain->norm[0][0]);
			//added hack to solve bug that norm[0][0] is negative sometimes.
			
			aubio_onsetdetection(o, fftgrain, onset);
			rawDetectionValue = onset->data[0][0];
		//Paul Brossier's method to return value of peak picking process
				
			anrMedianProcessedOnsetFound = checkForMedianOnset(rawDetectionValue);
				
			bestSlopeValue = getBestSlopeValue(rawDetectionValue); 
			anrBestSlopeOnset =	checkForSlopeOnset(bestSlopeValue);
				
	//	smpl_t my_sample_value;
		peakPickedDetectionValue = aubio_peakpick_pimrt_getval(parms); 
	//peakPickedDetectionValue = my_sample_value;

	//this was what got sent from max object::			
	//	outlet_float(x->detectionFunctionOutlet, my_sample_value);
	//	outlet_float(x->rawDetectionFunctionOutlet, x->onset->data[0][0]);
		
			isonset = aubio_peakpick_pimrt(onset,parms);
			if (isonset) {
				// test for silence 
				if (aubio_silence_detection(vec, threshold2)==1)
					{
					isonset=0;
					}
				else{
	//				outlet_bang(x->bangoutlet);
					aubioOnsetFound = true;
								
							}
			}//end if (isonset)
		
			
		
			// end of block loop 
			pos = -1; // so it will be zero next j loop 
		}
		pos++;
//	outL[j] = frame[j];//have added this so signal is "see through": outputting the input signal
	
	}
//end of Paul's code

return newFrameResult;
		
}


bool AubioOnsetDetector :: checkForMedianOnset(float dfvalue){
	bool onsetDetected = false;
	//check for onset relative to our rising and falling median threshold
	if (dfvalue > medianDetectionValue * thresholdRelativeToMedian && 
		dfvalue > aubioLongTermAverage &&
		//lastDfValue < medianDetectionValue &&
		 1000*framesToSeconds(currentFrame - lastMedianOnsetFrame) > cutoffForRepeatOnsetsMillis){
		printf("frame diff between onsets %6.1f", (1000*framesToSeconds(currentFrame - lastMedianOnsetFrame)) );
			onsetDetected = true;
			lastMedianOnsetFrame = currentFrame;
		}
		
		aubioLongTermAverage *= 0.999;
		aubioLongTermAverage += 0.001*(dfvalue - aubioLongTermAverage);
	
		if (dfvalue > medianDetectionValue)
			medianDetectionValue = dfvalue;
		else 
			medianDetectionValue += 0.01*medianSpeed*(dfvalue - medianDetectionValue);
	
	currentFrame++;
	lastDfValue = dfvalue;

	
	return onsetDetected;
}

double AubioOnsetDetector::getBestSlopeValue(float dfvalue){
//the idea is we want a high slope
	recentRawDetectionValues[recentValueIndex] = dfvalue;
	double bestValue = 0;
	for (int i = 1;i < numberOfDetectionValues;i++){
		double angle = 0;
		int otherIndex = (recentValueIndex - i + numberOfDetectionValues)%numberOfDetectionValues;
		double testValue = 0;
		if (otherIndex > 0 && recentRawDetectionValues[otherIndex] > 0){
			angle = atan((float)(i * dfvalue)/ (numberOfDetectionValues*(dfvalue-recentRawDetectionValues[otherIndex])) );
			testValue = (dfvalue - recentRawDetectionValues[otherIndex]) * cos(angle);
		}
		
		if (testValue > bestValue)
			bestValue = testValue;
	}
	
	recentValueIndex++;
	
	if (recentValueIndex == numberOfDetectionValues)
	recentValueIndex = 0;

		
	return bestValue;
	
}




bool AubioOnsetDetector :: checkForSlopeOnset(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
	
	if (bestValue > bestSlopeMedian * thresholdRelativeToMedian && 
		1000*framesToSeconds(currentFrame - lastSlopeOnsetFrame) > cutoffForRepeatOnsetsMillis
		&& slopeFallenBelowMedian
		){
		printf("frame diff between onsets %6.1f", (1000*framesToSeconds(currentFrame - lastMedianOnsetFrame)) );
		onsetDetected = true;
		lastSlopeOnsetFrame = currentFrame;
		slopeFallenBelowMedian = false;
	}
	
	
	if (bestValue > bestSlopeMedian)
		bestSlopeMedian += (bestValue - bestSlopeMedian)*0.1;
	else{
		bestSlopeMedian *= 0.995;
		slopeFallenBelowMedian = true;;
	}
	return onsetDetected;
}

double  AubioOnsetDetector::framesToSeconds(float frames){
	double seconds = frames * buffersize / 44100.;
	return seconds;
}

float AubioOnsetDetector :: getRawDetectionFrame(){
return rawDetectionValue;	
}

float AubioOnsetDetector :: getPeakPickedDetectionFrame(){
return peakPickedDetectionValue;	
}


void AubioOnsetDetector :: onsetclass_energy(){
		//aubio_onsetdetection_type
		aubio_onsetdetection_free (o);
		o = new_aubio_onsetdetection(aubio_onset_energy, buffersize, 1);
}

void AubioOnsetDetector :: onsetclass_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.*/
		aubio_onsetdetection_free (o);
		o = new_aubio_onsetdetection(aubio_onset_hfc, buffersize, 1);
}


void AubioOnsetDetector :: onsetclass_complex(){
		//aubio_onsetdetection_type
		//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.
		aubio_onsetdetection_free (o);
		o = new_aubio_onsetdetection(aubio_onset_complex, buffersize, 1);
}

void AubioOnsetDetector :: onsetclass_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.*/
  		aubio_onsetdetection_free (o);
		o = new_aubio_onsetdetection(aubio_onset_phase, buffersize, 1);
		
}

void AubioOnsetDetector :: onsetclass_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 (o);
		o = new_aubio_onsetdetection(aubio_onset_specdiff, buffersize, 1);
}

void AubioOnsetDetector :: onsetclass_kl(){
		/** 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.
		*/
		aubio_onsetdetection_free (o);
		o = new_aubio_onsetdetection(aubio_onset_kl, buffersize, 1);
}

void AubioOnsetDetector :: onsetclass_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.*/		
		aubio_onsetdetection_free (o);
		o = new_aubio_onsetdetection(aubio_onset_hfc, buffersize, 1);
}