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") {
203 d.
sampleType = OutputDescriptor::VariableSampleRate;
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";
226 d.
sampleType = OutputDescriptor::FixedSampleRate;
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) {
534 if (m_fr[i] > m_fr[i-1] &&
535 m_fr[i] > m_fr[i+1]) {
541 candidates[m_fr[i]] = i;
548 feature.
values[0] = m_fr[i];
549 sprintf(buffer,
"%.1f bpm", lag2tempo(i));
550 if (i == p1 || i == n/2-2) feature.
label =
"";
551 else feature.
label = buffer;
555 if (candidates.empty()) {
556 cerr <<
"No tempo candidates!" << endl;
564 feature.
duration = m_lasttime - m_start;
569 std::map<float, int>::const_iterator ci = candidates.end();
571 int maxpi = ci->second;
573 if (m_t[maxpi] > 0) {
578 feature.
values[0] = m_t[maxpi];
585 feature.
values[0] = lag2tempo(maxpi);
586 cerr <<
"WARNING: No stored tempo for index " << maxpi << endl;
589 sprintf(buffer,
"%.1f bpm", feature.
values[0]);
590 feature.
label = buffer;
602 while (feature.
values.size() < 10) {
603 if (m_t[ci->second] > 0) {
604 feature.
values.push_back(m_t[ci->second]);
606 feature.
values.push_back(lag2tempo(ci->second));
608 if (ci == candidates.begin())
break;
621 m_d(new
D(inputSampleRate))
639 return "Simple Fixed Tempo Estimator";
645 return "Study a short section of audio and estimate its tempo, assuming the tempo is constant";
651 return "Vamp SDK Example Plugins";
663 return "Code copyright 2008 Queen Mary, University of London. Freely redistributable (BSD license)";
static int CandidatesOutput
static int FilteredACFOutput
size_t getPreferredBlockSize() const
float getParameter(string id) const
FeatureSet assembleFeatures()
OutputList getOutputDescriptors() const
void setParameter(string id, float value)
FeatureSet getRemainingFeatures()
FeatureSet process(const float *const *, RealTime)
float * m_priorMagnitudes
ParameterList getParameterDescriptors() const
Vamp::RealTime m_lasttime
bool initialise(size_t channels, size_t stepSize, size_t blockSize)
size_t getPreferredStepSize() const
virtual ~FixedTempoEstimator()
std::string getIdentifier() const
Get the computer-usable name of the plugin.
FeatureSet process(const float *const *inputBuffers, Vamp::RealTime timestamp)
Process a single block of input data.
int getPluginVersion() const
Get the version number of the plugin.
FixedTempoEstimator(float inputSampleRate)
std::string getCopyright() const
Get the copyright statement or licensing summary for the plugin.
FeatureSet getRemainingFeatures()
After all blocks have been processed, calculate and return any remaining features derived from the co...
ParameterList getParameterDescriptors() const
Get the controllable parameters of this plugin.
std::string getDescription() const
Get a human-readable description for the plugin, typically a line of text that may optionally be disp...
std::string getMaker() const
Get the name of the author or vendor of the plugin in human-readable form.
void setParameter(std::string id, float value)
Set a named parameter.
size_t getPreferredBlockSize() const
Get the preferred block size (window size – the number of sample frames passed in each block to the p...
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,...
std::string getName() const
Get a human-readable name or title of the plugin.
void reset()
Reset the plugin after use, to prepare it for another clean run.
size_t getPreferredStepSize() const
Get the preferred step size (window increment – the distance in sample frames between the start frame...
float getParameter(std::string id) const
Get the value of a named parameter.
OutputList getOutputDescriptors() const
Get the outputs of this plugin.
std::vector< ParameterDescriptor > ParameterList
virtual size_t getMaxChannelCount() const
Get the maximum supported number of input channels.
Plugin(float inputSampleRate)
std::vector< OutputDescriptor > OutputList
std::map< int, FeatureList > FeatureSet
virtual size_t getMinChannelCount() const
Get the minimum supported number of input channels.
std::string name
The human-readable name of the parameter.
std::string identifier
The name of the parameter, in computer-usable form.
std::string unit
The unit of the parameter, in human-readable form.
std::string description
A human-readable short text describing the parameter.
bool isQuantized
True if the parameter values are quantized to a particular resolution.
float minValue
The minimum value of the parameter.
float maxValue
The maximum value of the parameter.
float defaultValue
The default value of the parameter.
bool hasDuration
True if an output feature has a specified duration.
std::vector< float > values
Results for a single sample of this feature.
std::string label
Label for the sample of this feature.
bool hasTimestamp
True if an output feature has its own timestamp.
RealTime timestamp
Timestamp of the output feature.
RealTime duration
Duration of the output feature.
SampleType sampleType
Positioning in time of the output results.
bool isQuantized
True if the output values are quantized to a particular resolution.
float quantizeStep
Quantization resolution of the output values (e.g.
float maxValue
Maximum value of the results in the output.
std::string unit
The unit of the output, in human-readable form.
bool hasDuration
True if the returned results for this output are known to have a duration field.
std::string name
The human-readable name of the output.
float minValue
Minimum value of the results in the output.
float sampleRate
Sample rate of the output results, as samples per second.
std::string identifier
The name of the output, in computer-usable form.
bool hasKnownExtents
True if the results in each output bin fall within a fixed numeric range (minimum and maximum values)...
bool hasFixedBinCount
True if the output has the same number of values per sample for every output sample.
std::string description
A human-readable short text describing the output.
size_t binCount
The number of values per result of the output.
RealTime represents time values to nanosecond precision with accurate arithmetic and frame-rate conve...