Mercurial > hg > beatroot-vamp
comparison BeatTracker.h @ 6:02d388f98c23
Introduce a number of new classes derived from the Java
author | Chris Cannam |
---|---|
date | Tue, 27 Sep 2011 18:37:01 +0100 |
parents | |
children | 3c11becfc81a |
comparison
equal
deleted
inserted
replaced
5:2150607d4726 | 6:02d388f98c23 |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Vamp feature extraction plugin for the BeatRoot beat tracker. | |
5 | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 This file copyright 2011 Simon Dixon, Chris Cannam and QMUL. | |
8 | |
9 This program is free software; you can redistribute it and/or | |
10 modify it under the terms of the GNU General Public License as | |
11 published by the Free Software Foundation; either version 2 of the | |
12 License, or (at your option) any later version. See the file | |
13 COPYING included with this distribution for more information. | |
14 */ | |
15 | |
16 #ifndef _BEAT_TRACKER_H_ | |
17 #define _BEAT_TRACKER_H_ | |
18 | |
19 #include "Event.h" | |
20 #include "Agent.h" | |
21 | |
22 using std::vector; | |
23 | |
24 class BeatTracker | |
25 { | |
26 protected: | |
27 /** beat data encoded as a list of Events */ | |
28 EventList beats; | |
29 | |
30 /** a list of onset events for passing to the tempo induction and beat tracking methods */ | |
31 EventList onsetList; | |
32 | |
33 /** the times of onsets (in seconds) */ | |
34 vector<double> onsets; | |
35 | |
36 /** the times corresponding to each point in the <code>magnitudes</code> array */ | |
37 vector<double> env; | |
38 | |
39 /** smoothed amplitude envelope of audio signal */ | |
40 vector<int> magnitudes; | |
41 | |
42 public: | |
43 /** Constructor: | |
44 * @param b The list of beats | |
45 */ | |
46 BeatTracker(EventList b) { | |
47 beats = b; | |
48 } // BeatTracker constructor | |
49 | |
50 /** Creates a new Event object representing a beat. | |
51 * @param time The time of the beat in seconds | |
52 * @param beatNum The index of the beat | |
53 * @return The Event object representing the beat | |
54 */ | |
55 static Event newBeat(double time, int beatNum) { | |
56 return Event(time, beatNum, 0); | |
57 } // newBeat() | |
58 | |
59 /** Perform beat tracking. | |
60 * @param events The onsets or peaks in a feature list | |
61 * @return The list of beats, or an empty list if beat tracking fails | |
62 */ | |
63 static EventList beatTrack(EventList events) { | |
64 return beatTrack(events, EventList()); | |
65 } | |
66 | |
67 /** Perform beat tracking. | |
68 * @param events The onsets or peaks in a feature list | |
69 * @param beats The initial beats which are given, if any | |
70 * @return The list of beats, or an empty list if beat tracking fails | |
71 */ | |
72 static EventList beatTrack(EventList events, EventList beats) { | |
73 AgentList agents = null; | |
74 int count = 0; | |
75 double beatTime = -1; | |
76 if (!beats.empty()) { | |
77 count = beats.size() - 1; | |
78 beatTime = beats.l.getLast().keyDown; | |
79 } | |
80 if (count > 0) { // tempo given by mean of initial beats | |
81 double ioi = (beatTime - beats.l.getFirst().keyDown) / count; | |
82 agents = new AgentList(new Agent(ioi), null); | |
83 } else // tempo not given; use tempo induction | |
84 agents = Induction.beatInduction(events); | |
85 if (beats != null) | |
86 for (AgentList ptr = agents; ptr.ag != null; ptr = ptr.next) { | |
87 ptr.ag.beatTime = beatTime; | |
88 ptr.ag.beatCount = count; | |
89 ptr.ag.events = new EventList(beats); | |
90 } | |
91 agents.beatTrack(events, -1); | |
92 Agent best = agents.bestAgent(); | |
93 if (best != null) { | |
94 best.fillBeats(beatTime); | |
95 return best.events; | |
96 } | |
97 return new EventList(); | |
98 } // beatTrack()/1 | |
99 | |
100 /** Finds the mean tempo (as inter-beat interval) from an array of beat times | |
101 * @param d An array of beat times | |
102 * @return The average inter-beat interval | |
103 */ | |
104 static double getAverageIBI(vector<double> d) { | |
105 if ((d == null) || (d.length < 2)) | |
106 return -1.0; | |
107 return (d[d.length - 1] - d[0]) / (d.length - 1); | |
108 } // getAverageIBI() | |
109 | |
110 /** Finds the median tempo (as inter-beat interval) from an array of beat times | |
111 * @param d An array of beat times | |
112 * @return The median inter-beat interval | |
113 */ | |
114 static double getMedianIBI(vector<double> d) { | |
115 if ((d == null) || (d.length < 2)) | |
116 return -1.0; | |
117 vector<double> ibi = new double[d.length-1]; | |
118 for (int i = 1; i < d.length; i++) | |
119 ibi[i-1] = d[i] - d[i-1]; | |
120 Arrays.sort(ibi); | |
121 if (ibi.length % 2 == 0) | |
122 return (ibi[ibi.length / 2] + ibi[ibi.length / 2 - 1]) / 2; | |
123 else | |
124 return ibi[ibi.length / 2]; | |
125 } // getAverageIBI() | |
126 | |
127 | |
128 // Various get and set methods | |
129 | |
130 /** @return the list of beats */ | |
131 EventList getBeats() { | |
132 return beats; | |
133 } // getBeats() | |
134 | |
135 /** @return the array of onset times */ | |
136 vector<double> getOnsets() { | |
137 return onsets; | |
138 } // getOnsets() | |
139 | |
140 /** @return the array of offset times */ | |
141 vector<double> getOffsets() { | |
142 return offsets; | |
143 } // getOffsets() | |
144 | |
145 /** @return the array of MIDI pitches */ | |
146 vector<int> getPitches() { | |
147 return pitches; | |
148 } // getPitches() | |
149 | |
150 /** Sets the onset times as a list of Events, for use by the beat tracking methods. | |
151 * @param on The times of onsets in seconds | |
152 */ | |
153 void setOnsetList(EventList on) { | |
154 onsetList = on; | |
155 } // setOnsetList() | |
156 | |
157 /** Sets the array of onset times, for displaying MIDI or audio input data. | |
158 * @param on The times of onsets in seconds | |
159 */ | |
160 void setOnsets(vector<double> on) { | |
161 onsets = on; | |
162 } // setOnsets() | |
163 | |
164 /** Sets the array of offset times, for displaying MIDI input data. | |
165 * @param off The array of MIDI offset times | |
166 */ | |
167 void setOffsets(vector<double> off) { | |
168 offsets = off; | |
169 // setMode(SHOW_MIDI, SHOW_AUDIO | SHOW_SPECTRO); | |
170 } // setOffsets() | |
171 | |
172 /** Sets the array of times of amplitude envelope points, for displaying. | |
173 * @param envTimes The array of times in seconds corresponding to the values in <code>magnitudes</code> | |
174 */ | |
175 void setEnvTimes(vector<double> envTimes) { | |
176 env = envTimes; | |
177 setMode(SHOW_AUDIO, SHOW_MIDI); | |
178 } // setEnvTimes() | |
179 | |
180 /** Sets the array of magnitude values, for displaying. | |
181 * @param mag The array of amplitude envelope values | |
182 */ | |
183 void setMagnitudes(vector<int> mag) { | |
184 magnitudes = mag; | |
185 } // setMagnitudes() | |
186 | |
187 /** Sets the array of pitch values, for displaying MIDI input data. | |
188 * @param p The array of MIDI pitch values | |
189 */ | |
190 void setPitches(vector<int> p) { | |
191 pitches = p; | |
192 } // setPitches() | |
193 | |
194 /** Sets the list of beats. | |
195 * @param b The list of beats | |
196 */ | |
197 void setBeats(EventList b) { | |
198 beats = b; | |
199 selectedBeat = null; | |
200 beatPtr = beats.listIterator(); | |
201 } // setBeats() | |
202 | |
203 }; // class BeatTrackDisplay | |
204 | |
205 | |
206 #endif | |
207 |