To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
root / Agent.cpp
History | View | Annotate | Download (4.22 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 | #include "Agent.h" |
||
| 17 | #include "BeatTracker.h" |
||
| 18 | |||
| 19 | 23:633ec097fa56 | Chris | const double AgentParameters::DEFAULT_POST_MARGIN_FACTOR = 0.3; |
| 20 | const double AgentParameters::DEFAULT_PRE_MARGIN_FACTOR = 0.15; |
||
| 21 | const double AgentParameters::DEFAULT_MAX_CHANGE = 0.2; |
||
| 22 | const double AgentParameters::DEFAULT_EXPIRY_TIME = 10.0; |
||
| 23 | |||
| 24 | 6:02d388f98c23 | Chris | const double Agent::INNER_MARGIN = 0.040; |
| 25 | 23:633ec097fa56 | Chris | const double Agent::CONF_FACTOR = 0.5; |
| 26 | 6:02d388f98c23 | Chris | const double Agent::DEFAULT_CORRECTION_FACTOR = 50.0; |
| 27 | |||
| 28 | int Agent::idCounter = 0; |
||
| 29 | |||
| 30 | 15:887c629502a9 | Chris | void Agent::accept(Event e, double err, int beats) { |
| 31 | beatTime = e.time; |
||
| 32 | events.push_back(e); |
||
| 33 | if (fabs(initialBeatInterval - beatInterval -
|
||
| 34 | 23:633ec097fa56 | Chris | err / correctionFactor) < maxChange * initialBeatInterval) |
| 35 | 15:887c629502a9 | Chris | beatInterval += err / correctionFactor;// Adjust tempo
|
| 36 | beatCount += beats; |
||
| 37 | double conFactor = 1.0 - CONF_FACTOR * err / |
||
| 38 | (err>0? postMargin: -preMargin);
|
||
| 39 | if (decayFactor > 0) { |
||
| 40 | double memFactor = 1. - 1. / threshold((double)beatCount,1,decayFactor); |
||
| 41 | phaseScore = memFactor * phaseScore + |
||
| 42 | (1.0 - memFactor) * conFactor * e.salience; |
||
| 43 | } else
|
||
| 44 | phaseScore += conFactor * e.salience; |
||
| 45 | |||
| 46 | #ifdef DEBUG_BEATROOT
|
||
| 47 | std::cerr << "Ag#" << idNumber << ": " << beatInterval << std::endl; |
||
| 48 | std::cerr << " Beat" << beatCount << " Time=" << beatTime |
||
| 49 | << " Score=" << tempoScore << ":P" << phaseScore << ":" |
||
| 50 | << topScoreTime << std::endl; |
||
| 51 | #endif
|
||
| 52 | } // accept()
|
||
| 53 | |||
| 54 | 8:f04f87b5e643 | Chris | bool Agent::considerAsBeat(Event e, AgentList &a) {
|
| 55 | 6:02d388f98c23 | Chris | double err;
|
| 56 | if (beatTime < 0) { // first event |
||
| 57 | 12:59520cd6abac | Chris | #ifdef DEBUG_BEATROOT
|
| 58 | std::cerr << "Ag#" << idNumber << ": accepting first event trivially at " << e.time << std::endl; |
||
| 59 | #endif
|
||
| 60 | 6:02d388f98c23 | Chris | accept(e, 0, 1); |
| 61 | return true; |
||
| 62 | } else { // subsequent events |
||
| 63 | 9:4f6626f9ffac | Chris | EventList::iterator last = events.end(); |
| 64 | --last; |
||
| 65 | if (e.time - last->time > expiryTime) {
|
||
| 66 | 12:59520cd6abac | Chris | #ifdef DEBUG_BEATROOT
|
| 67 | std::cerr << "Ag#" << idNumber << ": time " << e.time |
||
| 68 | << " too late relative to " << last->time << " (expiry " |
||
| 69 | << expiryTime << "), giving up" << std::endl;
|
||
| 70 | #endif
|
||
| 71 | 6:02d388f98c23 | Chris | phaseScore = -1.0; // flag agent to be deleted |
| 72 | return false; |
||
| 73 | } |
||
| 74 | 8:f04f87b5e643 | Chris | double beats = nearbyint((e.time - beatTime) / beatInterval);
|
| 75 | err = e.time - beatTime - beats * beatInterval; |
||
| 76 | 12:59520cd6abac | Chris | #ifdef DEBUG_BEATROOT
|
| 77 | std::cerr << "Ag#" << idNumber << ": time " << e.time << ", err " << err << " for beats " << beats << std::endl; |
||
| 78 | #endif
|
||
| 79 | 6:02d388f98c23 | Chris | if ((beats > 0) && (-preMargin <= err) && (err <= postMargin)) { |
| 80 | 16:33d0b18b2509 | Chris | if (fabs(err) > innerMargin) {
|
| 81 | 12:59520cd6abac | Chris | #ifdef DEBUG_BEATROOT
|
| 82 | std::cerr << "Ag#" << idNumber << ": creating another new agent" << std::endl; |
||
| 83 | #endif
|
||
| 84 | 16:33d0b18b2509 | Chris | // Create new agent that skips this event (avoids
|
| 85 | // large phase jump)
|
||
| 86 | a.add(clone()); |
||
| 87 | 12:59520cd6abac | Chris | } |
| 88 | 6:02d388f98c23 | Chris | accept(e, err, (int)beats);
|
| 89 | return true; |
||
| 90 | } |
||
| 91 | } |
||
| 92 | return false; |
||
| 93 | } // considerAsBeat()
|
||
| 94 | |||
| 95 | |||
| 96 | 9:4f6626f9ffac | Chris | void Agent::fillBeats(double start) { |
| 97 | 6:02d388f98c23 | Chris | double prevBeat = 0, nextBeat, currentInterval, beats; |
| 98 | 9:4f6626f9ffac | Chris | EventList::iterator ei = events.begin(); |
| 99 | if (ei != events.end()) {
|
||
| 100 | 13:0d4048bfadbb | Chris | EventList::iterator ni = ei; |
| 101 | 18:55969570044e | Chris | if (++ni != events.end()) {
|
| 102 | prevBeat = ni->time; |
||
| 103 | } |
||
| 104 | 6:02d388f98c23 | Chris | } |
| 105 | 16:33d0b18b2509 | Chris | while (ei != events.end()) {
|
| 106 | 13:0d4048bfadbb | Chris | EventList::iterator ni = ei; |
| 107 | 18:55969570044e | Chris | if (ni == events.end() ||
|
| 108 | ++ni == events.end()) {
|
||
| 109 | break;
|
||
| 110 | } |
||
| 111 | 16:33d0b18b2509 | Chris | nextBeat = ni->time; |
| 112 | 6:02d388f98c23 | Chris | beats = nearbyint((nextBeat - prevBeat) / beatInterval - 0.01); //prefer slow |
| 113 | currentInterval = (nextBeat - prevBeat) / beats; |
||
| 114 | for ( ; (nextBeat > start) && (beats > 1.5); beats--) { |
||
| 115 | prevBeat += currentInterval; |
||
| 116 | 13:0d4048bfadbb | Chris | events.insert(ni, BeatTracker::newBeat(prevBeat, 0));
|
| 117 | 6:02d388f98c23 | Chris | } |
| 118 | prevBeat = nextBeat; |
||
| 119 | 13:0d4048bfadbb | Chris | ei = ni; |
| 120 | 6:02d388f98c23 | Chris | } |
| 121 | } // fillBeats() |