9#include "metrics/hart_metric_query.hpp"
10#include "metrics/hart_metrics_common.hpp"
108template <
typename SampleType>
112 double maxLagSeconds,
116 if (maxLagSeconds < 0.0)
119 if ((bufferA.hasSampleRate() || bufferB.hasSampleRate()) && bufferA.getSampleRateHz() != bufferB.getSampleRateHz())
122 typename MetricQuery<
double>::ChannelPairMetricEvaluator evaluator =
123 [&bufferA, &bufferB, maxLagSeconds, searchMode]
124 (size_t channelA,size_t channelB,
Slice slice,
Unit requestedUnit)
128 hassert (channelA < bufferA.getNumChannels());
129 hassert (channelB < bufferB.getNumChannels());
137 const auto sliceFrameIndices = bufferA.getFrameIndices (slice);
138 const size_t sliceStart = sliceFrameIndices.first;
139 const size_t sliceStop = sliceFrameIndices.second;
140 hassert (sliceStop > sliceStart);
141 hassert (sliceStop <= bufferA.getNumFrames());
142 hassert (sliceStop <= bufferB.getNumFrames());
144 const size_t numFrames = sliceStop - sliceStart;
147 const double sampleRateHz = bufferA.getSampleRateHz();
148 const size_t maxLagFrames =
roundToSizeT (maxLagSeconds * sampleRateHz
);
150 const SampleType* x = bufferA[channelA] + sliceStart;
151 const SampleType* y = bufferB[channelB] + sliceStart;
154 bool hadValidOverlap =
false;
156 for (
int lag = -
static_cast<
int> (maxLagFrames); lag <=
static_cast<
int> (maxLagFrames); ++lag)
158 const bool lagIsNegative = lag < 0;
159 const size_t lagAbsFrames =
static_cast<size_t> (lagIsNegative ? -lag : lag);
161 if (lagAbsFrames >= numFrames)
164 const size_t xBegin = lagIsNegative ? lagAbsFrames : 0;
165 const size_t yBegin = lagIsNegative ? 0 : lagAbsFrames;
166 const size_t overlapFrames = numFrames - lagAbsFrames;
172 for (size_t frame = 0; frame < overlapFrames; ++frame)
174 const double xn =
static_cast<
double> (x[xBegin + frame]);
175 const double yn =
static_cast<
double> (y[yBegin + frame]);
177 dotProduct
+= xn * yn;
178 sumSquaresX
+= xn * xn;
179 sumSquaresY
+= yn * yn;
188 hadValidOverlap =
true;
189 const double correlation = dotProduct
.getValue() / std::sqrt (energyX * energyY);
193 if (correlation > bestCorrelation)
194 bestCorrelation = correlation;
198 if (std::abs (correlation) > std::abs (bestCorrelation))
199 bestCorrelation = correlation;
206 if (! hadValidOverlap)
209 return bestCorrelation;
212 const size_t numPairs = std::min (bufferA.getNumChannels(), bufferB.getNumChannels());
214 std::move (evaluator),
215 bufferA.getNumChannels(),
216 bufferB.getNumChannels(),
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 audio data.
Manages the metrics calculations.
Thrown when sample rate is mismatched.
Thrown when some metric is requested to return a value in an unsupported unit.
Thrown when an inappropriate value is encountered.
#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 > maxCrossCorrelation(const AudioBuffer< SampleType > &bufferA, const AudioBuffer< SampleType > &bufferB, double maxLagSeconds, CorrelationSearchMode searchMode=bestAbsoluteCorrelation)
Calculates maximum normalized cross-correlation between two audio buffers.
FloatType nan()
Returns a quiet NaN value for the given floating-point type.
static size_t roundToSizeT(SampleType x)
Rounds a floating point value to a size_t value.
constexpr double inf
Infinity.
static SampleType floatsEqual(SampleType a, SampleType b, SampleType epsilon=(SampleType) 1e-8)
Compares two floating point numbers within a given tolerance.
CorrelationSearchMode
Describes how to look for best cross-correlation.
@ bestAbsoluteCorrelation
Unit
Represents a physical unit.
@ native
Default (native) unit of whatever returns some value.
Helpers to generate common default channel subsets.
static std::vector< std::pair< size_t, size_t > > diagonalChannelPairs(size_t numChannels)
Represents a slice of analysis data.