53 D(
float inputSampleRate);
65 bool initialise(
size_t channels,
size_t stepSize,
size_t blockSize);
99 m_inputSampleRate(inputSampleRate),
105 m_priorMagnitudes(0),
116 delete[] m_priorMagnitudes;
130 d.
name =
"Minimum estimated tempo";
131 d.
description =
"Minimum beat-per-minute value which the tempo estimator is able to return";
140 d.
name =
"Maximum estimated tempo";
141 d.
description =
"Maximum beat-per-minute value which the tempo estimator is able to return";
146 d.
name =
"Input duration to study";
147 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.";
160 if (
id ==
"minbpm") {
162 }
else if (
id ==
"maxbpm") {
164 }
else if (
id ==
"maxdflen") {
173 if (
id ==
"minbpm") {
175 }
else if (
id ==
"maxbpm") {
177 }
else if (
id ==
"maxdflen") {
208 d.
name =
"Tempo candidates";
209 d.
description =
"Possible tempo estimates, one per bin with the most likely in the first bin";
215 d.
name =
"Detection Function";
235 d.
name =
"Autocorrelation Function";
236 d.
description =
"Autocorrelation of onset detection function";
242 d.
name =
"Filtered Autocorrelation";
243 d.
description =
"Filtered autocorrelation of onset detection function";
253 m_stepSize = stepSize;
254 m_blockSize = blockSize;
256 float dfLengthSecs = m_maxdflen;
259 m_priorMagnitudes =
new float[m_blockSize/2];
260 m_df =
new float[m_dfsize];
262 for (
size_t i = 0; i < m_blockSize/2; ++i) {
263 m_priorMagnitudes[i] = 0.f;
265 for (
size_t i = 0; i < m_dfsize; ++i) {
277 if (!m_priorMagnitudes)
return;
279 for (
size_t i = 0; i < m_blockSize/2; ++i) {
280 m_priorMagnitudes[i] = 0.f;
282 for (
size_t i = 0; i < m_dfsize; ++i) {
297 m_start = RealTime::zeroTime;
298 m_lasttime = RealTime::zeroTime;
306 if (m_stepSize == 0) {
307 cerr <<
"ERROR: FixedTempoEstimator::process: "
308 <<
"FixedTempoEstimator has not been initialised"
313 if (m_n == 0) m_start = ts;
316 if (m_n == m_dfsize) {
319 fs = assembleFeatures();
333 for (
size_t i = 1; i < m_blockSize/2; ++i) {
335 float real = inputBuffers[0][i*2];
336 float imag = inputBuffers[0][i*2 + 1];
338 float sqrmag = real * real + imag * imag;
339 value += fabsf(sqrmag - m_priorMagnitudes[i]);
341 m_priorMagnitudes[i] = sqrmag;
354 if (m_n > m_dfsize)
return fs;
356 fs = assembleFeatures();
377 cerr <<
"FixedTempoEstimator::calculate: calculation already happened?" << endl;
381 if (m_n < m_dfsize / 9 &&
383 cerr <<
"FixedTempoEstimator::calculate: Input is too short" << endl;
394 m_r =
new float[n/2];
395 m_fr =
new float[n/2];
396 m_t =
new float[n/2];
398 for (
int i = 0; i < n/2; ++i) {
401 m_t[i] = lag2tempo(i);
406 for (
int i = 0; i < n/2; ++i) {
408 for (
int j = i; j < n; ++j) {
409 m_r[i] += m_df[j] * m_df[j - i];
417 float related[] = { 0.5, 2, 4, 8 };
419 for (
int i = 1; i < n/2-1; ++i) {
425 for (
int j = 0; j < int(
sizeof(related)/
sizeof(related[0])); ++j) {
429 int k0 = int(i * related[j] + 0.5);
431 if (k0 >= 0 && k0 <
int(n/2)) {
433 int kmax = 0, kmin = 0;
434 float kvmax = 0, kvmin = 0;
437 for (
int k = k0 - 1; k <= k0 + 1; ++k) {
439 if (k < 0 || k >= n/2)
continue;
441 if (!have || (m_r[k] > kvmax)) { kmax = k; kvmax = m_r[k]; }
442 if (!have || (m_r[k] < kvmin)) { kmin = k; kvmin = m_r[k]; }
450 m_fr[i] += m_r[kmax] / 5;
452 if ((kmax == 0 || m_r[kmax] > m_r[kmax-1]) &&
453 (kmax == n/2-1 || m_r[kmax] > m_r[kmax+1]) &&
454 kvmax > kvmin * 1.05) {
460 m_t[i] = m_t[i] + lag2tempo(kmax) * related[j];
471 float weight = 1.f - fabsf(128.f - lag2tempo(i)) * 0.005;
472 if (weight < 0.f) weight = 0.f;
473 weight = weight * weight * weight;
475 m_fr[i] += m_fr[i] * (weight / 3);
490 feature.
values.push_back(0.f);
496 for (
int i = 0; i < n; ++i) {
502 feature.
values[0] = m_df[i];
507 for (
int i = 1; i < n/2; ++i) {
514 feature.
values[0] = m_r[i];
515 sprintf(buffer,
"%.1f bpm", lag2tempo(i));
516 if (i == n/2-1) feature.
label =
"";
517 else feature.
label = buffer;
524 int p0 = tempo2lag(t1);
525 int p1 = tempo2lag(t0);
527 std::map<float, int> candidates;
529 for (
int i = p0; i <= p1 && i+1 < n/2; ++i) {
531 if (m_fr[i] > m_fr[i-1] &&
532 m_fr[i] > m_fr[i+1]) {
538 candidates[m_fr[i]] = i;
545 feature.
values[0] = m_fr[i];
546 sprintf(buffer,
"%.1f bpm", lag2tempo(i));
547 if (i == p1 || i == n/2-2) feature.
label =
"";
548 else feature.
label = buffer;
552 if (candidates.empty()) {
553 cerr <<
"No tempo candidates!" << endl;
561 feature.
duration = m_lasttime - m_start;
566 std::map<float, int>::const_iterator ci = candidates.end();
568 int maxpi = ci->second;
570 if (m_t[maxpi] > 0) {
575 feature.
values[0] = m_t[maxpi];
582 feature.
values[0] = lag2tempo(maxpi);
583 cerr <<
"WARNING: No stored tempo for index " << maxpi << endl;
586 sprintf(buffer,
"%.1f bpm", feature.
values[0]);
587 feature.
label = buffer;
599 while (feature.
values.size() < 10) {
600 if (m_t[ci->second] > 0) {
601 feature.
values.push_back(m_t[ci->second]);
603 feature.
values.push_back(lag2tempo(ci->second));
605 if (ci == candidates.begin())
break;
618 m_d(new
D(inputSampleRate))
636 return "Simple Fixed Tempo Estimator";
642 return "Study a short section of audio and estimate its tempo, assuming the tempo is constant";
648 return "Vamp SDK Example Plugins";
660 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