8#include "metrics/hart_metric_query.hpp"
9#include "metrics/hart_metrics_common.hpp"
86template <
typename SampleType>
89 MetricQuery<
double>::SingleChannelMetricEvaluator evaluator =
91 (size_t channel,
Slice ,
Unit requestedUnit)
94 hassert (channel < ir.getNumChannels());
99 const size_t numFrames = ir.getNumFrames();
104 const SampleType* irChannelData = ir[channel];
107 std::vector<
double> energy (numFrames);
110 for (size_t i = numFrames; i-- > 0;)
112 const double sample =
static_cast<
double> (irChannelData[i]);
113 accumulatedEnergy
+= sample * sample;
117 const auto totalEnergy = energy[0];
119 if (totalEnergy <= 0.0)
122 const double sampleRateHz = ir.getSampleRateHz();
149 const FitRange fitRange (method);
161 std::size_t numPoints = 0;
162 bool lowerBoundWasReached =
false;
164 for (std::size_t i = 0; i < numFrames; ++i)
166 if (energy[i] <= 0.0)
169 const double decayDb = 10.0 * std::log10 (energy[i] / totalEnergy);
171 if (decayDb > fitRange.upperDb)
174 if (decayDb <= fitRange.lowerDb)
176 lowerBoundWasReached =
true;
180 const double timeSeconds =
static_cast<
double> (i) / sampleRateHz;
184 sumXX
+= timeSeconds * timeSeconds;
185 sumXY
+= timeSeconds * decayDb;
190 if (! lowerBoundWasReached)
200 const double n =
static_cast<
double> (numPoints);
207 hassert (slopeDbPerSecond < 0.0);
209 const double sixtyDbDecayTimeSeconds = -60.0 / slopeDbPerSecond;
211 switch (requestedUnit)
216 case Unit::frames:
return sixtyDbDecayTimeSeconds * sampleRateHz;
222 const size_t numChannels = ir.getNumChannels();
224 std::move (evaluator)
,
Implements Kahan algorithm for floating point accumulations.
SampleType getValue() const
AccurateSum & operator+=(SampleType value)
Adds a value to a sum, tracking the potential floating point error.
Container for representing an impulse response (IR)
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 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 > rt60(const ImpulseResponse< SampleType > &ir, RT60::Method method=RT60::Method::edt)
Estimates the RT60 reverberation time of an impulse response.
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.
Method
RT60 estimation method.
Unit
Represents a physical unit.
@ seconds
Time stamps, intervals, durations.
@ native
Default (native) unit of whatever returns some value.
@ frames
Value of something in frames (samples)
Helpers to generate common default channel subsets.
static std::vector< size_t > allChannels(size_t numChannels)
Represents a slice of analysis data.