54 D(
float inputSampleRate);
66 bool initialise(
size_t channels,
size_t stepSize,
size_t blockSize);
100 m_inputSampleRate(inputSampleRate),
106 m_priorMagnitudes(0),
117 delete[] m_priorMagnitudes;
131 d.
name =
"Minimum estimated tempo";
132 d.
description =
"Minimum beat-per-minute value which the tempo estimator is able to return";
141 d.
name =
"Maximum estimated tempo";
142 d.
description =
"Maximum beat-per-minute value which the tempo estimator is able to return";
147 d.
name =
"Input duration to study";
148 d.
description =
"Length of audio input, in seconds, which should be taken into account when estimating tempo. There is no need to supply the plugin with any further input once this time has elapsed since the start of the audio. The tempo estimator may use only the first part of this, up to eight times the slowest beat duration: increasing this value further than that is unlikely to improve results.";
161 if (
id ==
"minbpm") {
163 }
else if (
id ==
"maxbpm") {
165 }
else if (
id ==
"maxdflen") {
174 if (
id ==
"minbpm") {
176 }
else if (
id ==
"maxbpm") {
178 }
else if (
id ==
"maxdflen") {
209 d.
name =
"Tempo candidates";
210 d.
description =
"Possible tempo estimates, one per bin with the most likely in the first bin";
216 d.
name =
"Detection Function";
236 d.
name =
"Autocorrelation Function";
237 d.
description =
"Autocorrelation of onset detection function";
243 d.
name =
"Filtered Autocorrelation";
244 d.
description =
"Filtered autocorrelation of onset detection function";
254 m_stepSize = stepSize;
255 m_blockSize = blockSize;
257 float dfLengthSecs = m_maxdflen;
260 m_priorMagnitudes =
new float[m_blockSize/2];
261 m_df =
new float[m_dfsize];
263 for (
size_t i = 0; i < m_blockSize/2; ++i) {
264 m_priorMagnitudes[i] = 0.f;
266 for (
size_t i = 0; i < m_dfsize; ++i) {
278 if (!m_priorMagnitudes)
return;
280 for (
size_t i = 0; i < m_blockSize/2; ++i) {
281 m_priorMagnitudes[i] = 0.f;
283 for (
size_t i = 0; i < m_dfsize; ++i) {
298 m_start = RealTime::zeroTime;
299 m_lasttime = RealTime::zeroTime;
307 if (m_stepSize == 0) {
308 cerr <<
"ERROR: FixedTempoEstimator::process: "
309 <<
"FixedTempoEstimator has not been initialised"
314 if (m_n == 0) m_start = ts;
317 if (m_n == m_dfsize) {
320 fs = assembleFeatures();
334 for (
size_t i = 1; i < m_blockSize/2; ++i) {
336 float real = inputBuffers[0][i*2];
337 float imag = inputBuffers[0][i*2 + 1];
339 float sqrmag = real * real + imag * imag;
340 value += fabsf(sqrmag - m_priorMagnitudes[i]);
342 m_priorMagnitudes[i] = sqrmag;
355 if (m_n > m_dfsize)
return fs;
357 fs = assembleFeatures();
378 cerr <<
"FixedTempoEstimator::calculate: calculation already happened?" << endl;
382 if (m_n < m_dfsize / 9 &&
384 cerr <<
"FixedTempoEstimator::calculate: Input is too short" << endl;
395 m_r =
new float[n/2];
396 m_fr =
new float[n/2];
397 m_t =
new float[n/2];
399 for (
int i = 0; i < n/2; ++i) {
402 m_t[i] = lag2tempo(i);
407 for (
int i = 0; i < n/2; ++i) {
409 for (
int j = i; j < n; ++j) {
410 m_r[i] += m_df[j] * m_df[j - i];
418 float related[] = { 0.5, 2, 4, 8 };
420 for (
int i = 1; i < n/2-1; ++i) {
426 for (
int j = 0; j < int(
sizeof(related)/
sizeof(related[0])); ++j) {
430 int k0 = int(i * related[j] + 0.5);
432 if (k0 >= 0 && k0 <
int(n/2)) {
435 float kvmax = 0, kvmin = 0;
438 for (
int k = k0 - 1; k <= k0 + 1; ++k) {
440 if (k < 0 || k >= n/2)
continue;
442 if (!have || (m_r[k] > kvmax)) { kvmax = m_r[k]; kmax = k; }
443 if (!have || (m_r[k] < kvmin)) { kvmin = m_r[k]; }
451 m_fr[i] += m_r[kmax] / 5;
453 if ((kmax == 0 || m_r[kmax] > m_r[kmax-1]) &&
454 (kmax == n/2-1 || m_r[kmax] > m_r[kmax+1]) &&
455 kvmax > kvmin * 1.05) {
461 m_t[i] = m_t[i] + lag2tempo(kmax) * related[j];
472 float weight = 1.f - fabsf(128.f - lag2tempo(i)) * 0.005;
473 if (weight < 0.f) weight = 0.f;
474 weight = weight * weight * weight;
476 m_fr[i] += m_fr[i] * (weight / 3);
491 feature.
values.push_back(0.f);
497 for (
int i = 0; i < n; ++i) {
503 feature.
values[0] = m_df[i];
508 for (
int i = 1; i < n/2; ++i) {
515 feature.
values[0] = m_r[i];
516 sprintf(buffer,
"%.1f bpm", lag2tempo(i));
517 if (i == n/2-1) feature.
label =
"";
518 else feature.
label = buffer;
525 int p0 = tempo2lag(t1);
526 int p1 = tempo2lag(t0);
528 std::map<float, int> candidates;
530 for (
int i = p0; i <= p1 && i+1 < n/2; ++i) {
532 if (m_fr[i] > m_fr[i-1] &&
533 m_fr[i] > m_fr[i+1]) {
539 candidates[m_fr[i]] = i;
546 feature.
values[0] = m_fr[i];
547 sprintf(buffer,
"%.1f bpm", lag2tempo(i));
548 if (i == p1 || i == n/2-2) feature.
label =
"";
549 else feature.
label = buffer;
553 if (candidates.empty()) {
554 cerr <<
"No tempo candidates!" << endl;
562 feature.
duration = m_lasttime - m_start;
567 std::map<float, int>::const_iterator ci = candidates.end();
569 int maxpi = ci->second;
571 if (m_t[maxpi] > 0) {
576 feature.
values[0] = m_t[maxpi];
583 feature.
values[0] = lag2tempo(maxpi);
584 cerr <<
"WARNING: No stored tempo for index " << maxpi << endl;
587 sprintf(buffer,
"%.1f bpm", feature.
values[0]);
588 feature.
label = buffer;
600 while (feature.
values.size() < 10) {
601 if (m_t[ci->second] > 0) {
602 feature.
values.push_back(m_t[ci->second]);
604 feature.
values.push_back(lag2tempo(ci->second));
606 if (ci == candidates.begin())
break;
619 m_d(new
D(inputSampleRate))
637 return "Simple Fixed Tempo Estimator";
643 return "Study a short section of audio and estimate its tempo, assuming the tempo is constant";
649 return "Vamp SDK Example Plugins";
661 return "Code copyright 2008 Queen Mary, University of London. Freely redistributable (BSD license)";
std::vector< OutputDescriptor > OutputList
float * m_priorMagnitudes
bool hasDuration
True if the returned results for this output are known to have a duration field.
ParameterList getParameterDescriptors() const
std::string label
Label for the sample of this feature.
FeatureSet process(const float *const *inputBuffers, Vamp::RealTime timestamp)
Process a single block of input data.
float sampleRate
Sample rate of the output results, as samples per second.
FeatureSet getRemainingFeatures()
size_t getPreferredStepSize() const
bool hasFixedBinCount
True if the output has the same number of values per sample for every output sample.
std::vector< float > values
Results for a single sample of this feature.
Results are evenly spaced in time (sampleRate specified below)
virtual ~FixedTempoEstimator()
std::map< int, FeatureList > FeatureSet
float quantizeStep
Quantization resolution of the output values (e.g.
RealTime timestamp
Timestamp of the output feature.
std::string getName() const
Get a human-readable name or title of the plugin.
std::string identifier
The name of the parameter, in computer-usable form.
std::string description
A human-readable short text describing the output.
Plugin(float inputSampleRate)
void reset()
Reset the plugin after use, to prepare it for another clean run.
std::string getDescription() const
Get a human-readable description for the plugin, typically a line of text that may optionally be disp...
std::string identifier
The name of the output, in computer-usable form.
float minValue
Minimum value of the results in the output.
float getParameter(std::string id) const
Get the value of a named parameter.
OutputList getOutputDescriptors() const
std::string getIdentifier() const
Get the computer-usable name of the plugin.
std::string name
The human-readable name of the parameter.
float maxValue
Maximum value of the results in the output.
Vamp::RealTime m_lasttime
size_t getPreferredBlockSize() const
Get the preferred block size (window size – the number of sample frames passed in each block to the ...
RealTime duration
Duration of the output feature.
float minValue
The minimum value of the parameter.
std::string getMaker() const
Get the name of the author or vendor of the plugin in human-readable form.
float getParameter(string id) const
std::string unit
The unit of the parameter, in human-readable form.
std::string unit
The unit of the output, in human-readable form.
std::string name
The human-readable name of the output.
RealTime represents time values to nanosecond precision with accurate arithmetic and frame-rate conve...
bool hasTimestamp
True if an output feature has its own timestamp.
FeatureSet getRemainingFeatures()
After all blocks have been processed, calculate and return any remaining features derived from the co...
void setParameter(std::string id, float value)
Set a named parameter.
std::string description
A human-readable short text describing the parameter.
float maxValue
The maximum value of the parameter.
static int CandidatesOutput
ParameterList getParameterDescriptors() const
Get the controllable parameters of this plugin.
FeatureSet process(const float *const *, RealTime)
bool hasDuration
True if an output feature has a specified duration.
std::string getCopyright() const
Get the copyright statement or licensing summary for the plugin.
size_t getPreferredBlockSize() const
virtual size_t getMaxChannelCount() const
Get the maximum supported number of input channels.
static int FilteredACFOutput
size_t binCount
The number of values per result of the output.
void setParameter(string id, float value)
size_t getPreferredStepSize() const
Get the preferred step size (window increment – the distance in sample frames between the start fram...
bool initialise(size_t channels, size_t stepSize, size_t blockSize)
Initialise a plugin to prepare it for use with the given number of input channels, step size (window increment, in sample frames) and block size (window size, in sample frames).
bool initialise(size_t channels, size_t stepSize, size_t blockSize)
bool isQuantized
True if the output values are quantized to a particular resolution.
float defaultValue
The default value of the parameter.
OutputList getOutputDescriptors() const
Get the outputs of this plugin.
virtual size_t getMinChannelCount() const
Get the minimum supported number of input channels.
int getPluginVersion() const
Get the version number of the plugin.
bool isQuantized
True if the parameter values are quantized to a particular resolution.
FeatureSet assembleFeatures()
FixedTempoEstimator(float inputSampleRate)
SampleType sampleType
Positioning in time of the output results.
Results are unevenly spaced and have individual timestamps.
bool hasKnownExtents
True if the results in each output bin fall within a fixed numeric range (minimum and maximum values)...
std::vector< ParameterDescriptor > ParameterList