Mercurial > hg > precise-onset-detection
view src/PeakProcessor.cpp @ 8:184a7c232049 tip
changed files since updating computer
author | Venetian |
---|---|
date | Thu, 14 Aug 2014 17:53:57 +0100 |
parents | 93b9a9471011 |
children |
line wrap: on
line source
/* * PeakProcessor.cpp * peakOnsetDetector * * Created by Andrew Robertson on 07/09/2012. * Copyright 2012 QMUL. All rights reserved. * */ #include "PeakProcessor.h" const bool printingOn = false;//true;//false;//true;//false; /* how it works detectionTriggerThreshold is a fairly fdast moving average (every twenty frames) tend to require newValue > detectionTriggerRatio * detectionTriggerThreshold */ PeakProcessor::PeakProcessor(){ recentDFsamples.assign(vectorSize, 0.0); recentDFonsetFound.assign(vectorSize, false); recentDFslopeValues.assign(vectorSize, 0.0); /* //all in reset numberOfDetectionValuesToTest = 10; currentFrame = 0; cutoffForRepeatOnsetsFrames = 8; detectionTriggerRatio = 0.34f;//was 0.5 detectionTriggerThreshold = 0.2;//was 1.5 is trigger? bestSlopeMedian = 3; thresholdRelativeToMedian = 1.1; slopeFallenBelowMedian = true; lastSlopeOnsetFrame = 0; */ initialise(); reset(); minimumThreshold = 15.; } PeakProcessor::~PeakProcessor(){ recentDFsamples.clear(); recentDFonsetFound.clear(); recentDFslopeValues.clear(); } void PeakProcessor::initialise(){ numberOfDetectionValuesToTest = 10; cutoffForRepeatOnsetsFrames = 8; detectionTriggerRatio = 0.234f;//was 0.5 thresholdRelativeToMedian = 1.01;//need to be this multiple above median value //median tends to move relatively slowly reset(); /* slopeFallenBelowMedian = true; lastSlopeOnsetFrame = 0; currentFrame = 0; */ } void PeakProcessor::reset(){ /* numberOfDetectionValuesToTest = 10; cutoffForRepeatOnsetsFrames = 8; detectionTriggerRatio = 0.234f;//was 0.5 detectionTriggerThreshold = 0.2; bestSlopeMedian = 3; thresholdRelativeToMedian = 1.01;//need to be this multiple above median value */ //median tends to move relatively slowly slopeFallenBelowMedian = true; lastSlopeOnsetFrame = 0; currentFrame = 0; detectionTriggerThreshold = 0.4; bestSlopeMedian = 16; } 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); if (printingOn) printf("PeakProcessor: slope %f best slope median %f det trigger thresh median %f\n", slopeVal, bestSlopeMedian, detectionTriggerThreshold); if (newOnsetFound && printingOn){ printf("PeakProcessor: 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; double bestCosAngle = 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; bestCosAngle = cos(angle); } } if (printingOn) printf("best value %f dfValue %f cosAngle %f\n", bestValue, dfvalue, bestCosAngle); 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 && bestValue > minimumThreshold//fixed minimum requirement ){ // printf("frame diff between onsets %6.1f", (1000*framesToSeconds(currentFrame - lastMedianOnsetFrame)) ); onsetDetected = true; lastSlopeOnsetFrame = currentFrame; slopeFallenBelowMedian = false; updateDetectionTriggerThreshold(bestValue); if (printingOn) printf("ONSET, best value %f, min %f\n", bestValue, minimumThreshold); } 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); }