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 @ 23:633ec097fa56

History | View | Annotate | Download (7.69 KB)

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 _AGENT_H_
17
#define _AGENT_H_
18

    
19
#include "Event.h"
20

    
21
#include <cmath>
22

    
23
#ifdef DEBUG_BEATROOT
24
#include <iostream>
25
#endif
26

    
27
class AgentList;
28

    
29
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
/** 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
    /** 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
    static const double INNER_MARGIN;
74
        
75
    /** 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
        
79
    /** 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
    static const double DEFAULT_CORRECTION_FACTOR;
87
        
88
protected:
89
    /** The identity number of the next created Agent */
90
    static int idCounter;
91
        
92
    /** 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

    
97
    /** 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

    
104
    /** The time (in seconds) after which an Agent that has no Event
105
     *  matching its beat predictions will be destroyed. */
106
    double expiryTime;
107
        
108
    /** For scoring Agents in a (non-existent) real-time version
109
     * (otherwise not used). */
110
    double decayFactor;
111

    
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
    /** 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
    double phaseScore;
129
        
130
    /** How long has this agent been the best?  For real-time version;
131
     * otherwise not used. */
132
    double topScoreTime;
133
        
134
    /** The number of beats found by this Agent, including
135
     * interpolated beats. */
136
    int beatCount;
137
        
138
    /** The current tempo hypothesis of the Agent, expressed as the
139
     * beat period in seconds. */
140
    double beatInterval;
141

    
142
    /** The initial tempo hypothesis of the Agent, expressed as the
143
     * beat period in seconds. */
144
    double initialBeatInterval;
145
        
146
    /** The time of the most recent beat accepted by this Agent. */
147
    double beatTime;
148

    
149
    /** The maximum allowed deviation from the initial tempo,
150
     * expressed as a fraction of the initial beat period. */
151
    double maxChange;
152
        
153
    /** The list of Events (onsets) accepted by this Agent as beats,
154
     * plus interpolated beats. */
155
    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
    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
    } // constructor
177

    
178
    Agent *clone() const {
179
        Agent *a = new Agent(*this);
180
        a->idNumber = idCounter++;
181
        return a;
182
    }
183

    
184
protected:
185
    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
public:
194
    /** 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
    void accept(Event e, double err, int beats);
200

    
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
     *  4) The Event is within the postMargin's of the beat prediction; it is accepted as a beat by this Agent,
206
     *     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
    bool considerAsBeat(Event e, AgentList &a);
213

    
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