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