8#include "matchers/hart_matcher.hpp"
9#include "metrics/hart_true_peak.hpp"
29template<
typename SampleType>
67 double numericToleranceLinear = 1e-3
70 m_thresholdDbTP (thresholdDbTP),
71 m_thresholdLinear (
static_cast<SampleType> (
decibelsToRatio (thresholdDbTP
) + numericToleranceLinear)),
72 m_oversamplingRatio (oversamplingRatio),
73 m_filterQuality (
static_cast<
typename TruePeak<SampleType>::FilterQuality> (filterQuality)),
74 m_strictness (strictness),
75 m_numericToleranceLinear (
static_cast<SampleType> (numericToleranceLinear)),
76 truePeakEstimator (oversamplingRatio, m_filterQuality)
80 void prepare (
double sampleRateHz, size_t , size_t numOutputChannels, size_t )
override
82 const size_t numActiveChannels =
this->getChannelFlags().numTrue();
83 hassert (numActiveChannels > 0);
84 hassert (numActiveChannels <= numOutputChannels);
86 truePeakEstimator.prepare (sampleRateHz, numActiveChannels);
87 m_sampleRateHz = sampleRateHz;
92 m_TruePeakLinear = (SampleType) 0;
93 truePeakEstimator.reset();
98 const AudioBuffer<SampleType>& observedOutputAudio = context.outputAudio();
100 const ChannelFlags channelFlags =
this->getChannelFlags();
101 const size_t numChannels = observedOutputAudio.getNumChannels();
104 std::vector<size_t> channels;
107 for (size_t channel = 0; channel < numChannels; ++channel)
108 if (channelFlags
[channel
] ==
true)
109 channels.push_back (channel);
111 const typename TruePeak<SampleType>::Result estimatorResult = truePeakEstimator.estimate (observedOutputAudio, std::move (channels));
112 m_TruePeakLinear = estimatorResult.valueLinear;
113 m_failedChannel = estimatorResult.channel;
114 m_failedFrame = estimatorResult.frame;
116 const bool matcherResult = ! isAboveRequiredThreshold (m_TruePeakLinear);
117 m_hasPassed &= matcherResult;
118 return matcherResult;
130 const double maximumUnderReadLinear =
static_cast<
double> (truePeakEstimator.getMaximumUnderReadLinear());
132 hassert (maximumUnderReadLinear <= 1.0);
135 const double observedPeakDbTP = ratioToDecibels (m_TruePeakLinear);
136 const double maximumMormalizedFrequencyHz = m_fNorm * m_sampleRateHz / 2;
138 std::ostringstream detailsStream;
140 <<
"Observed audio true peak is "
142 <<
dbPrecision << observedPeakDbTP <<
" dB TP), at frame "
143 << std::setprecision (4) << m_failedFrame
144 <<
"\nMaximum under-read at f_norm = " << std::setprecision (2) << m_fNorm
145 <<
hzPrecision <<
" (" << maximumMormalizedFrequencyHz <<
" Hz) is " << maximumUnderReadDb <<
" dB, "
146 << (m_strictness ==
Strictness::relaxed ?
"not " :
"") <<
"taken into account";
158 stream <<
"TruePeaksBelow ("
160 << m_oversamplingRatio <<
", "
161 << m_filterQuality <<
", "
162 << m_strictness <<
", "
166 friend std::ostream& operator<< (std::ostream& os,
Strictness strictness)
168 return os <<
"Strictness::" << (strictness ==
Strictness::relaxed ?
"relaxed" :
"strict");
171 friend std::ostream& operator<< (std::ostream& os,
FilterQuality filterQuality)
173 os <<
"FilterQuality::";
175 switch (filterQuality)
186 static constexpr double m_fNorm = 0.45;
187 const double m_thresholdDbTP;
188 const SampleType m_thresholdLinear;
190 const typename TruePeak<SampleType>::FilterQuality m_filterQuality;
192 const SampleType m_numericToleranceLinear;
194 SampleType m_TruePeakLinear =
static_cast<SampleType>(0);
195 TruePeak<SampleType> truePeakEstimator;
197 bool m_hasPassed =
true;
199 size_t m_failedChannel = 0;
204 std::vector<std::vector<SampleType>> m_history;
205 size_t m_historyIndex = 0;
206 size_t m_offsetFrames = 0;
209 std::vector<std::vector<SampleType>> m_phaseCoefficients;
211 inline bool isAboveRequiredThreshold (SampleType rectifiedPeakLinear)
214 ? rectifiedPeakLinear / truePeakEstimator.getMaximumUnderReadLinear() > m_thresholdLinear
215 : rectifiedPeakLinear > m_thresholdLinear;
Contains audio-related artefacts useful for analysis by matchers.
Container for audio data.
A set of boolean flags mapped to each audio channel.
bool operator[](size_t channel) const
Access the flag value for a specific channel.
size_t numTrue() const noexcept
Checks how many channels are marked with true
Checks whether the audio true-peaks below specific level.
void prepare(double sampleRateHz, size_t, size_t numOutputChannels, size_t) override
Prepare for processing It is guaranteed that all subsequent process() calls will be in line with the ...
MatcherFailureDetails getFailureDetails() const override
Returns a description of why the match has failed.
Strictness
Strictness to when it comes to decision on whether the signal is below a specific dB TP target.
@ strict
Numeric tolerance + estimated under-read.
@ relaxed
Numeric tolerance only.
FilterQuality
Number of taps of the internal poly-phase IIR filter.
void represent(std::ostream &stream) const override
Makes a text representation of this Matcher for test failure outputs.
bool match(AnalysisContext< SampleType > context) override
Tells the host if the piece of audio satisfies Matcher's condition or not.
bool canOperatePerBlock() const override
Tells the host if it can operate on a block-by-block basis.
void reset() override
Resets the matcher to its initial state.
TruePeaksBelow(double thresholdDbTP, Oversampling oversamplingRatio=Oversampling::x4, FilterQuality filterQuality=FilterQuality::low, Strictness strictness=Strictness::relaxed, double numericToleranceLinear=1e-3)
Creates a matcher for a specific true peak level.
#define hassert(condition)
Triggers a HartAssertException if the condition is false
std::ostream & linPrecision(std::ostream &stream)
Sets number of decimal places for linear (sample) values.
std::ostream & hzPrecision(std::ostream &stream)
Sets number of decimal places for values in hertz.
std::ostream & dbPrecision(std::ostream &stream)
Sets number of decimal places for values in decibels.
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.
static SampleType ratioToDecibels(SampleType valueLinear)
Converts linear value (ratio) to dB.
static SampleType decibelsToRatio(SampleType valueDb)
Converts dB to linear value (ratio)
static SampleType floatsEqual(SampleType a, SampleType b, SampleType epsilon=(SampleType) 1e-8)
Compares two floating point numbers within a given tolerance.
Oversampling
Oversampling ratio.
#define HART_MATCHER_DECLARE_ALIASES_FOR(ClassName)
Details about matcher failure.
size_t channel
Index of channel at which the failure was detected.
std::string description
Readable description of why the match has failed.
size_t frame
Index of frame at which the match has failed.