annotate src/TempoFollower.cpp @ 56:4394c9490716 tip

minor changes
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Mon, 24 Dec 2012 18:58:39 +0000
parents 2eca10a31ae2
children
rev   line source
andrew@19 1 /*
andrew@19 2 * TempoFollower.cpp
andrew@19 3 * MultipleAudioMathcher
andrew@19 4 *
andrew@19 5 * Created by Andrew on 09/02/2012.
andrew@19 6 * Copyright 2012 QMUL. All rights reserved.
andrew@19 7 *
andrew@19 8 */
andrew@19 9
andrew@19 10 #include "TempoFollower.h"
andrew@19 11
andrew@19 12 TempoFollower::TempoFollower(){
andrew@20 13
andrew@20 14
andrew@20 15
andrew@20 16
andrew@19 17 maximumTempoInterval = 600;
andrew@19 18 minimumTempoInterval = 200;
andrew@19 19 tempoArraySize = maximumTempoInterval - minimumTempoInterval;;
andrew@19 20
andrew@19 21 tempoPrior.createVector(tempoArraySize);
andrew@19 22 tempoPosterior.createVector(tempoArraySize);
andrew@19 23 tempoLikelihood.createVector(tempoArraySize);
andrew@19 24
andrew@19 25 tempoPosterior.addConstant(1);
andrew@19 26
andrew@19 27 tempoPrior.offset = minimumTempoInterval;
andrew@19 28 tempoPosterior.offset = minimumTempoInterval;
andrew@19 29 tempoLikelihood.offset = minimumTempoInterval;
andrew@19 30
andrew@19 31 tempoPrior.scalar = 1;
andrew@19 32 tempoPosterior.scalar = 1;
andrew@19 33 tempoLikelihood.scalar = 1;
andrew@20 34
andrew@20 35 intervalsToTest[0] = 1;
andrew@20 36 intervalsToTest[1] = 2;
andrew@20 37 intervalsToTest[2] = 4;
andrew@20 38 intervalsToTest[3] = 8;
andrew@20 39 intervalsToTest[4] = 16;
andrew@20 40
andrew@20 41 setUpEventTimeMatrix();
andrew@19 42 }
andrew@19 43
andrew@20 44 void TempoFollower::zero(){
andrew@20 45 eventTimes.clear();
andrew@20 46 tempoIntervals.clear();
andrew@20 47 divisions.clear();
andrew@20 48 tempo.clear();
andrew@20 49 globalTempo.clear();
andrew@20 50 globalTempoTimes.clear();
andrew@20 51 setUpEventTimeMatrix();
andrew@20 52 }
andrew@19 53
andrew@19 54 void TempoFollower::reset(){
andrew@55 55 printf("reset temporal follower\n");
andrew@19 56 tempoPrior.zero();
andrew@19 57 tempoPosterior.addConstant(1);
andrew@20 58
andrew@19 59 }
andrew@19 60
andrew@19 61
andrew@19 62 void TempoFollower::setUpEventTimeMatrix(){
andrew@19 63 for (int i = 0;i < NUMBER_OF_CHANNELS;i++){
andrew@19 64 IntVector v;
andrew@19 65 eventTimes.push_back(v);
andrew@19 66
andrew@19 67 DoubleMatrix m;
andrew@19 68 tempoIntervals.push_back(m);
andrew@20 69
andrew@20 70 IntMatrix h;
andrew@20 71 divisions.push_back(h);
andrew@20 72
andrew@20 73 DoubleVector d;
andrew@20 74 tempo.push_back(d);
andrew@20 75
andrew@19 76 }
andrew@19 77
andrew@19 78 //[channel][index]
andrew@19 79 }
andrew@19 80
andrew@19 81
andrew@19 82
andrew@19 83 void TempoFollower::printEventTimes(){
andrew@19 84 for (int i = 0;i < NUMBER_OF_CHANNELS;i++){
andrew@19 85 printf("CHANNEL %i EVENT TIMES...\n", i);
andrew@19 86 for (int j = 0;j < eventTimes[i].size();j++)
andrew@19 87 printf("%i\n", eventTimes[i][j]);
andrew@19 88 }
andrew@19 89 }
andrew@19 90
andrew@19 91
andrew@20 92 void TempoFollower::printTempoTimes(){
andrew@20 93
andrew@20 94 for (int i = 0;i < globalTempo.size();i++){
andrew@20 95 printf("Time %i : tempo %f\n", globalTempoTimes[i], globalTempo[i]);
andrew@20 96 }
andrew@20 97 }
andrew@20 98
andrew@19 99 void TempoFollower::updateTempo(const int& channel, const int& timeIn){
andrew@19 100
andrew@19 101 eventTimes[channel].push_back(timeIn);
andrew@19 102
andrew@19 103 int interval = 0;
andrew@19 104 int intervalLimit = 3600;
andrew@19 105
andrew@19 106 int recentIndex = eventTimes[channel].size()-1;
andrew@19 107
andrew@19 108 DoubleVector d;
andrew@20 109 IntVector div;
andrew@19 110 int recentEvent = eventTimes[channel][recentIndex];
andrew@19 111
andrew@19 112 for (int i = 1;i < eventTimes[channel].size() && interval < intervalLimit;i++){
andrew@19 113 interval = eventTimes[channel][recentIndex] - eventTimes[channel][recentIndex - i];
andrew@19 114
andrew@20 115 for (int k = 0;k < 3;k++){
andrew@19 116
andrew@20 117 double divisionInEighthNotes = intervalsToTest[k];
andrew@19 118 double testInterval = interval / divisionInEighthNotes;
andrew@20 119 if (testTempoInterval(channel, testInterval, d)){
andrew@55 120 printf("channel %i interval %i at division %.0f == tempo update %f\n", channel, interval, divisionInEighthNotes, testInterval);
andrew@20 121 div.push_back((int)divisionInEighthNotes);
andrew@20 122 }
andrew@19 123 }
andrew@19 124 }
andrew@19 125
andrew@19 126 (tempoIntervals[channel]).push_back(d);
andrew@20 127 (divisions[channel]).push_back(div);
andrew@19 128 updateTempoDistribution(d);
andrew@19 129
andrew@20 130 tempo[channel].push_back(playingTempo);
andrew@20 131
andrew@20 132 globalTempo.push_back(playingTempo);
andrew@20 133 globalTempoTimes.push_back(timeIn);
andrew@20 134
andrew@20 135
andrew@19 136 }
andrew@19 137
andrew@19 138
andrew@19 139 bool TempoFollower::testTempoInterval(const int& channel, const double& testInterval, DoubleVector& d){
andrew@19 140
andrew@19 141 bool updated = false;
andrew@19 142 if (testInterval >= minimumTempoInterval && testInterval <= maximumTempoInterval){
andrew@19 143 d.push_back(testInterval);
andrew@19 144 updated = true;
andrew@19 145 }
andrew@19 146 return updated;
andrew@19 147 }
andrew@19 148
andrew@19 149 void TempoFollower::updateTempoDistribution(const DoubleVector& d){
andrew@19 150 double tempoLikelihoodToNoiseRatio = 0.8;
andrew@20 151 tempoLikelihoodStdDev = 4;
andrew@20 152
andrew@19 153 tempoLikelihood.zero();
andrew@19 154 double amount = tempoLikelihoodToNoiseRatio/d.size();
andrew@19 155 for (int i = 0;i < d.size();i++){
andrew@20 156 tempoLikelihood.addGaussianShapeFromRealTime(d[i], tempoLikelihoodStdDev, amount);
andrew@19 157 }
andrew@19 158 tempoLikelihood.addConstant(0.1*(1-tempoLikelihoodToNoiseRatio));
andrew@19 159 calculatePosterior();
andrew@19 160 tempoPosterior.renormalise();
andrew@19 161 playingTempo = tempoPosterior.getIndexInRealTerms(tempoPosterior.getMAPestimate());
andrew@20 162
andrew@19 163 }
andrew@19 164
andrew@19 165
andrew@19 166
andrew@19 167 void TempoFollower::calculatePosterior(){
andrew@19 168 tempoPrior.copyFromDynamicVector(tempoPosterior);
andrew@19 169 for (int i = 0;i < tempoArraySize;i++){
andrew@19 170 tempoPosterior.array[i] = tempoLikelihood.array[i] * tempoPrior.array[i];
andrew@19 171 }
andrew@19 172 }
andrew@19 173
andrew@19 174 void TempoFollower::drawTempoArray(ofxWindowRegion& window){
andrew@19 175 ofSetColor(150,0,250);
andrew@19 176 tempoPosterior.drawConstrainedVector(0, tempoArraySize, 0, ofGetWidth(), window);
andrew@20 177
andrew@20 178 ofSetColor(150,150,150);
andrew@20 179 tempoLikelihood.drawConstrainedVector(0, tempoArraySize, 0, ofGetWidth(), window);
andrew@20 180
andrew@50 181 if (printOutput)
andrew@19 182 ofDrawBitmapString("tempo "+ofToString(playingTempo), window.x+ 20, window.y + 40);
andrew@20 183
andrew@20 184
andrew@20 185 for (int channel = 0;channel < 3;channel+=2){
andrew@20 186 int index = tempoIntervals[channel].size()-1;
andrew@20 187
andrew@20 188 for (int i = 0;i < 9 && index - i>=0 ;i++){
andrew@20 189 for (int j = 0;j < tempoIntervals[channel][index - i].size();j++){
andrew@20 190 ofSetColor(channel*125, 0, 250);
andrew@20 191 ofCircle(window.x+((tempoIntervals[channel][index - i][j] - minimumTempoInterval)*window.width)/tempoArraySize, window.y+6+(window.height*i/9.0), 4);
andrew@20 192 ofSetColor(255,255,255);
andrew@20 193 ofDrawBitmapString(ofToString(divisions[channel][index-i][j]), (window.x+((tempoIntervals[channel][index - i][j] - minimumTempoInterval)*window.width)/tempoArraySize)-3, window.y+8+(window.height*i/9.0));
andrew@20 194 }
andrew@20 195 }
andrew@20 196 }
andrew@19 197 }
andrew@20 198