Revision 23:633ec097fa56
| Agent.cpp | ||
|---|---|---|
| 16 | 16 |
#include "Agent.h" |
| 17 | 17 |
#include "BeatTracker.h" |
| 18 | 18 |
|
| 19 |
double Agent::POST_MARGIN_FACTOR = 0.3; |
|
| 20 |
double Agent::PRE_MARGIN_FACTOR = 0.15; |
|
| 19 |
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 |
|
|
| 21 | 24 |
const double Agent::INNER_MARGIN = 0.040; |
| 22 |
double Agent::MAX_CHANGE = 0.2; |
|
| 23 |
double Agent::CONF_FACTOR = 0.5; |
|
| 25 |
const double Agent::CONF_FACTOR = 0.5; |
|
| 24 | 26 |
const double Agent::DEFAULT_CORRECTION_FACTOR = 50.0; |
| 25 |
const double Agent::DEFAULT_EXPIRY_TIME = 10.0; |
|
| 26 | 27 |
|
| 27 | 28 |
int Agent::idCounter = 0; |
| 28 | 29 |
|
| 29 |
double Agent::innerMargin = 0.0; |
|
| 30 |
double Agent::correctionFactor = 0.0; |
|
| 31 |
double Agent::expiryTime = 0.0; |
|
| 32 |
double Agent::decayFactor = 0.0; |
|
| 33 |
|
|
| 34 | 30 |
void Agent::accept(Event e, double err, int beats) {
|
| 35 | 31 |
beatTime = e.time; |
| 36 | 32 |
events.push_back(e); |
| 37 | 33 |
if (fabs(initialBeatInterval - beatInterval - |
| 38 |
err / correctionFactor) < MAX_CHANGE * initialBeatInterval)
|
|
| 34 |
err / correctionFactor) < maxChange * initialBeatInterval)
|
|
| 39 | 35 |
beatInterval += err / correctionFactor;// Adjust tempo |
| 40 | 36 |
beatCount += beats; |
| 41 | 37 |
double conFactor = 1.0 - CONF_FACTOR * err / |
| Agent.h | ||
|---|---|---|
| 26 | 26 |
|
| 27 | 27 |
class AgentList; |
| 28 | 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 |
|
|
| 29 | 63 |
/** Agent is the central class for beat tracking. |
| 30 | 64 |
* Each Agent object has a tempo hypothesis, a history of tracked beats, and |
| 31 | 65 |
* a score evaluating the continuity, regularity and salience of its beat track. |
| ... | ... | |
| 33 | 67 |
class Agent |
| 34 | 68 |
{
|
| 35 | 69 |
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. */ |
|
| 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. */ |
|
| 46 | 73 |
static const double INNER_MARGIN; |
| 47 | 74 |
|
| 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; |
|
| 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; |
|
| 53 | 78 |
|
| 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. */ |
|
| 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. */ |
|
| 58 | 86 |
static const double DEFAULT_CORRECTION_FACTOR; |
| 59 | 87 |
|
| 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 | 88 |
protected: |
| 65 | 89 |
/** The identity number of the next created Agent */ |
| 66 | 90 |
static int idCounter; |
| 67 | 91 |
|
| 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; |
|
| 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; |
|
| 71 | 96 |
|
| 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; |
|
| 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; |
|
| 76 | 103 |
|
| 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;
|
|
| 104 |
/** The time (in seconds) after which an Agent that has no Event
|
|
| 105 |
* matching its beat predictions will be destroyed. */ |
|
| 106 |
double expiryTime; |
|
| 80 | 107 |
|
| 81 |
/** For scoring Agents in a (non-existent) real-time version (otherwise not used). */ |
|
| 82 |
static double decayFactor; |
|
| 108 |
/** For scoring Agents in a (non-existent) real-time version |
|
| 109 |
* (otherwise not used). */ |
|
| 110 |
double decayFactor; |
|
| 83 | 111 |
|
| 84 | 112 |
public: |
| 85 | 113 |
/** The size of the outer half-window before the predicted beat time. */ |
| ... | ... | |
| 94 | 122 |
/** To be used in real-time version?? */ |
| 95 | 123 |
double tempoScore; |
| 96 | 124 |
|
| 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. */ |
|
| 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. */ |
|
| 99 | 128 |
double phaseScore; |
| 100 | 129 |
|
| 101 |
/** How long has this agent been the best? For real-time version; otherwise not used. */ |
|
| 130 |
/** How long has this agent been the best? For real-time version; |
|
| 131 |
* otherwise not used. */ |
|
| 102 | 132 |
double topScoreTime; |
| 103 | 133 |
|
| 104 |
/** The number of beats found by this Agent, including interpolated beats. */ |
|
| 134 |
/** The number of beats found by this Agent, including |
|
| 135 |
* interpolated beats. */ |
|
| 105 | 136 |
int beatCount; |
| 106 | 137 |
|
| 107 |
/** The current tempo hypothesis of the Agent, expressed as the beat period in seconds. */ |
|
| 138 |
/** The current tempo hypothesis of the Agent, expressed as the |
|
| 139 |
* beat period in seconds. */ |
|
| 108 | 140 |
double beatInterval; |
| 109 | 141 |
|
| 110 |
/** The initial tempo hypothesis of the Agent, expressed as the beat period in seconds. */ |
|
| 142 |
/** The initial tempo hypothesis of the Agent, expressed as the |
|
| 143 |
* beat period in seconds. */ |
|
| 111 | 144 |
double initialBeatInterval; |
| 112 | 145 |
|
| 113 | 146 |
/** The time of the most recent beat accepted by this Agent. */ |
| 114 | 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; |
|
| 115 | 152 |
|
| 116 |
/** The list of Events (onsets) accepted by this Agent as beats, plus interpolated beats. */ |
|
| 153 |
/** The list of Events (onsets) accepted by this Agent as beats, |
|
| 154 |
* plus interpolated beats. */ |
|
| 117 | 155 |
EventList events; |
| 118 | 156 |
|
| 119 | 157 |
/** Constructor: the work is performed by init() |
| 120 | 158 |
* @param ibi The beat period (inter-beat interval) of the Agent's tempo hypothesis. |
| 121 | 159 |
*/ |
| 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; |
|
| 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) {
|
|
| 137 | 176 |
} // constructor |
| 138 | 177 |
|
| 139 | 178 |
Agent *clone() const {
|
| AgentList.cpp | ||
|---|---|---|
| 75 | 75 |
} // removeDuplicates() |
| 76 | 76 |
|
| 77 | 77 |
|
| 78 |
void AgentList::beatTrack(EventList el, double stop) |
|
| 78 |
void AgentList::beatTrack(EventList el, AgentParameters params, double stop)
|
|
| 79 | 79 |
{
|
| 80 | 80 |
EventList::iterator ei = el.begin(); |
| 81 | 81 |
bool phaseGiven = !empty() && ((*begin())->beatTime >= 0); // if given for one, assume given for others |
| ... | ... | |
| 102 | 102 |
std::cerr << "Creating a new agent" << std::endl; |
| 103 | 103 |
#endif |
| 104 | 104 |
// Create new agent with different phase |
| 105 |
Agent *newAgent = new Agent(prevBeatInterval); |
|
| 105 |
Agent *newAgent = new Agent(params, prevBeatInterval);
|
|
| 106 | 106 |
// This may add another agent to our list as well |
| 107 | 107 |
newAgent->considerAsBeat(ev, *this); |
| 108 | 108 |
add(newAgent); |
| AgentList.h | ||
|---|---|---|
| 121 | 121 |
/** Perform beat tracking on a list of events (onsets). |
| 122 | 122 |
* @param el The list of onsets (or events or peaks) to beat track |
| 123 | 123 |
*/ |
| 124 |
void beatTrack(EventList el) {
|
|
| 125 |
beatTrack(el, -1.0); |
|
| 124 |
void beatTrack(EventList el, AgentParameters params) {
|
|
| 125 |
beatTrack(el, params, -1.0);
|
|
| 126 | 126 |
} // beatTrack()/1 |
| 127 | 127 |
|
| 128 | 128 |
/** Perform beat tracking on a list of events (onsets). |
| 129 | 129 |
* @param el The list of onsets (or events or peaks) to beat track. |
| 130 | 130 |
* @param stop Do not find beats after <code>stop</code> seconds. |
| 131 | 131 |
*/ |
| 132 |
void beatTrack(EventList el, double stop); |
|
| 132 |
void beatTrack(EventList el, AgentParameters params, double stop);
|
|
| 133 | 133 |
|
| 134 | 134 |
/** Finds the Agent with the highest score in the list, or NULL if beat tracking has failed. |
| 135 | 135 |
* @return The Agent with the highest score |
| BeatRootProcessor.cpp | ||
|---|---|---|
| 67 | 67 |
std::cerr << "Onsets: " << onsetList.size() << std::endl; |
| 68 | 68 |
#endif |
| 69 | 69 |
|
| 70 |
return BeatTracker::beatTrack(onsetList); |
|
| 70 |
return BeatTracker::beatTrack(agentParameters, onsetList);
|
|
| 71 | 71 |
|
| 72 | 72 |
} // processFile() |
| 73 | 73 |
|
| BeatRootProcessor.h | ||
|---|---|---|
| 81 | 81 |
|
| 82 | 82 |
/** The estimated onset times and their saliences. */ |
| 83 | 83 |
EventList onsetList; |
| 84 |
|
|
| 85 |
/** User-specifiable processing parameters. */ |
|
| 86 |
AgentParameters agentParameters; |
|
| 84 | 87 |
|
| 85 | 88 |
/** Flag for suppressing all standard output messages except results. */ |
| 86 | 89 |
static bool silent; |
| ... | ... | |
| 89 | 92 |
|
| 90 | 93 |
/** Constructor: note that streams are not opened until the input |
| 91 | 94 |
* file is set (see <code>setInputFile()</code>). */ |
| 92 |
BeatRootProcessor(float sr) : |
|
| 93 |
sampleRate(sr) {
|
|
| 94 |
hopSize = 0; |
|
| 95 |
fftSize = 0; |
|
| 96 |
hopTime = 0.010; |
|
| 97 |
fftTime = 0.04644; |
|
| 95 |
BeatRootProcessor(float sr, AgentParameters parameters) : |
|
| 96 |
sampleRate(sr), |
|
| 97 |
hopSize(0), |
|
| 98 |
fftSize(0), |
|
| 99 |
hopTime(0.010), |
|
| 100 |
fftTime(0.04644), |
|
| 101 |
agentParameters(parameters) |
|
| 102 |
{
|
|
| 98 | 103 |
hopSize = lrint(sampleRate * hopTime); |
| 99 | 104 |
fftSize = lrint(pow(2, lrint( log(fftTime * sampleRate) / log(2)))); |
| 100 | 105 |
} // constructor |
| BeatRootVampPlugin.cpp | ||
|---|---|---|
| 24 | 24 |
BeatRootVampPlugin::BeatRootVampPlugin(float inputSampleRate) : |
| 25 | 25 |
Plugin(inputSampleRate) |
| 26 | 26 |
{
|
| 27 |
m_processor = new BeatRootProcessor(inputSampleRate); |
|
| 27 |
m_processor = new BeatRootProcessor(inputSampleRate, AgentParameters());
|
|
| 28 | 28 |
} |
| 29 | 29 |
|
| 30 | 30 |
BeatRootVampPlugin::~BeatRootVampPlugin() |
| ... | ... | |
| 104 | 104 |
BeatRootVampPlugin::getParameterDescriptors() const |
| 105 | 105 |
{
|
| 106 | 106 |
ParameterList list; |
| 107 |
|
|
| 108 |
ParameterDescriptor desc; |
|
| 109 |
|
|
| 110 |
double postMarginFactor; |
|
| 111 |
|
|
| 112 |
/** The maximum amount by which a beat can be earlier than the |
|
| 113 |
* predicted beat time, expressed as a fraction of the beat |
|
| 114 |
* period. */ |
|
| 115 |
double preMarginFactor; |
|
| 116 |
|
|
| 117 |
/** The maximum allowed deviation from the initial tempo, |
|
| 118 |
* expressed as a fraction of the initial beat period. */ |
|
| 119 |
double maxChange; |
|
| 120 |
|
|
| 121 |
/** The default value of expiryTime, which is the time (in |
|
| 122 |
* seconds) after which an Agent that has no Event matching its |
|
| 123 |
* beat predictions will be destroyed. */ |
|
| 124 |
|
|
| 125 |
desc.identifier = "preMarginFactor"; |
|
| 126 |
desc.name = "Pre-Margin Factor"; |
|
| 127 |
desc.description = "The maximum amount by which a beat can be earlier than the predicted beat time, expressed as a fraction of the beat period."; |
|
| 128 |
desc.minValue = 0; |
|
| 129 |
desc.maxValue = 1; |
|
| 130 |
desc.defaultValue = AgentParameters::DEFAULT_PRE_MARGIN_FACTOR; |
|
| 131 |
desc.isQuantized = false; |
|
| 132 |
list.push_back(desc); |
|
| 133 |
|
|
| 134 |
desc.identifier = "postMarginFactor"; |
|
| 135 |
desc.name = "Post-Margin Factor"; |
|
| 136 |
desc.description = "The maximum amount by which a beat can be later than the predicted beat time, expressed as a fraction of the beat period."; |
|
| 137 |
desc.minValue = 0; |
|
| 138 |
desc.maxValue = 1; |
|
| 139 |
desc.defaultValue = AgentParameters::DEFAULT_POST_MARGIN_FACTOR; |
|
| 140 |
desc.isQuantized = false; |
|
| 141 |
list.push_back(desc); |
|
| 142 |
|
|
| 143 |
desc.identifier = "maxChange"; |
|
| 144 |
desc.name = "Maximum Change"; |
|
| 145 |
desc.description = "The maximum allowed deviation from the initial tempo, expressed as a fraction of the initial beat period."; |
|
| 146 |
desc.minValue = 0; |
|
| 147 |
desc.maxValue = 1; |
|
| 148 |
desc.defaultValue = AgentParameters::DEFAULT_MAX_CHANGE; |
|
| 149 |
desc.isQuantized = false; |
|
| 150 |
list.push_back(desc); |
|
| 151 |
|
|
| 152 |
desc.identifier = "expiryTime"; |
|
| 153 |
desc.name = "Expiry Time"; |
|
| 154 |
desc.description = "The default value of expiryTime, which is the time (in seconds) after which an Agent that has no Event matching its beat predictions will be destroyed."; |
|
| 155 |
desc.minValue = 2; |
|
| 156 |
desc.maxValue = 120; |
|
| 157 |
desc.defaultValue = AgentParameters::DEFAULT_EXPIRY_TIME; |
|
| 158 |
desc.isQuantized = false; |
|
| 159 |
list.push_back(desc); |
|
| 160 |
|
|
| 161 |
// Simon says... |
|
| 162 |
|
|
| 163 |
// These are the parameters that should be exposed (Agent.cpp): |
|
| 164 |
|
|
| 165 |
// If Pop, both margins should be lower (0.1). If classical |
|
| 166 |
// music, post margin can be increased |
|
| 167 |
// |
|
| 168 |
// double Agent::POST_MARGIN_FACTOR = 0.3; |
|
| 169 |
// double Agent::PRE_MARGIN_FACTOR = 0.15; |
|
| 170 |
// |
|
| 171 |
// Max Change tells us how much tempo can change - so for |
|
| 172 |
// classical we should make it higher |
|
| 173 |
// |
|
| 174 |
// double Agent::MAX_CHANGE = 0.2; |
|
| 175 |
// |
|
| 176 |
// The EXPIRY TIME default should be defaulted to 100 (usual cause |
|
| 177 |
// of agents dying....) it should also be exposed in order to |
|
| 178 |
// troubleshoot eventual problems in songs with big silences in |
|
| 179 |
// the beggining/end. |
|
| 180 |
// |
|
| 181 |
// const double Agent::DEFAULT_EXPIRY_TIME = 10.0; |
|
| 182 |
|
|
| 107 | 183 |
return list; |
| 108 | 184 |
} |
| 109 | 185 |
|
| 110 | 186 |
float |
| 111 | 187 |
BeatRootVampPlugin::getParameter(string identifier) const |
| 112 | 188 |
{
|
| 189 |
if (identifier == "preMarginFactor") {
|
|
| 190 |
return m_parameters.preMarginFactor; |
|
| 191 |
} else if (identifier == "postMarginFactor") {
|
|
| 192 |
return m_parameters.postMarginFactor; |
|
| 193 |
} else if (identifier == "maxChange") {
|
|
| 194 |
return m_parameters.maxChange; |
|
| 195 |
} else if (identifier == "expiryTime") {
|
|
| 196 |
return m_parameters.expiryTime; |
|
| 197 |
} |
|
| 198 |
|
|
| 113 | 199 |
return 0; |
| 114 | 200 |
} |
| 115 | 201 |
|
| 116 | 202 |
void |
| 117 | 203 |
BeatRootVampPlugin::setParameter(string identifier, float value) |
| 118 | 204 |
{
|
| 205 |
if (identifier == "preMarginFactor") {
|
|
| 206 |
m_parameters.preMarginFactor = value; |
|
| 207 |
} else if (identifier == "postMarginFactor") {
|
|
| 208 |
m_parameters.postMarginFactor = value; |
|
| 209 |
} else if (identifier == "maxChange") {
|
|
| 210 |
m_parameters.maxChange = value; |
|
| 211 |
} else if (identifier == "expiryTime") {
|
|
| 212 |
m_parameters.expiryTime = value; |
|
| 213 |
} |
|
| 119 | 214 |
} |
| 120 | 215 |
|
| 121 | 216 |
BeatRootVampPlugin::ProgramList |
| ... | ... | |
| 187 | 282 |
return false; |
| 188 | 283 |
} |
| 189 | 284 |
|
| 190 |
m_processor->reset(); |
|
| 285 |
// Delete the processor that was created with default parameters |
|
| 286 |
// and used to determine the expected step and block size; replace |
|
| 287 |
// with one using the actual parameters we have |
|
| 288 |
delete m_processor; |
|
| 289 |
m_processor = new BeatRootProcessor(m_inputSampleRate, m_parameters); |
|
| 191 | 290 |
|
| 192 | 291 |
return true; |
| 193 | 292 |
} |
| BeatRootVampPlugin.h | ||
|---|---|---|
| 16 | 16 |
#ifndef _BEATROOT_VAMP_PLUGIN_H_ |
| 17 | 17 |
#define _BEATROOT_VAMP_PLUGIN_H_ |
| 18 | 18 |
|
| 19 |
#include "Agent.h" |
|
| 20 |
|
|
| 19 | 21 |
#include <vamp-sdk/Plugin.h> |
| 20 | 22 |
|
| 21 | 23 |
using std::string; |
| ... | ... | |
| 61 | 63 |
|
| 62 | 64 |
protected: |
| 63 | 65 |
BeatRootProcessor *m_processor; |
| 66 |
AgentParameters m_parameters; |
|
| 64 | 67 |
}; |
| 65 | 68 |
|
| 66 | 69 |
|
| BeatTracker.cpp | ||
|---|---|---|
| 15 | 15 |
|
| 16 | 16 |
#include "BeatTracker.h" |
| 17 | 17 |
|
| 18 |
EventList BeatTracker::beatTrack(EventList events, EventList beats) |
|
| 18 |
EventList BeatTracker::beatTrack(AgentParameters params, |
|
| 19 |
EventList events, EventList beats) |
|
| 19 | 20 |
{
|
| 20 | 21 |
AgentList agents; |
| 21 | 22 |
int count = 0; |
| ... | ... | |
| 28 | 29 |
} |
| 29 | 30 |
if (count > 0) { // tempo given by mean of initial beats
|
| 30 | 31 |
double ioi = (beatTime - beats.begin()->time) / count; |
| 31 |
agents.push_back(new Agent(ioi)); |
|
| 32 |
agents.push_back(new Agent(params, ioi));
|
|
| 32 | 33 |
} else // tempo not given; use tempo induction |
| 33 |
agents = Induction::beatInduction(events); |
|
| 34 |
agents = Induction::beatInduction(params, events);
|
|
| 34 | 35 |
if (!beats.empty()) |
| 35 | 36 |
for (AgentList::iterator itr = agents.begin(); itr != agents.end(); |
| 36 | 37 |
++itr) {
|
| ... | ... | |
| 38 | 39 |
(*itr)->beatCount = count; |
| 39 | 40 |
(*itr)->events = beats; |
| 40 | 41 |
} |
| 41 |
agents.beatTrack(events, -1); |
|
| 42 |
agents.beatTrack(events, params, -1);
|
|
| 42 | 43 |
Agent *best = agents.bestAgent(); |
| 43 | 44 |
EventList results; |
| 44 | 45 |
if (best) {
|
| BeatTracker.h | ||
|---|---|---|
| 56 | 56 |
* @param events The onsets or peaks in a feature list |
| 57 | 57 |
* @return The list of beats, or an empty list if beat tracking fails |
| 58 | 58 |
*/ |
| 59 |
static EventList beatTrack(EventList events) {
|
|
| 60 |
return beatTrack(events, EventList()); |
|
| 59 |
static EventList beatTrack(AgentParameters params, EventList events) {
|
|
| 60 |
return beatTrack(params, events, EventList());
|
|
| 61 | 61 |
} |
| 62 | 62 |
|
| 63 | 63 |
/** Perform beat tracking. |
| ... | ... | |
| 65 | 65 |
* @param beats The initial beats which are given, if any |
| 66 | 66 |
* @return The list of beats, or an empty list if beat tracking fails |
| 67 | 67 |
*/ |
| 68 |
static EventList beatTrack(EventList events, EventList beats); |
|
| 68 |
static EventList beatTrack(AgentParameters params, |
|
| 69 |
EventList events, EventList beats); |
|
| 69 | 70 |
|
| 70 | 71 |
|
| 71 | 72 |
// Various get and set methods |
| Induction.cpp | ||
|---|---|---|
| 23 | 23 |
int Induction::topN = 10; |
| 24 | 24 |
|
| 25 | 25 |
|
| 26 |
AgentList Induction::beatInduction(EventList events) {
|
|
| 26 |
AgentList Induction::beatInduction(AgentParameters params, EventList events) {
|
|
| 27 | 27 |
int i, j, b, bestCount; |
| 28 | 28 |
bool submult; |
| 29 | 29 |
int intervals = 0; // number of interval clusters |
| ... | ... | |
| 183 | 183 |
while (beat > maxIBI) // Minimum speed |
| 184 | 184 |
beat /= 2.0; |
| 185 | 185 |
if (beat >= minIBI) {
|
| 186 |
a.push_back(new Agent(beat)); |
|
| 186 |
a.push_back(new Agent(params, beat));
|
|
| 187 | 187 |
} |
| 188 | 188 |
} |
| 189 | 189 |
#ifdef DEBUG_BEATROOT |
| Induction.h | ||
|---|---|---|
| 68 | 68 |
* @return A list of beat tracking agents, where each is initialised with one |
| 69 | 69 |
* of the top tempo hypotheses but no beats |
| 70 | 70 |
*/ |
| 71 |
static AgentList beatInduction(EventList events); |
|
| 71 |
static AgentList beatInduction(AgentParameters params, EventList events);
|
|
| 72 | 72 |
|
| 73 | 73 |
protected: |
| 74 | 74 |
/** For variable cluster widths in newInduction(). |
Also available in: Unified diff