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 / AgentList.cpp @ 22:6afcb5edd7ab

History | View | Annotate | Download (5.35 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
#include "AgentList.h"
17

    
18
bool AgentList::useAverageSalience = false;
19
const double AgentList::DEFAULT_BI = 0.02;
20
const double AgentList::DEFAULT_BT = 0.04;
21

    
22
void AgentList::removeDuplicates() 
23
{
24
    sort();
25
    for (iterator itr = begin(); itr != end(); ++itr) {
26
#ifdef DEBUG_BEATROOT
27
        std::cerr << "removeDuplicates: considering agent " << (*itr)->idNumber << std::endl;
28
#endif
29
        if ((*itr)->phaseScore < 0.0) // already flagged for deletion
30
            continue;
31
        iterator itr2 = itr;
32
        for (++itr2; itr2 != end(); ++itr2) {
33
            if ((*itr2)->beatInterval - (*itr)->beatInterval > DEFAULT_BI)
34
                break;
35
            if (fabs((*itr)->beatTime - (*itr2)->beatTime) > DEFAULT_BT)
36
                continue;
37
            if ((*itr)->phaseScore < (*itr2)->phaseScore) {
38
#ifdef DEBUG_BEATROOT
39
                std::cerr << "agent " << (*itr)->idNumber << " is similar to but lower-scoring than agent " << (*itr2)->idNumber << ", marking for deletion" << std::endl;
40
#endif
41
                (*itr)->phaseScore = -1.0;        // flag for deletion
42
                if ((*itr2)->topScoreTime < (*itr)->topScoreTime)
43
                    (*itr2)->topScoreTime = (*itr)->topScoreTime;
44
                break;
45
            } else {
46
#ifdef DEBUG_BEATROOT
47
                std::cerr << "agent " << (*itr2)->idNumber << " is similar to but lower-scoring than agent " << (*itr)->idNumber << ", marking for deletion" << std::endl;
48
#endif
49
                (*itr2)->phaseScore = -1.0;        // flag for deletion
50
                if ((*itr)->topScoreTime < (*itr2)->topScoreTime)
51
                    (*itr)->topScoreTime = (*itr2)->topScoreTime;
52
            }
53
        }
54
    }
55
    int removed = 0;
56
    for (iterator itr = begin(); itr != end(); ) {
57
        if ((*itr)->phaseScore < 0.0) {
58
            ++removed;
59
            delete *itr;
60
            list.erase(itr);
61
        } else {
62
            ++itr;
63
        }
64
    }
65
#ifdef DEBUG_BEATROOT
66
    if (removed > 0) {
67
        std::cerr << "removeDuplicates: removed " << removed << ", have "
68
                  << list.size() << " agent(s) remaining" << std::endl;
69
    }
70
    int n = 0;
71
    for (Container::iterator i = list.begin(); i != list.end(); ++i) {
72
        std::cerr << "agent " << n++ << ": time " << (*i)->beatTime << std::endl;
73
    }
74
#endif
75
} // removeDuplicates()
76

    
77

    
78
void AgentList::beatTrack(EventList el, double stop)
79
{
80
    EventList::iterator ei = el.begin();
81
    bool phaseGiven = !empty() && ((*begin())->beatTime >= 0); // if given for one, assume given for others
82
    while (ei != el.end()) {
83
        Event ev = *ei;
84
        ++ei;
85
        if ((stop > 0) && (ev.time > stop))
86
            break;
87
        bool created = phaseGiven;
88
        double prevBeatInterval = -1.0;
89
        // cc: Duplicate our list of agents, and scan through the
90
        // copy.  This means we can safely add agents to our own
91
        // list while scanning without disrupting our scan.  Each
92
        // agent needs to be re-added to our own list explicitly
93
        // (since it is modified by e.g. considerAsBeat)
94
        Container currentAgents = list;
95
        list.clear();
96
        for (Container::iterator ai = currentAgents.begin();
97
             ai != currentAgents.end(); ++ai) {
98
            Agent *currentAgent = *ai;
99
            if (currentAgent->beatInterval != prevBeatInterval) {
100
                if ((prevBeatInterval>=0) && !created && (ev.time<5.0)) {
101
#ifdef DEBUG_BEATROOT
102
                    std::cerr << "Creating a new agent" << std::endl;
103
#endif
104
                    // Create new agent with different phase
105
                    Agent *newAgent = new Agent(prevBeatInterval);
106
                    // This may add another agent to our list as well
107
                    newAgent->considerAsBeat(ev, *this);
108
                    add(newAgent);
109
                }
110
                prevBeatInterval = currentAgent->beatInterval;
111
                created = phaseGiven;
112
            }
113
            if (currentAgent->considerAsBeat(ev, *this))
114
                created = true;
115
            add(currentAgent);
116
        } // loop for each agent
117
        removeDuplicates();
118
    } // loop for each event
119
} // beatTrack()
120

    
121
Agent *AgentList::bestAgent()
122
{
123
    double best = -1.0;
124
    Agent *bestAg = 0;
125
    for (iterator itr = begin(); itr != end(); ++itr) {
126
        if ((*itr)->events.empty()) continue;
127
        double conf = ((*itr)->phaseScore + (*itr)->tempoScore) /
128
            (useAverageSalience? (double)(*itr)->beatCount: 1.0);
129
        if (conf > best) {
130
            bestAg = *itr;
131
            best = conf;
132
        }
133
    }
134
#ifdef DEBUG_BEATROOT
135
    if (bestAg) {
136
        std::cerr << "Best agent: Ag#" << bestAg->idNumber << std::endl;
137
        std::cerr << "  Av-salience = " << best << std::endl;
138
    } else {
139
        std::cerr << "No surviving agent - beat tracking failed" << std::endl;
140
    }
141
#endif
142
    return bestAg;
143
} // bestAgent()
144