8#include "matchers/hart_matcher.hpp"
10#include "signals/hart_signal.hpp"
22template<
typename SampleType>
33 EqualsTo (std::unique_ptr<SignalBase<SampleType>>&& referenceSignal,
double toleranceLinear = (SampleType) 1e-5):
34 m_referenceSignal (std::move (referenceSignal)),
35 m_toleranceLinear ((SampleType) toleranceLinear)
45 EqualsTo (
const SignalBase<SampleType>& referenceSignal,
double toleranceLinear = (SampleType) 1e-5):
46 EqualsTo (referenceSignal.copy(), toleranceLinear)
56 EqualsTo (SignalBase<SampleType>&& referenceSignal,
double toleranceLinear = (SampleType) 1e-5):
57 EqualsTo (referenceSignal.move(), toleranceLinear)
63 m_referenceSignal (std::move (other.m_referenceSignal)),
64 m_toleranceLinear (other.m_toleranceLinear)
70 m_referenceSignal (other.m_referenceSignal !=
nullptr ? other.m_referenceSignal->copy() :
nullptr),
71 m_toleranceLinear (other.m_toleranceLinear)
82 m_referenceSignal = other.m_referenceSignal !=
nullptr ? other.m_referenceSignal->copy() :
nullptr;
83 m_toleranceLinear = other.m_toleranceLinear;
97 m_referenceSignal = std::move(other.m_referenceSignal);
98 m_toleranceLinear = other.m_toleranceLinear;
105 void prepare (
double sampleRateHz, size_t , size_t numOutputChannels, size_t maxBlockSizeFrames)
override
107 m_maxBlockSizeFrames = maxBlockSizeFrames;
108 m_referenceOutputAudio =
AudioBuffer<SampleType> (numOutputChannels, maxBlockSizeFrames, sampleRateHz);
109 m_referenceSignal->prepareWithDSPChain (sampleRateHz, numOutputChannels, maxBlockSizeFrames);
114 const AudioBuffer<SampleType>& observedOutputAudio = context.outputAudio();
116 if (observedOutputAudio.getNumFrames() <= m_maxBlockSizeFrames)
120 if (m_referenceOutputAudio.getNumFrames() != observedOutputAudio.getNumFrames())
121 m_referenceOutputAudio.setNumFrames (observedOutputAudio.getNumFrames());
123 m_referenceSignal->renderNextBlockWithDSPChain (m_referenceOutputAudio);
133 AudioBuffer<SampleType> fullOutputBuffer (observedOutputAudio.getNumChannels(), 0, observedOutputAudio.getSampleRateHz());
134 const size_t totalDurationFrames = observedOutputAudio.getNumFrames();
135 size_t offsetFrames = 0;
137 while (offsetFrames < totalDurationFrames)
139 const size_t blockSizeFrames = std::min (m_maxBlockSizeFrames, totalDurationFrames - offsetFrames);
141 if (m_referenceOutputAudio.getNumFrames() != blockSizeFrames)
142 m_referenceOutputAudio.setNumFrames (blockSizeFrames);
144 m_referenceSignal->renderNextBlockWithDSPChain (m_referenceOutputAudio);
145 fullOutputBuffer.appendFrom (m_referenceOutputAudio);
147 offsetFrames += blockSizeFrames;
150 m_referenceOutputAudio = std::move (fullOutputBuffer);
154 hassert (m_referenceOutputAudio.getNumFrames() == observedOutputAudio.getNumFrames());
155 hassert (m_referenceOutputAudio.getNumChannels() == observedOutputAudio.getNumChannels());
156 hassert (floatsEqual (m_referenceOutputAudio.getSampleRateHz(), observedOutputAudio.getSampleRateHz()));
158 for (size_t channel = 0; channel < m_referenceOutputAudio.getNumChannels(); ++channel)
160 if (!
this->appliesToChannel (channel))
163 for (size_t frame = 0; frame < m_referenceOutputAudio.getNumFrames(); ++frame)
165 if (notEqual (observedOutputAudio[channel][frame], m_referenceOutputAudio[channel][frame]))
167 m_failedFrame = frame;
168 m_failedChannel = (
int) channel;
169 m_failedObservedValue = observedOutputAudio[channel][frame];
170 m_failedExpectedValue = m_referenceOutputAudio[channel][frame];
186 return m_referenceSignal->supportsNumChannelsWithDSPChain (numOutputChannels);
191 return m_referenceSignal->supportsSampleRateWithDSPChain (sampleRateHz);
196 m_referenceSignal->resetWithDSPChain();
201 const SampleType m_differenceLinear = std::abs (m_failedExpectedValue - m_failedObservedValue);
202 std::stringstream stream;
203 stream <<
linPrecision <<
"Expected sample value: " << m_failedExpectedValue
204 <<
dbPrecision <<
" (" << ratioToDecibels (m_failedExpectedValue) <<
" dB)"
205 <<
linPrecision <<
", difference: " << m_differenceLinear
206 <<
dbPrecision <<
" (" << ratioToDecibels (m_differenceLinear) <<
" dB)";
209 details
.frame = m_failedFrame;
217 stream <<
"EqualsTo (" << *m_referenceSignal
222 std::unique_ptr<SignalBase<SampleType>> m_referenceSignal;
223 const SampleType m_toleranceLinear;
225 size_t m_maxBlockSizeFrames = 0;
228 size_t m_failedFrame = 0;
229 size_t m_failedChannel = 0;
230 SampleType m_failedObservedValue = (SampleType) 0;
231 SampleType m_failedExpectedValue = (SampleType) 0;
233 inline bool notEqual (SampleType x, SampleType y)
235 return std::abs (x - y) > m_toleranceLinear;
Contains audio-related artefacts useful for analysis by matchers.
Container for audio data.
Checks whether the audio is identical to some signal.
bool supportsSampleRate(double sampleRateHz) const override
Tells whether this Matcher supports given sample rate.
EqualsTo(std::unique_ptr< SignalBase< SampleType > > &&referenceSignal, double toleranceLinear=(SampleType) 1e-5)
Creates a matcher for a specific signal by transfering smart pointer details The reference signal can...
EqualsTo(SignalBase< SampleType > &&referenceSignal, double toleranceLinear=(SampleType) 1e-5)
Creates a matcher for a specific signal by moving it details The reference signal can be something si...
~EqualsTo() override=default
bool supportsChannelLayout(size_t, size_t numOutputChannels) const override
Tells the host whether this Matcher is capable of operating on audio with a specific number of channe...
void represent(std::ostream &stream) const override
Makes a text representation of this Matcher for test failure outputs.
EqualsTo & operator=(const EqualsTo &other)
bool match(AnalysisContext< SampleType > context) override
Tells the host if the piece of audio satisfies Matcher's condition or not.
EqualsTo(const SignalBase< SampleType > &referenceSignal, double toleranceLinear=(SampleType) 1e-5)
Creates a matcher for a specific signal by copying it details The reference signal can be something s...
EqualsTo(EqualsTo &&other) noexcept
void prepare(double sampleRateHz, size_t, size_t numOutputChannels, size_t maxBlockSizeFrames) override
Prepare for processing It is guaranteed that all subsequent process() calls will be in line with the ...
bool canOperatePerBlock() const override
Tells the host if it can operate on a block-by-block basis.
virtual MatcherFailureDetails getFailureDetails() const override
Returns a description of why the match has failed.
EqualsTo(const EqualsTo &other)
void reset() override
Resets the matcher to its initial state.
EqualsTo & operator=(EqualsTo &&other) noexcept
#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 & dbPrecision(std::ostream &stream)
Sets number of decimal places for values in decibels.
#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.