annotate src/PeakProcessor.cpp @ 3:50f62c48b421

Small change
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Fri, 03 Jan 2014 17:43:02 +0000
parents 7ec1ed0b2eb0
children 93b9a9471011
rev   line source
andrew@0 1 /*
andrew@0 2 * PeakProcessor.cpp
andrew@0 3 * peakOnsetDetector
andrew@0 4 *
andrew@2 5 * Created by Andrew Robertson on 07/09/2012.
andrew@0 6 * Copyright 2012 QMUL. All rights reserved.
andrew@0 7 *
andrew@0 8 */
andrew@0 9
andrew@0 10 #include "PeakProcessor.h"
andrew@0 11
andrew@2 12 const bool printingOn = true;//false;
andrew@2 13
andrew@0 14 PeakProcessor::PeakProcessor(){
andrew@0 15
andrew@0 16 recentDFsamples.assign(vectorSize, 0.0);
andrew@0 17 recentDFonsetFound.assign(vectorSize, false);
andrew@0 18 recentDFslopeValues.assign(vectorSize, 0.0);
andrew@0 19
andrew@0 20 numberOfDetectionValuesToTest = 10;
andrew@0 21 currentFrame = 0;
andrew@0 22 cutoffForRepeatOnsetsFrames = 4;
andrew@0 23 detectionTriggerRatio = 0.5f;
andrew@2 24 detectionTriggerThreshold = 5;//0.1;
andrew@2 25 bestSlopeMedian = 8;
andrew@0 26 thresholdRelativeToMedian = 1.1;
andrew@0 27 slopeFallenBelowMedian = true;
andrew@0 28 lastSlopeOnsetFrame = 0;
andrew@0 29 }
andrew@0 30
andrew@0 31 PeakProcessor::~PeakProcessor(){
andrew@0 32
andrew@0 33 recentDFsamples.clear();
andrew@0 34 recentDFonsetFound.clear();
andrew@0 35 recentDFslopeValues.clear();
andrew@0 36 }
andrew@0 37
andrew@0 38
andrew@0 39 bool PeakProcessor::peakProcessing(const double& newDFval){
andrew@0 40 recentDFsamples.erase (recentDFsamples.begin(), recentDFsamples.begin()+1);//erase first val
andrew@0 41 recentDFsamples.push_back(newDFval);
andrew@0 42
andrew@0 43 double slopeVal = getBestSlopeValue(newDFval);
andrew@0 44
andrew@0 45 newOnsetFound = checkForSlopeOnset(slopeVal);
andrew@0 46
andrew@2 47 if (printingOn)
andrew@2 48 printf("PeakProcessor: slope %f best slope median %f det trigger thresh median %f\n", slopeVal, bestSlopeMedian, detectionTriggerThreshold);
andrew@0 49
andrew@2 50 if (newOnsetFound && printingOn){
andrew@2 51 printf("PeakProcessor: BANG!\n");
andrew@0 52 }
andrew@0 53
andrew@0 54 recentDFslopeValues.erase (recentDFslopeValues.begin(), recentDFslopeValues.begin()+1);//erase first val
andrew@0 55 recentDFslopeValues.push_back(slopeVal);
andrew@0 56
andrew@0 57 recentDFonsetFound.erase (recentDFonsetFound.begin(), recentDFonsetFound.begin()+1);//erase first val
andrew@0 58 recentDFonsetFound.push_back(newOnsetFound);
andrew@0 59
andrew@0 60
andrew@0 61 //printf("\n");
andrew@0 62 // for (int i = 0;i < recentDFsamples.size();i++){
andrew@0 63 // printf("rdf[%i] %f\n", i, recentDFsamples[i]);
andrew@0 64 // }
andrew@0 65 //printf("SLOPE %f\n", slopeVal);
andrew@0 66
andrew@0 67 return newOnsetFound;
andrew@0 68 }
andrew@0 69
andrew@0 70
andrew@0 71 double PeakProcessor::getBestSlopeValue(const float& dfvalue){
andrew@0 72
andrew@0 73 //the idea is we want a high slope
andrew@0 74 double bestValue = 0;
andrew@0 75
andrew@0 76 for (int i = 1;i < min(numberOfDetectionValuesToTest, (int)recentDFsamples.size() - 1);i++){
andrew@0 77 double angle = 0;
andrew@0 78 int otherIndex = recentDFsamples.size() - i + 1;
andrew@0 79 double testValue = 0;
andrew@0 80
andrew@0 81 if (otherIndex > 0 && recentDFsamples[otherIndex] > 0
andrew@0 82 && recentDFsamples[otherIndex] < dfvalue
andrew@0 83 ){
andrew@0 84 angle = atan((float)(i * dfvalue)/ (numberOfDetectionValuesToTest*(dfvalue-recentDFsamples[otherIndex])) );
andrew@0 85 testValue = (dfvalue - recentDFsamples[otherIndex]) * cos(angle);
andrew@0 86 }
andrew@0 87
andrew@0 88 if (testValue > bestValue)
andrew@0 89 bestValue = testValue;
andrew@0 90 }
andrew@0 91
andrew@0 92 return bestValue;
andrew@0 93
andrew@0 94 }
andrew@0 95
andrew@0 96
andrew@0 97
andrew@0 98 bool PeakProcessor :: checkForSlopeOnset(const float& bestValue){
andrew@0 99 bool onsetDetected = false;
andrew@0 100 //check for onset relative to our processed slope function
andrew@0 101 //a mix between increase in value and the gradient of that increase
andrew@0 102
andrew@0 103 currentFrame++;
andrew@0 104
andrew@0 105 if (bestValue > bestSlopeMedian * thresholdRelativeToMedian && //better than recent average
andrew@0 106 (currentFrame - lastSlopeOnsetFrame) > cutoffForRepeatOnsetsFrames //after cutoff time
andrew@0 107 && slopeFallenBelowMedian // has had onset and fall away again
andrew@0 108 && bestValue > detectionTriggerThreshold * detectionTriggerRatio //longer term ratio of winning onsets
andrew@0 109 ){
andrew@0 110 // printf("frame diff between onsets %6.1f", (1000*framesToSeconds(currentFrame - lastMedianOnsetFrame)) );
andrew@0 111 onsetDetected = true;
andrew@0 112 lastSlopeOnsetFrame = currentFrame;
andrew@0 113 slopeFallenBelowMedian = false;
andrew@0 114
andrew@0 115 updateDetectionTriggerThreshold(bestValue);
andrew@0 116 }
andrew@0 117
andrew@0 118
andrew@0 119 if (bestValue > bestSlopeMedian){
andrew@0 120 bestSlopeMedian += (bestValue - bestSlopeMedian)*0.04;//was 1.1
andrew@0 121 }
andrew@0 122 else{
andrew@0 123 bestSlopeMedian *= 0.99;
andrew@0 124 slopeFallenBelowMedian = true;;
andrew@0 125 }
andrew@0 126
andrew@0 127 //bestSlopeMedian += 0.02* (bestValue - bestSlopeMedian);
andrew@0 128
andrew@0 129 return onsetDetected;
andrew@0 130 }
andrew@0 131
andrew@0 132 void PeakProcessor :: updateDetectionTriggerThreshold(const float& val){
andrew@0 133 float detectionAdaptSpeed = 0.05;//moving average, roughly last twenty onsets
andrew@0 134 detectionTriggerThreshold *= 1- detectionAdaptSpeed;
andrew@0 135 detectionTriggerThreshold += (val * detectionAdaptSpeed);
andrew@0 136 }