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 @ 22:6afcb5edd7ab

History | View | Annotate | Download (7 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
/** Agent is the central class for beat tracking.
30
 *  Each Agent object has a tempo hypothesis, a history of tracked beats, and
31
 *  a score evaluating the continuity, regularity and salience of its beat track.
32
 */
33
class Agent
34
{
35
public:
36
    /** The maximum amount by which a beat can be later than the predicted beat time,
37
     *  expressed as a fraction of the beat period. */
38
    static double POST_MARGIN_FACTOR;
39

    
40
    /** The maximum amount by which a beat can be earlier than the predicted beat time,
41
     *  expressed as a fraction of the beat period. */
42
    static double PRE_MARGIN_FACTOR;
43
        
44
    /** The default value of innerMargin, which is the maximum time (in seconds) that a
45
     *         beat can deviate from the predicted beat time without a fork occurring. */
46
    static const double INNER_MARGIN;
47
        
48
    /** The maximum allowed deviation from the initial tempo, expressed as a fraction of the initial beat period. */
49
    static double MAX_CHANGE;
50
                
51
    /** The slope of the penalty function for onsets which do not coincide precisely with predicted beat times. */
52
    static double CONF_FACTOR;
53
        
54
    /** The reactiveness/inertia balance, i.e. degree of change in the tempo, is controlled by the correctionFactor
55
     *  variable.  This constant defines its default value, which currently is not subsequently changed. The
56
     *  beat period is updated by the reciprocal of the correctionFactor multiplied by the difference between the
57
     *  predicted beat time and matching onset. */
58
    static const double DEFAULT_CORRECTION_FACTOR;
59
        
60
    /** The default value of expiryTime, which is the time (in seconds) after which an Agent that
61
     *  has no Event matching its beat predictions will be destroyed. */
62
    static const double DEFAULT_EXPIRY_TIME;
63

    
64
protected:
65
    /** The identity number of the next created Agent */
66
    static int idCounter;
67
        
68
    /** The maximum time (in seconds) that a beat can deviate from the predicted beat time
69
     *  without a fork occurring (i.e. a 2nd Agent being created). */
70
    static double innerMargin;
71

    
72
    /** Controls the reactiveness/inertia balance, i.e. degree of change in the tempo.  The
73
     *  beat period is updated by the reciprocal of the correctionFactor multiplied by the difference between the
74
     *  predicted beat time and matching onset. */
75
    static double correctionFactor;
76

    
77
    /** The time (in seconds) after which an Agent that
78
     *  has no Event matching its beat predictions will be destroyed. */
79
    static double expiryTime;
80
        
81
    /** For scoring Agents in a (non-existent) real-time version (otherwise not used). */
82
    static double decayFactor;
83

    
84
public:
85
    /** The size of the outer half-window before the predicted beat time. */
86
    double preMargin;
87

    
88
    /** The size of the outer half-window after the predicted beat time. */
89
    double postMargin;
90
        
91
    /** The Agent's unique identity number. */
92
    int idNumber;
93
        
94
    /** To be used in real-time version?? */
95
    double tempoScore;
96
        
97
    /** Sum of salience values of the Events which have been interpreted
98
     *  as beats by this Agent, weighted by their nearness to the predicted beat times. */
99
    double phaseScore;
100
        
101
    /** How long has this agent been the best?  For real-time version; otherwise not used. */
102
    double topScoreTime;
103
        
104
    /** The number of beats found by this Agent, including interpolated beats. */
105
    int beatCount;
106
        
107
    /** The current tempo hypothesis of the Agent, expressed as the beat period in seconds. */
108
    double beatInterval;
109

    
110
    /** The initial tempo hypothesis of the Agent, expressed as the beat period in seconds. */
111
    double initialBeatInterval;
112
        
113
    /** The time of the most recent beat accepted by this Agent. */
114
    double beatTime;
115
        
116
    /** The list of Events (onsets) accepted by this Agent as beats, plus interpolated beats. */
117
    EventList events;
118

    
119
    /** Constructor: the work is performed by init()
120
     *  @param ibi The beat period (inter-beat interval) of the Agent's tempo hypothesis.
121
     */
122
    Agent(double ibi) {
123
        innerMargin = INNER_MARGIN;
124
        correctionFactor = DEFAULT_CORRECTION_FACTOR;
125
        expiryTime = DEFAULT_EXPIRY_TIME;
126
        decayFactor = 0;
127
        beatInterval = ibi;
128
        initialBeatInterval = ibi;
129
        postMargin = ibi * POST_MARGIN_FACTOR;
130
        preMargin = ibi * PRE_MARGIN_FACTOR;
131
        idNumber = idCounter++;
132
        phaseScore = 0.0;
133
        tempoScore = 0.0;
134
        topScoreTime = 0.0;
135
        beatCount = 0;
136
        beatTime = -1.0;
137
    } // constructor
138

    
139
    Agent *clone() const {
140
        Agent *a = new Agent(*this);
141
        a->idNumber = idCounter++;
142
        return a;
143
    }
144

    
145
protected:
146
    double threshold(double value, double min, double max) {
147
        if (value < min)
148
            return min;
149
        if (value > max)
150
            return max;
151
        return value;
152
    }
153

    
154
public:
155
    /** Accept a new Event as a beat time, and update the state of the Agent accordingly.
156
     *  @param e The Event which is accepted as being on the beat.
157
     *  @param err The difference between the predicted and actual beat times.
158
     *  @param beats The number of beats since the last beat that matched an Event.
159
     */
160
    void accept(Event e, double err, int beats);
161

    
162
    /** The given Event is tested for a possible beat time. The following situations can occur:
163
     *  1) The Agent has no beats yet; the Event is accepted as the first beat.
164
     *  2) The Event is beyond expiryTime seconds after the Agent's last 'confirming' beat; the Agent is terminated.
165
     *  3) The Event is within the innerMargin of the beat prediction; it is accepted as a beat.
166
     *  4) The Event is within the postMargin's of the beat prediction; it is accepted as a beat by this Agent,
167
     *     and a new Agent is created which doesn't accept it as a beat.
168
     *  5) The Event is ignored because it is outside the windows around the Agent's predicted beat time.
169
     * @param e The Event to be tested
170
     * @param a The list of all agents, which is updated if a new agent is created.
171
     * @return Indicate whether the given Event was accepted as a beat by this Agent.
172
     */
173
    bool considerAsBeat(Event e, AgentList &a);
174

    
175
    /** Interpolates missing beats in the Agent's beat track, starting from the beginning of the piece. */
176
    void fillBeats() {
177
        fillBeats(-1.0);
178
    } // fillBeats()/0
179

    
180
    /** Interpolates missing beats in the Agent's beat track.
181
     *  @param start Ignore beats earlier than this start time 
182
     */
183
    void fillBeats(double start);
184

    
185
}; // class Agent
186

    
187
#endif