To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

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