annotate 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
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
Venetian@8 12 const bool printingOn = false;//true;//false;//true;//false;
Venetian@8 13
Venetian@8 14
Venetian@8 15 /*
Venetian@8 16 how it works
Venetian@8 17 detectionTriggerThreshold is a fairly fdast moving average (every twenty frames)
Venetian@8 18 tend to require newValue > detectionTriggerRatio * detectionTriggerThreshold
Venetian@8 19 */
andrew@2 20
andrew@0 21 PeakProcessor::PeakProcessor(){
andrew@0 22
andrew@0 23 recentDFsamples.assign(vectorSize, 0.0);
andrew@0 24 recentDFonsetFound.assign(vectorSize, false);
andrew@0 25 recentDFslopeValues.assign(vectorSize, 0.0);
Venetian@8 26 /*
Venetian@8 27 //all in reset
andrew@0 28 numberOfDetectionValuesToTest = 10;
andrew@0 29 currentFrame = 0;
Venetian@8 30 cutoffForRepeatOnsetsFrames = 8;
andrew@4 31 detectionTriggerRatio = 0.34f;//was 0.5
Venetian@8 32 detectionTriggerThreshold = 0.2;//was 1.5 is trigger?
andrew@4 33 bestSlopeMedian = 3;
andrew@0 34 thresholdRelativeToMedian = 1.1;
andrew@0 35 slopeFallenBelowMedian = true;
andrew@0 36 lastSlopeOnsetFrame = 0;
Venetian@8 37 */
Venetian@8 38 initialise();
Venetian@8 39 reset();
Venetian@8 40 minimumThreshold = 15.;
andrew@0 41 }
andrew@0 42
andrew@0 43 PeakProcessor::~PeakProcessor(){
andrew@0 44
andrew@0 45 recentDFsamples.clear();
andrew@0 46 recentDFonsetFound.clear();
andrew@0 47 recentDFslopeValues.clear();
andrew@0 48 }
andrew@0 49
andrew@0 50
Venetian@8 51 void PeakProcessor::initialise(){
Venetian@8 52 numberOfDetectionValuesToTest = 10;
Venetian@8 53 cutoffForRepeatOnsetsFrames = 8;
Venetian@8 54 detectionTriggerRatio = 0.234f;//was 0.5
Venetian@8 55 thresholdRelativeToMedian = 1.01;//need to be this multiple above median value
Venetian@8 56 //median tends to move relatively slowly
Venetian@8 57 reset();
Venetian@8 58 /* slopeFallenBelowMedian = true;
Venetian@8 59 lastSlopeOnsetFrame = 0;
Venetian@8 60 currentFrame = 0;
Venetian@8 61 */
Venetian@8 62 }
Venetian@8 63
Venetian@8 64 void PeakProcessor::reset(){
Venetian@8 65 /*
Venetian@8 66 numberOfDetectionValuesToTest = 10;
Venetian@8 67
Venetian@8 68 cutoffForRepeatOnsetsFrames = 8;
Venetian@8 69 detectionTriggerRatio = 0.234f;//was 0.5
Venetian@8 70 detectionTriggerThreshold = 0.2;
Venetian@8 71 bestSlopeMedian = 3;
Venetian@8 72 thresholdRelativeToMedian = 1.01;//need to be this multiple above median value
Venetian@8 73 */
Venetian@8 74 //median tends to move relatively slowly
Venetian@8 75 slopeFallenBelowMedian = true;
Venetian@8 76 lastSlopeOnsetFrame = 0;
Venetian@8 77 currentFrame = 0;
Venetian@8 78 detectionTriggerThreshold = 0.4;
Venetian@8 79 bestSlopeMedian = 16;
Venetian@8 80 }
Venetian@8 81
andrew@0 82 bool PeakProcessor::peakProcessing(const double& newDFval){
andrew@0 83 recentDFsamples.erase (recentDFsamples.begin(), recentDFsamples.begin()+1);//erase first val
andrew@0 84 recentDFsamples.push_back(newDFval);
andrew@0 85
andrew@0 86 double slopeVal = getBestSlopeValue(newDFval);
andrew@0 87
andrew@0 88 newOnsetFound = checkForSlopeOnset(slopeVal);
andrew@0 89
andrew@2 90 if (printingOn)
andrew@2 91 printf("PeakProcessor: slope %f best slope median %f det trigger thresh median %f\n", slopeVal, bestSlopeMedian, detectionTriggerThreshold);
andrew@0 92
andrew@2 93 if (newOnsetFound && printingOn){
andrew@2 94 printf("PeakProcessor: BANG!\n");
andrew@0 95 }
andrew@0 96
andrew@0 97 recentDFslopeValues.erase (recentDFslopeValues.begin(), recentDFslopeValues.begin()+1);//erase first val
andrew@0 98 recentDFslopeValues.push_back(slopeVal);
andrew@0 99
andrew@0 100 recentDFonsetFound.erase (recentDFonsetFound.begin(), recentDFonsetFound.begin()+1);//erase first val
andrew@0 101 recentDFonsetFound.push_back(newOnsetFound);
andrew@0 102
andrew@0 103
andrew@0 104 //printf("\n");
andrew@0 105 // for (int i = 0;i < recentDFsamples.size();i++){
andrew@0 106 // printf("rdf[%i] %f\n", i, recentDFsamples[i]);
andrew@0 107 // }
andrew@0 108 //printf("SLOPE %f\n", slopeVal);
andrew@0 109
andrew@0 110 return newOnsetFound;
andrew@0 111 }
andrew@0 112
andrew@0 113
andrew@0 114 double PeakProcessor::getBestSlopeValue(const float& dfvalue){
andrew@0 115
andrew@0 116 //the idea is we want a high slope
andrew@0 117 double bestValue = 0;
Venetian@8 118 double bestCosAngle = 0;
andrew@0 119
andrew@0 120 for (int i = 1;i < min(numberOfDetectionValuesToTest, (int)recentDFsamples.size() - 1);i++){
andrew@0 121 double angle = 0;
andrew@0 122 int otherIndex = recentDFsamples.size() - i + 1;
andrew@0 123 double testValue = 0;
andrew@0 124
andrew@0 125 if (otherIndex > 0 && recentDFsamples[otherIndex] > 0
andrew@0 126 && recentDFsamples[otherIndex] < dfvalue
andrew@0 127 ){
andrew@0 128 angle = atan((float)(i * dfvalue)/ (numberOfDetectionValuesToTest*(dfvalue-recentDFsamples[otherIndex])) );
andrew@0 129 testValue = (dfvalue - recentDFsamples[otherIndex]) * cos(angle);
andrew@0 130 }
andrew@0 131
Venetian@8 132 if (testValue > bestValue){
andrew@0 133 bestValue = testValue;
Venetian@8 134 bestCosAngle = cos(angle);
Venetian@8 135 }
andrew@0 136 }
Venetian@8 137 if (printingOn)
Venetian@8 138 printf("best value %f dfValue %f cosAngle %f\n", bestValue, dfvalue, bestCosAngle);
Venetian@8 139
andrew@0 140 return bestValue;
andrew@0 141
andrew@0 142 }
andrew@0 143
andrew@0 144
andrew@0 145
andrew@0 146 bool PeakProcessor :: checkForSlopeOnset(const float& bestValue){
andrew@0 147 bool onsetDetected = false;
andrew@0 148 //check for onset relative to our processed slope function
andrew@0 149 //a mix between increase in value and the gradient of that increase
andrew@0 150
andrew@0 151 currentFrame++;
andrew@0 152
andrew@0 153 if (bestValue > bestSlopeMedian * thresholdRelativeToMedian && //better than recent average
andrew@0 154 (currentFrame - lastSlopeOnsetFrame) > cutoffForRepeatOnsetsFrames //after cutoff time
andrew@0 155 && slopeFallenBelowMedian // has had onset and fall away again
andrew@0 156 && bestValue > detectionTriggerThreshold * detectionTriggerRatio //longer term ratio of winning onsets
Venetian@8 157 && bestValue > minimumThreshold//fixed minimum requirement
andrew@0 158 ){
andrew@0 159 // printf("frame diff between onsets %6.1f", (1000*framesToSeconds(currentFrame - lastMedianOnsetFrame)) );
andrew@0 160 onsetDetected = true;
andrew@0 161 lastSlopeOnsetFrame = currentFrame;
andrew@0 162 slopeFallenBelowMedian = false;
andrew@0 163
andrew@0 164 updateDetectionTriggerThreshold(bestValue);
Venetian@8 165
Venetian@8 166 if (printingOn)
Venetian@8 167 printf("ONSET, best value %f, min %f\n", bestValue, minimumThreshold);
andrew@0 168 }
andrew@0 169
andrew@0 170
andrew@0 171 if (bestValue > bestSlopeMedian){
andrew@0 172 bestSlopeMedian += (bestValue - bestSlopeMedian)*0.04;//was 1.1
andrew@0 173 }
andrew@0 174 else{
andrew@0 175 bestSlopeMedian *= 0.99;
andrew@0 176 slopeFallenBelowMedian = true;;
andrew@0 177 }
andrew@0 178
andrew@0 179 //bestSlopeMedian += 0.02* (bestValue - bestSlopeMedian);
andrew@0 180
andrew@0 181 return onsetDetected;
andrew@0 182 }
andrew@0 183
andrew@0 184 void PeakProcessor :: updateDetectionTriggerThreshold(const float& val){
andrew@0 185 float detectionAdaptSpeed = 0.05;//moving average, roughly last twenty onsets
andrew@0 186 detectionTriggerThreshold *= 1- detectionAdaptSpeed;
andrew@0 187 detectionTriggerThreshold += (val * detectionAdaptSpeed);
andrew@0 188 }