26#include "../Core/DspMath.h"
68 void prepare(
double sampleRate,
double targetFreqHz,
int blockSize)
noexcept
70 assert(sampleRate > 0.0 &&
"Sample rate must be positive");
71 assert(blockSize > 0 &&
"Block size must be strictly positive");
72 assert(targetFreqHz >= 0.0 && targetFreqHz <= (sampleRate * 0.5) &&
"Frequency must be within Nyquist limit");
74 if (!std::isfinite(sampleRate) || sampleRate <= 0.0
75 || !std::isfinite(targetFreqHz) || blockSize <= 0)
78 sampleRate_ = sampleRate;
79 targetFreq_ = std::clamp(targetFreqHz, 0.0, sampleRate * 0.5);
80 blockSize_ = blockSize;
83 double omega = 2.0 * std::numbers::pi * targetFreq_ / sampleRate_;
85 coeff_ =
static_cast<T
>(2.0 * std::cos(omega));
86 cosOmega_ =
static_cast<T
>(std::cos(omega));
87 sinOmega_ =
static_cast<T
>(std::sin(omega));
92 const bool isDc = targetFreq_ <= 0.001;
93 const bool isNyquist = targetFreq_ >= sampleRate_ * 0.5 * (1.0 - 1e-12);
94 normalisationFactor_ = (isDc || isNyquist)
95 ?
static_cast<T
>(1.0 / blockSize_)
96 :
static_cast<T
>(2.0 / blockSize_);
112 if (data ==
nullptr || numSamples <= 0)
return;
117 const T coeff = coeff_;
119 for (
int i = 0; i < numSamples; ++i)
121 T s0 = data[i] + coeff * s1 - s2;
125 if (++sampleCount_ >= blockSize_)
127 computeResult(s1, s2);
147 T s0 = sample + coeff_ * s1_ - s2_;
151 if (++sampleCount_ >= blockSize_)
153 computeResult(s1_, s2_);
170 computeResult(s1_, s2_);
190 hasNewResult_ =
false;
202 return std::sqrt(real_ * real_ + imag_ * imag_);
211 return real_ * real_ + imag_ * imag_;
235 return std::atan2(imag_, real_);
262 hasNewResult_ =
false;
269 void computeResult(T s1, T s2)
noexcept
271 real_ = (s1 - s2 * cosOmega_) * normalisationFactor_;
272 imag_ = (s2 * sinOmega_) * normalisationFactor_;
273 hasNewResult_ =
true;
276 double sampleRate_ = 48000.0;
277 double targetFreq_ = 440.0;
278 int blockSize_ = 2048;
283 T normalisationFactor_ = T(0);
288 int sampleCount_ = 0;
293 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.