diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BeatTracker.h	Tue Sep 27 18:37:01 2011 +0100
@@ -0,0 +1,207 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+  Vamp feature extraction plugin for the BeatRoot beat tracker.
+
+  Centre for Digital Music, Queen Mary, University of London.
+  This file copyright 2011 Simon Dixon, Chris Cannam and QMUL.
+    
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.  See the file
+  COPYING included with this distribution for more information.
+*/
+
+#ifndef _BEAT_TRACKER_H_
+#define _BEAT_TRACKER_H_
+
+#include "Event.h"
+#include "Agent.h"
+
+using std::vector;
+
+class BeatTracker
+{
+protected:
+    /** beat data encoded as a list of Events */
+    EventList beats;
+	
+    /** a list of onset events for passing to the tempo induction and beat tracking methods */
+    EventList onsetList;
+	
+    /** the times of onsets (in seconds) */
+    vector<double> onsets;
+	
+    /** the times corresponding to each point in the <code>magnitudes</code> array */
+    vector<double> env;
+	
+    /** smoothed amplitude envelope of audio signal */ 
+    vector<int> magnitudes;
+
+public:
+    /** Constructor:
+     *  @param b The list of beats
+     */
+    BeatTracker(EventList b) {
+	beats = b;
+    } // BeatTracker constructor
+
+    /** Creates a new Event object representing a beat.
+     *  @param time The time of the beat in seconds
+     *  @param beatNum The index of the beat
+     *  @return The Event object representing the beat
+     */
+    static Event newBeat(double time, int beatNum) {
+	return Event(time, beatNum, 0);
+    } // newBeat()
+
+    /** Perform beat tracking.
+     *  @param events The onsets or peaks in a feature list
+     *  @return The list of beats, or an empty list if beat tracking fails
+     */
+    static EventList beatTrack(EventList events) {
+	return beatTrack(events, EventList());
+    }
+	
+    /** Perform beat tracking.
+     *  @param events The onsets or peaks in a feature list
+     *  @param beats The initial beats which are given, if any
+     *  @return The list of beats, or an empty list if beat tracking fails
+     */
+    static EventList beatTrack(EventList events, EventList beats) {
+	AgentList agents = null;
+	int count = 0;
+	double beatTime = -1;
+	if (!beats.empty()) {
+	    count = beats.size() - 1;
+	    beatTime = beats.l.getLast().keyDown;
+	}
+	if (count > 0) { // tempo given by mean of initial beats
+	    double ioi = (beatTime - beats.l.getFirst().keyDown) / count;
+	    agents = new AgentList(new Agent(ioi), null);
+	} else									// tempo not given; use tempo induction
+	    agents = Induction.beatInduction(events);
+	if (beats != null)
+	    for (AgentList ptr = agents; ptr.ag != null; ptr = ptr.next) {
+		ptr.ag.beatTime = beatTime;
+		ptr.ag.beatCount = count;
+		ptr.ag.events = new EventList(beats);
+	    }
+	agents.beatTrack(events, -1);
+	Agent best = agents.bestAgent();
+	if (best != null) {
+	    best.fillBeats(beatTime);
+	    return best.events;
+	}
+	return new EventList();
+    } // beatTrack()/1
+	
+    /** Finds the mean tempo (as inter-beat interval) from an array of beat times
+     *  @param d An array of beat times
+     *  @return The average inter-beat interval
+     */
+    static double getAverageIBI(vector<double> d) {
+	if ((d == null) || (d.length < 2))
+	    return -1.0;
+	return (d[d.length - 1] - d[0]) / (d.length - 1);
+    } // getAverageIBI()
+	
+    /** Finds the median tempo (as inter-beat interval) from an array of beat times
+     *  @param d An array of beat times
+     *  @return The median inter-beat interval
+     */
+    static double getMedianIBI(vector<double> d) {
+	if ((d == null) || (d.length < 2))
+	    return -1.0;
+	vector<double> ibi = new double[d.length-1];
+	for (int i = 1; i < d.length; i++)
+	    ibi[i-1] = d[i] - d[i-1];
+	Arrays.sort(ibi);
+	if (ibi.length % 2 == 0)
+	    return (ibi[ibi.length / 2] + ibi[ibi.length / 2 - 1]) / 2;
+	else
+	    return ibi[ibi.length / 2];
+    } // getAverageIBI()
+	
+	
+    // Various get and set methods
+	
+    /** @return the list of beats */
+    EventList getBeats() {
+	return beats;
+    } // getBeats()
+
+    /** @return the array of onset times */
+    vector<double> getOnsets() {
+	return onsets;
+    } // getOnsets()
+
+    /** @return the array of offset times */
+    vector<double> getOffsets() {
+	return offsets;
+    } // getOffsets()
+
+    /** @return the array of MIDI pitches */
+    vector<int> getPitches() {
+	return pitches;
+    } // getPitches()
+
+    /** Sets the onset times as a list of Events, for use by the beat tracking methods. 
+     *  @param on The times of onsets in seconds
+     */
+    void setOnsetList(EventList on) {
+	onsetList = on;
+    } // setOnsetList()
+
+    /** Sets the array of onset times, for displaying MIDI or audio input data.
+     *  @param on The times of onsets in seconds
+     */
+    void setOnsets(vector<double> on) {
+	onsets = on;
+    } // setOnsets()
+
+    /** Sets the array of offset times, for displaying MIDI input data.
+     *  @param off The array of MIDI offset times
+     */
+    void setOffsets(vector<double> off) {
+	offsets = off;
+	// setMode(SHOW_MIDI, SHOW_AUDIO | SHOW_SPECTRO);
+    } // setOffsets()
+
+    /** Sets the array of times of amplitude envelope points, for displaying.
+     *  @param envTimes The array of times in seconds corresponding to the values in <code>magnitudes</code>
+     */
+    void setEnvTimes(vector<double> envTimes) {
+	env = envTimes;
+	setMode(SHOW_AUDIO, SHOW_MIDI);
+    } // setEnvTimes()
+
+    /** Sets the array of magnitude values, for displaying.
+     *  @param mag The array of amplitude envelope values
+     */
+    void setMagnitudes(vector<int> mag) {
+	magnitudes = mag;
+    } // setMagnitudes()
+
+    /** Sets the array of pitch values, for displaying MIDI input data.
+     *  @param p The array of MIDI pitch values
+     */
+    void setPitches(vector<int> p) {
+	pitches = p;
+    } // setPitches()
+
+    /** Sets the list of beats.
+     * @param b The list of beats
+     */
+    void setBeats(EventList b) {
+	beats = b;
+	selectedBeat = null;
+	beatPtr = beats.listIterator();
+    } // setBeats()
+
+}; // class BeatTrackDisplay
+
+
+#endif
+