comparison src/TempoFollower.cpp @ 20:4f6006cac9de

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