To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
root / Agent.h
History | View | Annotate | Download (7.69 KB)
| 1 | 6:02d388f98c23 | Chris | /* -*- 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 _AGENT_H_
|
||
| 17 | #define _AGENT_H_
|
||
| 18 | |||
| 19 | #include "Event.h" |
||
| 20 | |||
| 21 | 9:4f6626f9ffac | Chris | #include <cmath> |
| 22 | |||
| 23 | 12:59520cd6abac | Chris | #ifdef DEBUG_BEATROOT
|
| 24 | #include <iostream> |
||
| 25 | #endif
|
||
| 26 | |||
| 27 | 8:f04f87b5e643 | Chris | class AgentList; |
| 28 | |||
| 29 | 23:633ec097fa56 | Chris | class AgentParameters |
| 30 | {
|
||
| 31 | public:
|
||
| 32 | static const double DEFAULT_POST_MARGIN_FACTOR; |
||
| 33 | static const double DEFAULT_PRE_MARGIN_FACTOR; |
||
| 34 | static const double DEFAULT_MAX_CHANGE; |
||
| 35 | static const double DEFAULT_EXPIRY_TIME; |
||
| 36 | |||
| 37 | AgentParameters() : |
||
| 38 | postMarginFactor(DEFAULT_POST_MARGIN_FACTOR), |
||
| 39 | preMarginFactor(DEFAULT_PRE_MARGIN_FACTOR), |
||
| 40 | maxChange(DEFAULT_MAX_CHANGE), |
||
| 41 | expiryTime(DEFAULT_EXPIRY_TIME) { }
|
||
| 42 | |||
| 43 | /** The maximum amount by which a beat can be later than the
|
||
| 44 | * predicted beat time, expressed as a fraction of the beat
|
||
| 45 | * period. */
|
||
| 46 | double postMarginFactor;
|
||
| 47 | |||
| 48 | /** The maximum amount by which a beat can be earlier than the
|
||
| 49 | * predicted beat time, expressed as a fraction of the beat
|
||
| 50 | * period. */
|
||
| 51 | double preMarginFactor;
|
||
| 52 | |||
| 53 | /** The maximum allowed deviation from the initial tempo,
|
||
| 54 | * expressed as a fraction of the initial beat period. */
|
||
| 55 | double maxChange;
|
||
| 56 | |||
| 57 | /** The default value of expiryTime, which is the time (in
|
||
| 58 | * seconds) after which an Agent that has no Event matching its
|
||
| 59 | * beat predictions will be destroyed. */
|
||
| 60 | double expiryTime;
|
||
| 61 | }; |
||
| 62 | |||
| 63 | 6:02d388f98c23 | Chris | /** Agent is the central class for beat tracking.
|
| 64 | * Each Agent object has a tempo hypothesis, a history of tracked beats, and
|
||
| 65 | * a score evaluating the continuity, regularity and salience of its beat track.
|
||
| 66 | */
|
||
| 67 | class Agent |
||
| 68 | {
|
||
| 69 | public:
|
||
| 70 | 23:633ec097fa56 | Chris | /** The default value of innerMargin, which is the maximum time
|
| 71 | * (in seconds) that a beat can deviate from the predicted beat
|
||
| 72 | * time without a fork occurring. */
|
||
| 73 | 6:02d388f98c23 | Chris | static const double INNER_MARGIN; |
| 74 | |||
| 75 | 23:633ec097fa56 | Chris | /** The slope of the penalty function for onsets which do not
|
| 76 | * coincide precisely with predicted beat times. */
|
||
| 77 | static const double CONF_FACTOR; |
||
| 78 | 6:02d388f98c23 | Chris | |
| 79 | 23:633ec097fa56 | Chris | /** The reactiveness/inertia balance, i.e. degree of change in the
|
| 80 | * tempo, is controlled by the correctionFactor variable. This
|
||
| 81 | * constant defines its default value, which currently is not
|
||
| 82 | * subsequently changed. The beat period is updated by the
|
||
| 83 | * reciprocal of the correctionFactor multiplied by the
|
||
| 84 | * difference between the predicted beat time and matching
|
||
| 85 | * onset. */
|
||
| 86 | 6:02d388f98c23 | Chris | static const double DEFAULT_CORRECTION_FACTOR; |
| 87 | |||
| 88 | protected:
|
||
| 89 | /** The identity number of the next created Agent */
|
||
| 90 | static int idCounter; |
||
| 91 | |||
| 92 | 23:633ec097fa56 | Chris | /** The maximum time (in seconds) that a beat can deviate from the
|
| 93 | * predicted beat time without a fork occurring (i.e. a 2nd Agent
|
||
| 94 | * being created). */
|
||
| 95 | double innerMargin;
|
||
| 96 | 6:02d388f98c23 | Chris | |
| 97 | 23:633ec097fa56 | Chris | /** Controls the reactiveness/inertia balance, i.e. degree of
|
| 98 | * change in the tempo. The beat period is updated by the
|
||
| 99 | * reciprocal of the correctionFactor multiplied by the
|
||
| 100 | * difference between the predicted beat time and matching
|
||
| 101 | * onset. */
|
||
| 102 | double correctionFactor;
|
||
| 103 | 6:02d388f98c23 | Chris | |
| 104 | 23:633ec097fa56 | Chris | /** The time (in seconds) after which an Agent that has no Event
|
| 105 | * matching its beat predictions will be destroyed. */
|
||
| 106 | double expiryTime;
|
||
| 107 | 6:02d388f98c23 | Chris | |
| 108 | 23:633ec097fa56 | Chris | /** For scoring Agents in a (non-existent) real-time version
|
| 109 | * (otherwise not used). */
|
||
| 110 | double decayFactor;
|
||
| 111 | 6:02d388f98c23 | Chris | |
| 112 | public:
|
||
| 113 | /** The size of the outer half-window before the predicted beat time. */
|
||
| 114 | double preMargin;
|
||
| 115 | |||
| 116 | /** The size of the outer half-window after the predicted beat time. */
|
||
| 117 | double postMargin;
|
||
| 118 | |||
| 119 | /** The Agent's unique identity number. */
|
||
| 120 | int idNumber;
|
||
| 121 | |||
| 122 | /** To be used in real-time version?? */
|
||
| 123 | double tempoScore;
|
||
| 124 | |||
| 125 | 23:633ec097fa56 | Chris | /** Sum of salience values of the Events which have been
|
| 126 | * interpreted as beats by this Agent, weighted by their nearness
|
||
| 127 | * to the predicted beat times. */
|
||
| 128 | 6:02d388f98c23 | Chris | double phaseScore;
|
| 129 | |||
| 130 | 23:633ec097fa56 | Chris | /** How long has this agent been the best? For real-time version;
|
| 131 | * otherwise not used. */
|
||
| 132 | 6:02d388f98c23 | Chris | double topScoreTime;
|
| 133 | |||
| 134 | 23:633ec097fa56 | Chris | /** The number of beats found by this Agent, including
|
| 135 | * interpolated beats. */
|
||
| 136 | 6:02d388f98c23 | Chris | int beatCount;
|
| 137 | |||
| 138 | 23:633ec097fa56 | Chris | /** The current tempo hypothesis of the Agent, expressed as the
|
| 139 | * beat period in seconds. */
|
||
| 140 | 6:02d388f98c23 | Chris | double beatInterval;
|
| 141 | |||
| 142 | 23:633ec097fa56 | Chris | /** The initial tempo hypothesis of the Agent, expressed as the
|
| 143 | * beat period in seconds. */
|
||
| 144 | 6:02d388f98c23 | Chris | double initialBeatInterval;
|
| 145 | |||
| 146 | /** The time of the most recent beat accepted by this Agent. */
|
||
| 147 | double beatTime;
|
||
| 148 | 23:633ec097fa56 | Chris | |
| 149 | /** The maximum allowed deviation from the initial tempo,
|
||
| 150 | * expressed as a fraction of the initial beat period. */
|
||
| 151 | double maxChange;
|
||
| 152 | 6:02d388f98c23 | Chris | |
| 153 | 23:633ec097fa56 | Chris | /** The list of Events (onsets) accepted by this Agent as beats,
|
| 154 | * plus interpolated beats. */
|
||
| 155 | 6:02d388f98c23 | Chris | EventList events; |
| 156 | |||
| 157 | /** Constructor: the work is performed by init()
|
||
| 158 | * @param ibi The beat period (inter-beat interval) of the Agent's tempo hypothesis.
|
||
| 159 | */
|
||
| 160 | 23:633ec097fa56 | Chris | Agent(AgentParameters params, double ibi) :
|
| 161 | innerMargin(INNER_MARGIN), |
||
| 162 | correctionFactor(DEFAULT_CORRECTION_FACTOR), |
||
| 163 | expiryTime(params.expiryTime), |
||
| 164 | decayFactor(0),
|
||
| 165 | preMargin(ibi * params.preMarginFactor), |
||
| 166 | postMargin(ibi * params.postMarginFactor), |
||
| 167 | idNumber(idCounter++), |
||
| 168 | tempoScore(0.0), |
||
| 169 | phaseScore(0.0), |
||
| 170 | topScoreTime(0.0), |
||
| 171 | beatCount(0),
|
||
| 172 | beatInterval(ibi), |
||
| 173 | initialBeatInterval(ibi), |
||
| 174 | beatTime(-1.0), |
||
| 175 | maxChange(params.maxChange) {
|
||
| 176 | 12:59520cd6abac | Chris | } // constructor
|
| 177 | 6:02d388f98c23 | Chris | |
| 178 | 16:33d0b18b2509 | Chris | Agent *clone() const {
|
| 179 | Agent *a = new Agent(*this); |
||
| 180 | a->idNumber = idCounter++; |
||
| 181 | 12:59520cd6abac | Chris | return a;
|
| 182 | } |
||
| 183 | 6:02d388f98c23 | Chris | |
| 184 | 12:59520cd6abac | Chris | protected:
|
| 185 | 6:02d388f98c23 | Chris | double threshold(double value, double min, double max) { |
| 186 | if (value < min)
|
||
| 187 | return min;
|
||
| 188 | if (value > max)
|
||
| 189 | return max;
|
||
| 190 | return value;
|
||
| 191 | } |
||
| 192 | |||
| 193 | 8:f04f87b5e643 | Chris | public:
|
| 194 | 6:02d388f98c23 | Chris | /** Accept a new Event as a beat time, and update the state of the Agent accordingly.
|
| 195 | * @param e The Event which is accepted as being on the beat.
|
||
| 196 | * @param err The difference between the predicted and actual beat times.
|
||
| 197 | * @param beats The number of beats since the last beat that matched an Event.
|
||
| 198 | */
|
||
| 199 | 15:887c629502a9 | Chris | void accept(Event e, double err, int beats); |
| 200 | 6:02d388f98c23 | Chris | |
| 201 | /** The given Event is tested for a possible beat time. The following situations can occur:
|
||
| 202 | * 1) The Agent has no beats yet; the Event is accepted as the first beat.
|
||
| 203 | * 2) The Event is beyond expiryTime seconds after the Agent's last 'confirming' beat; the Agent is terminated.
|
||
| 204 | * 3) The Event is within the innerMargin of the beat prediction; it is accepted as a beat.
|
||
| 205 | 9:4f6626f9ffac | Chris | * 4) The Event is within the postMargin's of the beat prediction; it is accepted as a beat by this Agent,
|
| 206 | 6:02d388f98c23 | Chris | * and a new Agent is created which doesn't accept it as a beat.
|
| 207 | * 5) The Event is ignored because it is outside the windows around the Agent's predicted beat time.
|
||
| 208 | * @param e The Event to be tested
|
||
| 209 | * @param a The list of all agents, which is updated if a new agent is created.
|
||
| 210 | * @return Indicate whether the given Event was accepted as a beat by this Agent.
|
||
| 211 | */
|
||
| 212 | 8:f04f87b5e643 | Chris | bool considerAsBeat(Event e, AgentList &a);
|
| 213 | 6:02d388f98c23 | Chris | |
| 214 | /** Interpolates missing beats in the Agent's beat track, starting from the beginning of the piece. */
|
||
| 215 | void fillBeats() {
|
||
| 216 | fillBeats(-1.0); |
||
| 217 | } // fillBeats()/0
|
||
| 218 | |||
| 219 | /** Interpolates missing beats in the Agent's beat track.
|
||
| 220 | * @param start Ignore beats earlier than this start time
|
||
| 221 | */
|
||
| 222 | void fillBeats(double start); |
||
| 223 | |||
| 224 | }; // class Agent
|
||
| 225 | |||
| 226 | #endif |