8#include "metrics/hart_metric_query.hpp"
9#include "metrics/hart_metrics_common.hpp"
63 typename MetricQuery<
double>::SingleChannelMetricEvaluator evaluator =
65 (size_t channel,
const Slice& slice,
Unit requestedUnit)
78 const size_t startBin = binIndices.first;
79 const size_t stopBin = binIndices.second;
81 if (slice
.isEmpty() || stopBin - startBin == 0)
87 const std::complex<
double>* bins = spectrum
[channel
];
88 double maxSquaredMagnitude = 0.0;
89 size_t binOfMaxSquaredMagnitude = 0;
91 for (size_t currentBin = startBin; currentBin < stopBin; ++currentBin)
93 const double currentSquaredMagnitude = std::norm (bins[currentBin]);
95 if (currentSquaredMagnitude > maxSquaredMagnitude)
97 maxSquaredMagnitude = currentSquaredMagnitude;
98 binOfMaxSquaredMagnitude = currentBin;
103 if (binOfMaxSquaredMagnitude == 0 || binOfMaxSquaredMagnitude == spectrum
.getNumBins() - 1)
114 const auto tau = [] (
double x) ->
double
116 constexpr double sqrtTwoThirds = 0.816496580927726;
117 constexpr double sqrtSixBy24 = 0.10206207261596574;
119 const double p1 = std::log (3 * x * x + 6 * x + 1);
120 const double part1 = x + 1 - sqrtTwoThirds;
121 const double part2 = x + 1 + sqrtTwoThirds;
122 const double p2 = std::log (part1 / part2);
124 return (0.25 * p1 - sqrtSixBy24 * p2);
127 const size_t k = binOfMaxSquaredMagnitude;
128 const double n =
static_cast<
double> (spectrum
.getFFTSize());
131 const double divider = std::norm (bins[k]);
132 const double ap = (bins[k + 1].real() * bins[k].real() + bins[k + 1].imag() * bins[k].imag()) / divider;
133 const double dp = -ap / (1.0 - ap);
134 const double am = (bins[k-1].real() * bins[k].real() + bins[k-1].imag() * bins[k].imag()) / divider;
135 const double dm = am / (1.0 - am);
136 const double d = 0.5 * (dp + dm) + tau (dp * dp) - tau (dm * dm);
138 const double adjustedBinLocation =
static_cast<
double> (k) + d;
139 const double peakFreqAdjusted = (sampleRateHz * adjustedBinLocation / n);
141 return peakFreqAdjusted;
146 std::move (evaluator)
,
Manages the metrics calculations.
MetricQuery(SingleChannelMetricEvaluator evaluator, size_t totalNumChannels, std::vector< size_t > &&defaultChannelsToProcess)
Create a metric query object for a metric that operates on one channel at a time.
Thrown when sample rate is mismatched.
Frequency-domain representation of a multi-channel audio signal.
const std::complex< double > * operator[](size_t channel) const
Returns pointer to read-only magnitudes of a specific channel.
size_t getFFTSize() const
Returns FFT size.
double getSampleRateHz() const
Returns sample rate in Hz.
std::pair< size_t, size_t > getBinIndices(const Slice &slice) const
Returns a pair of indices representing a provided slice.
size_t getNumBins() const
Returns number of frequency bins per channel.
size_t getNumChannels() const
Returns number of channels.
Thrown when some metric is requested to return a value in an unsupported unit.
#define hassert(condition)
Triggers a HartAssertException if the condition is false
#define HART_THROW_OR_RETURN(ExceptionType, message, returnValue)
Throws an exception if HART_DO_NOT_THROW_EXCEPTIONS is set, prints a message and returns a specified ...
MetricQuery< double > quinns2(const Spectrum &spectrum)
Returns somewhat accurate loudest frequency in the spectrum.
FloatType nan()
Returns a quiet NaN value for the given floating-point type.
static SampleType floatsEqual(SampleType a, SampleType b, SampleType epsilon=(SampleType) 1e-8)
Compares two floating point numbers within a given tolerance.
Unit
Represents a physical unit.
@ native
Default (native) unit of whatever returns some value.
Helpers to generate common default channel subsets.
static std::vector< size_t > allChannels(size_t numChannels)
Represents a slice of analysis data.