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

History | View | Annotate | Download (5.38 KB)

1 8:f04f87b5e643 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
#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 15:887c629502a9 Chris
void AgentList::removeDuplicates()
23
{
24
    sort();
25
    for (iterator itr = begin(); itr != end(); ++itr) {
26 22:6afcb5edd7ab Chris
#ifdef DEBUG_BEATROOT
27
        std::cerr << "removeDuplicates: considering agent " << (*itr)->idNumber << std::endl;
28
#endif
29 16:33d0b18b2509 Chris
        if ((*itr)->phaseScore < 0.0) // already flagged for deletion
30 15:887c629502a9 Chris
            continue;
31
        iterator itr2 = itr;
32
        for (++itr2; itr2 != end(); ++itr2) {
33 16:33d0b18b2509 Chris
            if ((*itr2)->beatInterval - (*itr)->beatInterval > DEFAULT_BI)
34 15:887c629502a9 Chris
                break;
35 16:33d0b18b2509 Chris
            if (fabs((*itr)->beatTime - (*itr2)->beatTime) > DEFAULT_BT)
36 15:887c629502a9 Chris
                continue;
37 16:33d0b18b2509 Chris
            if ((*itr)->phaseScore < (*itr2)->phaseScore) {
38 22:6afcb5edd7ab Chris
#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 16:33d0b18b2509 Chris
                (*itr)->phaseScore = -1.0;        // flag for deletion
42
                if ((*itr2)->topScoreTime < (*itr)->topScoreTime)
43
                    (*itr2)->topScoreTime = (*itr)->topScoreTime;
44 15:887c629502a9 Chris
                break;
45
            } else {
46 22:6afcb5edd7ab Chris
#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 16:33d0b18b2509 Chris
                (*itr2)->phaseScore = -1.0;        // flag for deletion
50
                if ((*itr)->topScoreTime < (*itr2)->topScoreTime)
51
                    (*itr)->topScoreTime = (*itr2)->topScoreTime;
52 15:887c629502a9 Chris
            }
53
        }
54
    }
55
    int removed = 0;
56
    for (iterator itr = begin(); itr != end(); ) {
57 16:33d0b18b2509 Chris
        if ((*itr)->phaseScore < 0.0) {
58 15:887c629502a9 Chris
            ++removed;
59 16:33d0b18b2509 Chris
            delete *itr;
60 15:887c629502a9 Chris
            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 16:33d0b18b2509 Chris
        std::cerr << "agent " << n++ << ": time " << (*i)->beatTime << std::endl;
73 15:887c629502a9 Chris
    }
74
#endif
75
} // removeDuplicates()
76
77
78 23:633ec097fa56 Chris
void AgentList::beatTrack(EventList el, AgentParameters params, double stop)
79 15:887c629502a9 Chris
{
80
    EventList::iterator ei = el.begin();
81 16:33d0b18b2509 Chris
    bool phaseGiven = !empty() && ((*begin())->beatTime >= 0); // if given for one, assume given for others
82 15:887c629502a9 Chris
    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 16:33d0b18b2509 Chris
            Agent *currentAgent = *ai;
99
            if (currentAgent->beatInterval != prevBeatInterval) {
100 15:887c629502a9 Chris
                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 23:633ec097fa56 Chris
                    Agent *newAgent = new Agent(params, prevBeatInterval);
106 15:887c629502a9 Chris
                    // This may add another agent to our list as well
107 16:33d0b18b2509 Chris
                    newAgent->considerAsBeat(ev, *this);
108 15:887c629502a9 Chris
                    add(newAgent);
109
                }
110 16:33d0b18b2509 Chris
                prevBeatInterval = currentAgent->beatInterval;
111 15:887c629502a9 Chris
                created = phaseGiven;
112
            }
113 16:33d0b18b2509 Chris
            if (currentAgent->considerAsBeat(ev, *this))
114 15:887c629502a9 Chris
                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 16:33d0b18b2509 Chris
        if ((*itr)->events.empty()) continue;
127
        double conf = ((*itr)->phaseScore + (*itr)->tempoScore) /
128
            (useAverageSalience? (double)(*itr)->beatCount: 1.0);
129 15:887c629502a9 Chris
        if (conf > best) {
130 16:33d0b18b2509 Chris
            bestAg = *itr;
131 15:887c629502a9 Chris
            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()