Provide the interpolated beat position

This commit is contained in:
Jean Pierre Cimalando 2020-11-15 11:23:02 +01:00
parent 04fdfc4de2
commit e31bf1381f
3 changed files with 32 additions and 20 deletions

View file

@ -64,12 +64,6 @@ T BeatClock::dequantize(qbeats_t qbeats)
} }
/// ///
BeatClock::BeatClock()
{
setSampleRate(config::defaultSampleRate);
setSamplesPerBlock(config::defaultSamplesPerBlock);
}
void BeatClock::clear() void BeatClock::clear()
{ {
beatsPerSecond_ = 2.0; beatsPerSecond_ = 2.0;
@ -99,7 +93,8 @@ void BeatClock::setSampleRate(double sampleRate)
void BeatClock::setSamplesPerBlock(unsigned samplesPerBlock) void BeatClock::setSamplesPerBlock(unsigned samplesPerBlock)
{ {
runningBeat_.resize(samplesPerBlock); runningBeatNumber_.resize(samplesPerBlock);
runningBeatPosition_.resize(samplesPerBlock);
runningBeatsPerBar_.resize(samplesPerBlock); runningBeatsPerBar_.resize(samplesPerBlock);
} }
@ -147,11 +142,11 @@ void BeatClock::setPlaying(unsigned delay, bool playing)
isPlaying_ = playing; isPlaying_ = playing;
} }
absl::Span<const int> BeatClock::getRunningBeat() absl::Span<const int> BeatClock::getRunningBeatNumber()
{ {
fillBufferUpTo(currentCycleFrames_); fillBufferUpTo(currentCycleFrames_);
return absl::MakeConstSpan(runningBeat_.data(), currentCycleFrames_); return absl::MakeConstSpan(runningBeatNumber_.data(), currentCycleFrames_);
} }
absl::Span<const int> BeatClock::getRunningBeatsPerBar() absl::Span<const int> BeatClock::getRunningBeatsPerBar()
@ -163,7 +158,8 @@ absl::Span<const int> BeatClock::getRunningBeatsPerBar()
void BeatClock::fillBufferUpTo(unsigned delay) void BeatClock::fillBufferUpTo(unsigned delay)
{ {
int *beatData = runningBeat_.data(); int *beatNumberData = runningBeatNumber_.data();
float *beatNumberPosition = runningBeatPosition_.data();
int *beatsPerBarData = runningBeatsPerBar_.data(); int *beatsPerBarData = runningBeatsPerBar_.data();
unsigned fill = currentCycleFill_; unsigned fill = currentCycleFill_;
@ -172,8 +168,10 @@ void BeatClock::fillBufferUpTo(unsigned delay)
beatsPerBarData[i] = sig.beatsPerBar; beatsPerBarData[i] = sig.beatsPerBar;
if (!isPlaying_) { if (!isPlaying_) {
for (; fill < delay; ++fill) for (; fill < delay; ++fill) {
beatData[fill] = 0; beatNumberData[fill] = 0;
beatNumberPosition[fill] = 0;
}
currentCycleFill_ = fill; currentCycleFill_ = fill;
return; return;
} }
@ -190,7 +188,9 @@ void BeatClock::fillBufferUpTo(unsigned delay)
mustApplyHostPos = false; mustApplyHostPos = false;
// quantization to nearest for prevention of rounding errors // quantization to nearest for prevention of rounding errors
beatData[fill] = dequantize<int>(quantize(clientPos.toBeats(sig))); double beats = clientPos.toBeats(sig);
beatNumberData[fill] = dequantize<int>(quantize(beats));
beatNumberPosition[fill] = static_cast<float>(beats);
} }
currentCycleFill_ = fill; currentCycleFill_ = fill;

View file

@ -5,6 +5,7 @@
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz // If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#pragma once #pragma once
#include "Buffer.h"
#include <absl/types/span.h> #include <absl/types/span.h>
#include <vector> #include <vector>
#include <iosfwd> #include <iosfwd>
@ -73,8 +74,6 @@ struct BBT {
class BeatClock { class BeatClock {
public: public:
BeatClock();
/** /**
* @brief Set the sample rate. * @brief Set the sample rate.
*/ */
@ -113,8 +112,20 @@ public:
void setPlaying(unsigned delay, bool playing); void setPlaying(unsigned delay, bool playing);
/** /**
* @brief Get the beat number for each frame of the current cycle. * @brief Get the beat number for each frame of the current cycle.
*
* This signal is quantized to a fixed resolution, such that it never
* suffers 1-off errors due to imprecision in the host time position.
*/ */
absl::Span<const int> getRunningBeat(); absl::Span<const int> getRunningBeatNumber();
/**
* @brief Get the beat position for each frame of the current cycle.
*
* This is a fractional equivalent of the beat number, however the beat
* boundaries can be traversed erratically due to approximation errors.
* If you need to perform work on exact beat transitions, prefer
* `getRunningBeatNumber` instead.
*/
absl::Span<const float> getRunningBeatPosition();
/** /**
* @brief Get the time signature numerator for each frame of the current cycle. * @brief Get the time signature numerator for each frame of the current cycle.
*/ */
@ -124,7 +135,7 @@ private:
void fillBufferUpTo(unsigned delay); void fillBufferUpTo(unsigned delay);
private: private:
double samplePeriod_ = 0; double samplePeriod_ { 1.0 / config::defaultSampleRate };
// quantization // quantization
typedef int64_t qbeats_t; typedef int64_t qbeats_t;
@ -150,8 +161,9 @@ private:
// plugin-side counter // plugin-side counter
BBT lastClientPos_; BBT lastClientPos_;
std::vector<int> runningBeat_; Buffer<int> runningBeatNumber_ { config::defaultSamplesPerBlock };
std::vector<int> runningBeatsPerBar_; Buffer<float> runningBeatPosition_ { config::defaultSamplesPerBlock };
Buffer<int> runningBeatsPerBar_ { config::defaultSamplesPerBlock };
}; };
} // namespace sfz } // namespace sfz

View file

@ -925,7 +925,7 @@ void Synth::renderBlock(AudioSpan<float> buffer) noexcept
constexpr bool metronomeEnabled = false; constexpr bool metronomeEnabled = false;
if (metronomeEnabled) { if (metronomeEnabled) {
impl.resources_.metronome.processAdding( impl.resources_.metronome.processAdding(
bc.getRunningBeat().data(), bc.getRunningBeatsPerBar().data(), bc.getRunningBeatNumber().data(), bc.getRunningBeatsPerBar().data(),
buffer.getChannel(0), buffer.getChannel(1), numFrames); buffer.getChannel(0), buffer.getChannel(1), numFrames);
} }