comparison src/TempoFollower.cpp @ 19:1a62561bd72d

Added in tempo follower class that models the tempo of played events
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Thu, 09 Feb 2012 18:09:34 +0000
parents
children 4f6006cac9de
comparison
equal deleted inserted replaced
18:4ded82fe318d 19:1a62561bd72d
1 /*
2 * TempoFollower.cpp
3 * MultipleAudioMathcher
4 *
5 * Created by Andrew on 09/02/2012.
6 * Copyright 2012 QMUL. All rights reserved.
7 *
8 */
9
10 #include "TempoFollower.h"
11
12 TempoFollower::TempoFollower(){
13 maximumTempoInterval = 600;
14 minimumTempoInterval = 200;
15 tempoArraySize = maximumTempoInterval - minimumTempoInterval;;
16
17 tempoPrior.createVector(tempoArraySize);
18 tempoPosterior.createVector(tempoArraySize);
19 tempoLikelihood.createVector(tempoArraySize);
20
21 tempoPosterior.addConstant(1);
22
23 tempoPrior.offset = minimumTempoInterval;
24 tempoPosterior.offset = minimumTempoInterval;
25 tempoLikelihood.offset = minimumTempoInterval;
26
27 tempoPrior.scalar = 1;
28 tempoPosterior.scalar = 1;
29 tempoLikelihood.scalar = 1;
30 }
31
32
33 void TempoFollower::reset(){
34
35 tempoPrior.zero();
36 tempoPosterior.addConstant(1);
37 }
38
39
40 void TempoFollower::setUpEventTimeMatrix(){
41 for (int i = 0;i < NUMBER_OF_CHANNELS;i++){
42 IntVector v;
43 eventTimes.push_back(v);
44
45 DoubleMatrix m;
46 tempoIntervals.push_back(m);
47 }
48
49 //[channel][index]
50 }
51
52
53
54 void TempoFollower::printEventTimes(){
55 for (int i = 0;i < NUMBER_OF_CHANNELS;i++){
56 printf("CHANNEL %i EVENT TIMES...\n", i);
57 for (int j = 0;j < eventTimes[i].size();j++)
58 printf("%i\n", eventTimes[i][j]);
59 }
60 }
61
62
63 void TempoFollower::updateTempo(const int& channel, const int& timeIn){
64
65 eventTimes[channel].push_back(timeIn);
66
67 int interval = 0;
68 int intervalLimit = 3600;
69
70 int recentIndex = eventTimes[channel].size()-1;
71
72 DoubleVector d;
73
74 int recentEvent = eventTimes[channel][recentIndex];
75
76 for (int i = 1;i < eventTimes[channel].size() && interval < intervalLimit;i++){
77 interval = eventTimes[channel][recentIndex] - eventTimes[channel][recentIndex - i];
78
79 if (testTempoInterval(channel, interval, d))
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
84 double testInterval = interval / divisionInEighthNotes;
85 if (testTempoInterval(channel, testInterval, d))
86 printf("channel %i interval %i at division %.0f == tempo update %f\n", channel, interval, divisionInEighthNotes, testInterval);
87
88 }
89 }
90
91 (tempoIntervals[channel]).push_back(d);
92 updateTempoDistribution(d);
93
94 }
95
96
97 bool TempoFollower::testTempoInterval(const int& channel, const double& testInterval, DoubleVector& d){
98
99 bool updated = false;
100 if (testInterval >= minimumTempoInterval && testInterval <= maximumTempoInterval){
101 d.push_back(testInterval);
102 updated = true;
103 }
104 return updated;
105 }
106
107 void TempoFollower::updateTempoDistribution(const DoubleVector& d){
108 double tempoLikelihoodToNoiseRatio = 0.8;
109 tempoLikelihood.zero();
110 double amount = tempoLikelihoodToNoiseRatio/d.size();
111 for (int i = 0;i < d.size();i++){
112 tempoLikelihood.addGaussianShapeFromRealTime(d[i], 10, amount);
113 }
114 tempoLikelihood.addConstant(0.1*(1-tempoLikelihoodToNoiseRatio));
115 calculatePosterior();
116
117 tempoPosterior.renormalise();
118 playingTempo = tempoPosterior.getIndexInRealTerms(tempoPosterior.getMAPestimate());
119 }
120
121
122
123 void TempoFollower::calculatePosterior(){
124 tempoPrior.copyFromDynamicVector(tempoPosterior);
125 for (int i = 0;i < tempoArraySize;i++){
126 tempoPosterior.array[i] = tempoLikelihood.array[i] * tempoPrior.array[i];
127 }
128 }
129
130 void TempoFollower::drawTempoArray(ofxWindowRegion& window){
131 ofSetColor(150,0,250);
132 tempoPosterior.drawConstrainedVector(0, tempoArraySize, 0, ofGetWidth(), window);
133 ofDrawBitmapString("tempo "+ofToString(playingTempo), window.x+ 20, window.y + 40);
134 }