43#include "../Core/DspMath.h"
89 void prepare(
double sampleRate,
double targetFreqHz,
int blockSize)
noexcept
91 assert(sampleRate > 0.0 &&
"Sample rate must be positive");
92 assert(blockSize > 0 &&
"Block size must be strictly positive");
93 assert(targetFreqHz >= 0.0 && targetFreqHz <= (sampleRate * 0.5) &&
"Frequency must be within Nyquist limit");
95 if (!std::isfinite(sampleRate) || sampleRate <= 0.0
96 || !std::isfinite(targetFreqHz) || blockSize <= 0)
99 sampleRate_ = sampleRate;
100 targetFreq_ = std::clamp(targetFreqHz, 0.0, sampleRate * 0.5);
101 blockSize_ = blockSize;
104 double omega = 2.0 * std::numbers::pi * targetFreq_ / sampleRate_;
106 coeff_ =
static_cast<T
>(2.0 * std::cos(omega));
107 cosOmega_ =
static_cast<T
>(std::cos(omega));
108 sinOmega_ =
static_cast<T
>(std::sin(omega));
113 const bool isDc = targetFreq_ <= 0.001;
114 const bool isNyquist = targetFreq_ >= sampleRate_ * 0.5 * (1.0 - 1e-12);
115 normalisationFactor_ = (isDc || isNyquist)
116 ?
static_cast<T
>(1.0 / blockSize_)
117 :
static_cast<T
>(2.0 / blockSize_);
133 if (data ==
nullptr || numSamples <= 0)
return;
138 const T coeff = coeff_;
140 for (
int i = 0; i < numSamples; ++i)
142 T s0 = data[i] + coeff * s1 - s2;
146 if (++sampleCount_ >= blockSize_)
148 computeResult(s1, s2);
168 T s0 = sample + coeff_ * s1_ - s2_;
172 if (++sampleCount_ >= blockSize_)
174 computeResult(s1_, s2_);
191 computeResult(s1_, s2_);
211 hasNewResult_ =
false;
223 return std::sqrt(real_ * real_ + imag_ * imag_);
232 return real_ * real_ + imag_ * imag_;
256 return std::atan2(imag_, real_);
283 hasNewResult_ =
false;
290 void computeResult(T s1, T s2)
noexcept
292 real_ = (s1 - s2 * cosOmega_) * normalisationFactor_;
293 imag_ = (s2 * sinOmega_) * normalisationFactor_;
294 hasNewResult_ =
true;
297 double sampleRate_ = 48000.0;
298 double targetFreq_ = 440.0;
299 int blockSize_ = 2048;
304 T normalisationFactor_ = T(0);
309 int sampleCount_ = 0;
314 bool hasNewResult_ =
false;
Single-frequency magnitude detector using the Goertzel algorithm.
double getSampleRate() const noexcept
Returns the configured sample rate in Hz.
T getPower() const noexcept
Returns the power at the target frequency.
void processBlock(const T *data, int numSamples) noexcept
Processes a block of audio samples, updating the internal state.
double getTargetFrequency() const noexcept
Returns the currently configured target frequency.
void reset() noexcept
Resets the internal IIR state and counters to zero.
void forceCompute() noexcept
Manually forces the computation of the result before N samples are reached.
T getPhase() const noexcept
Returns the phase angle at the target frequency.
bool checkNewResultAvailable() noexcept
Checks if a new result has been computed.
T getMagnitude() const noexcept
Returns the magnitude at the target frequency (linear scale).
int getBlockSize() const noexcept
Returns the configured analysis block size in samples.
bool pushSample(T sample) noexcept
Feeds a single sample into the running Goertzel computation.
T getMagnitudeDb() const noexcept
Returns the magnitude in decibels.
void prepare(double sampleRate, double targetFreqHz, int blockSize) noexcept
Prepares the detector for a specific frequency.
Main namespace for the DSPark framework.
T gainToDecibels(T gain, T minusInfinityDb=T(-100)) noexcept
Converts a linear gain value to decibels.