15#include "dsp/hart_dsp_all.hpp"
16#include "dsp/hart_dsp_function.hpp"
18#include "matchers/hart_matcher.hpp"
19#include "matchers/hart_matcher_function.hpp"
24#include "signals/hart_signals_all.hpp"
51template <
typename SampleType>
60 template <
typename DSPType>
62 typename std::enable_if<
63 ! std::is_lvalue_reference<DSPType&&>::value &&
64 std::is_base_of<
DSPBase<SampleType>,
typename std::decay<DSPType>::type>::value
66 : m_processor (std::forward<DSPType> (dsp).move())
75 : m_processor (std::move (dsp))
84 if (sampleRateHz <= 0)
87 if (! m_processor->supportsSampleRate (sampleRateHz))
90 m_sampleRateHz = sampleRateHz;
98 if (blockSizeFrames == 0)
101 m_blockSizeFrames = blockSizeFrames;
112 paramValues.emplace_back (ParamValue { id, value });
120 if (durationSeconds < 0)
123 m_testDurationSeconds = durationSeconds;
133 m_dspPreparationBeforeWarmUp = dspPreparation;
143 m_signalPreparationBeforeWarmUp = signalPreparation;
162 double warmUpDurationSeconds,
167 if (warmUpDurationSeconds < 0)
170 m_warmUpDurationSeconds = warmUpDurationSeconds;
171 m_signalPreparationAfterWarmUp = signalPreparation;
172 m_dspPreparationAfterWarmUp = dspPreparation;
180 m_inputSignal = std::move (signal.copy());
188 m_inputSignal = std::move (signal.move());
197 m_inputSignal = std::move (signal);
219 std::function<
void (AudioBuffer<SampleType>&)> signalFunction,
220 const std::string& label = {},
224 std::move (signalFunction),
238 if (numInputChannels == 0)
241 if (numInputChannels > 128)
244 m_numInputChannels = numInputChannels;
254 if (numOutputChannels == 0)
257 if (numOutputChannels > 128)
260 m_numOutputChannels = numOutputChannels;
267 return this->withInputChannels (2);
273 return this->withOutputChannels (2);
279 return this->withInputChannels (1);
285 return this->withOutputChannels (1);
291 return this->withMonoInput().withMonoOutput();
297 return this->withStereoInput().withStereoOutput();
302 template<
typename MatcherType>
305 addCheck (std::forward<MatcherType> (matcher), SignalAssertionLevel::expect,
true);
311 template<
typename MatcherType>
314 addCheck (std::forward<MatcherType> (matcher), SignalAssertionLevel::expect,
false);
320 template<
typename MatcherType>
323 addCheck (std::forward<MatcherType> (matcher), SignalAssertionLevel::assert,
true);
329 template<
typename MatcherType>
332 addCheck (std::forward<MatcherType> (matcher), SignalAssertionLevel::assert,
false);
354 return expectTrue (
MatcherFunction<SampleType> (std::move (matcherFunction), label));
373 return expectTrue (
MatcherFunction<SampleType> (std::move (matcherFunction), label));
398 return expectTrue (
MatcherFunction<SampleType> (std::move (matcherFunction), label));
417 return expectFalse (
MatcherFunction<SampleType> (std::move (matcherFunction), label));
436 return expectFalse (
MatcherFunction<SampleType> (std::move (matcherFunction), label));
461 return expectFalse (
MatcherFunction<SampleType> (std::move (matcherFunction), label));
480 return assertTrue (
MatcherFunction<SampleType> (std::move (matcherFunction), label));
499 return assertTrue (
MatcherFunction<SampleType> (std::move (matcherFunction), label));
524 return assertTrue (
MatcherFunction<SampleType> (std::move (matcherFunction), label));
543 return assertFalse (
MatcherFunction<SampleType> (std::move (matcherFunction), label));
562 return assertFalse (
MatcherFunction<SampleType> (std::move (matcherFunction), label));
587 return assertFalse (
MatcherFunction<SampleType> (std::move (matcherFunction), label));
595 m_inputBufferSink = [&receivingBuffer] (AudioBuffer<SampleType>&& inputBuffer)
597 receivingBuffer = std::move (inputBuffer);
608 m_inputBufferSink = std::move (inputBufferSink);
624 m_saveOutputMode = mode;
625 m_saveOutputWavFormat = wavFormat;
634 m_outputBufferSink = [&receivingBuffer] (AudioBuffer<SampleType>&& outputBuffer)
636 receivingBuffer = std::move (outputBuffer);
647 m_outputBufferSink = std::move (outputBufferSink);
664 m_savePlotMode = mode;
674 m_inputSignalSink = [&receivingSignal] (std::unique_ptr<SignalBase<SampleType>>&& usedSignal)
676 receivingSignal = std::move (usedSignal);
688 m_inputSignalSink = std::move (inputSignalSink);
699 m_testLabel = testLabel;
707 const size_t warmUpDurationFrames =
roundToSizeT (m_sampleRateHz * m_warmUpDurationSeconds
);
708 const size_t testDurationFrames =
roundToSizeT (m_sampleRateHz * m_testDurationSeconds
);
710 if (testDurationFrames == 0 && warmUpDurationFrames == 0)
713 const bool perBlockChecksPreparationSuccessful = prepareChecks (perBlockChecks);
714 const bool fullSignalChecksPreparationSuccessful = prepareChecks (fullSignalChecks);
716 if (! perBlockChecksPreparationSuccessful || ! fullSignalChecksPreparationSuccessful)
717 return std::move (m_processor);
719 if (! m_processor->supportsSampleRate (m_sampleRateHz))
722 if (! m_processor->supportsChannelLayout (m_numInputChannels, m_numOutputChannels))
726 m_processor->reset();
729 m_processor->prepareWithEnvelopes (m_sampleRateHz, m_numInputChannels, m_numOutputChannels, m_blockSizeFrames);
731 for (
const ParamValue& paramValue : paramValues)
734 m_processor->setValue (paramValue.id, paramValue.value);
737 if (m_inputSignal ==
nullptr)
738 m_inputSignal = std::move (
hart::make_unique<
Silence<SampleType>>());
740 if (! m_inputSignal->supportsSampleRateWithDSPChain (m_sampleRateHz))
743 if (! m_inputSignal->supportsNumChannelsWithDSPChain (m_numInputChannels))
747 m_inputSignal->resetWithDSPChain();
750 m_inputSignal->prepareWithDSPChain (m_sampleRateHz, m_numInputChannels, m_blockSizeFrames);
755 while (offsetFrames < warmUpDurationFrames)
757 const size_t blockSizeFrames = std::min (m_blockSizeFrames, warmUpDurationFrames - offsetFrames);
759 hart::AudioBuffer<SampleType> inputBlock (m_numInputChannels, blockSizeFrames, m_sampleRateHz);
760 hart::AudioBuffer<SampleType> outputBlock (m_numOutputChannels, blockSizeFrames, m_sampleRateHz);
761 m_inputSignal->renderNextBlockWithDSPChain (inputBlock);
762 m_processor->processWithEnvelopes (inputBlock, outputBlock);
764 offsetFrames += blockSizeFrames;
768 m_processor->reset();
771 m_processor->prepareWithEnvelopes (m_sampleRateHz, m_numInputChannels, m_numOutputChannels, m_blockSizeFrames);
774 m_inputSignal->resetWithDSPChain();
777 m_inputSignal->prepareWithDSPChain (m_sampleRateHz, m_numInputChannels, m_blockSizeFrames);
779 AudioBuffer<SampleType> fullInputBuffer (m_numInputChannels, testDurationFrames, m_sampleRateHz);
780 AudioBuffer<SampleType> fullOutputBuffer (m_numOutputChannels, testDurationFrames, m_sampleRateHz);
781 bool atLeastOneCheckFailed =
false;
786 fullInputBuffer.fillWith (nan<SampleType>());
787 fullOutputBuffer.fillWith (nan<SampleType>());
790 while (offsetFrames < testDurationFrames)
794 const size_t blockSizeFrames = std::min (m_blockSizeFrames, testDurationFrames - offsetFrames);
796 hart::AudioBuffer<SampleType> inputBlock (m_numInputChannels, blockSizeFrames, m_sampleRateHz);
797 hart::AudioBuffer<SampleType> outputBlock (m_numOutputChannels, blockSizeFrames, m_sampleRateHz);
798 m_inputSignal->renderNextBlockWithDSPChain (inputBlock);
799 m_processor->processWithEnvelopes (inputBlock, outputBlock);
801 const bool allChecksPassed = processChecks (perBlockChecks, inputBlock, outputBlock, offsetFrames);
802 atLeastOneCheckFailed |= ! allChecksPassed;
804 for (size_t channel = 0; channel < m_numInputChannels; ++channel)
805 fullInputBuffer.copyFrom (channel, offsetFrames, inputBlock, channel, 0, blockSizeFrames);
807 for (size_t channel = 0; channel < m_numOutputChannels; ++channel)
808 fullOutputBuffer.copyFrom (channel, offsetFrames, outputBlock, channel, 0, blockSizeFrames);
810 offsetFrames += blockSizeFrames;
814 for (size_t channel = 0; channel < m_numInputChannels; ++channel)
816 const SampleType* channelData = fullInputBuffer[channel];
818 for (size_t frame = 0; frame < testDurationFrames; ++frame)
819 hassert (! std::isnan (channelData[frame]));
823 for (size_t channel = 0; channel < m_numOutputChannels; ++channel)
825 const SampleType* channelData = fullOutputBuffer[channel];
827 for (size_t frame = 0; frame < testDurationFrames; ++frame)
828 hassert (! std::isnan (channelData[frame]));
831 if (testDurationFrames != 0 && ! fullSignalChecks.empty())
833 const bool allChecksPassed = processChecks (fullSignalChecks, fullInputBuffer, fullOutputBuffer, warmUpDurationFrames);
834 atLeastOneCheckFailed |= ! allChecksPassed;
838 WavWriter<SampleType>::writeBuffer (fullOutputBuffer, m_saveOutputPath, m_saveOutputWavFormat);
841 plotData (fullInputBuffer, fullOutputBuffer, m_savePlotPath);
843 if (m_inputBufferSink !=
nullptr)
844 m_inputBufferSink (std::move (fullInputBuffer));
846 if (m_outputBufferSink !=
nullptr)
847 m_outputBufferSink (std::move (fullOutputBuffer));
849 if (m_inputSignalSink !=
nullptr)
850 m_inputSignalSink (std::move (m_inputSignal));
852 return std::move (m_processor);
862 enum class SignalAssertionLevel
871 SignalAssertionLevel signalAssertionLevel;
876 std::unique_ptr<
DSPBase<SampleType>> m_processor;
877 std::unique_ptr<SignalBase<SampleType>> m_inputSignal;
882 std::vector<ParamValue> paramValues;
884 double m_warmUpDurationSeconds = 0.0;
885 size_t offsetFrames = 0;
886 std::string m_testLabel = {};
893 std::vector<Check> perBlockChecks;
894 std::vector<Check> fullSignalChecks;
896 std::string m_saveOutputPath;
900 std::string m_savePlotPath;
903 std::function<
void (AudioBuffer<SampleType>&&)> m_inputBufferSink =
nullptr;
904 std::function<
void (AudioBuffer<SampleType>&&)> m_outputBufferSink =
nullptr;
905 std::function<
void (std::unique_ptr<SignalBase<SampleType>>&&)> m_inputSignalSink =
nullptr;
908 typename MatcherType,
909 typename =
typename std::enable_if<
911 typename std::decay<MatcherType>::type,
915 void addCheck (MatcherType&& matcher, SignalAssertionLevel assertionLevel,
bool shouldPass)
917 using Derived =
typename std::decay<MatcherType>::type;
918 static_assert (std::is_base_of<
MatcherBase<SampleType>, Derived>::value,
"matcher argument must derive from hart::Matcher");
920 const bool forceFullSignal = !shouldPass;
921 auto& group = (matcher.canOperatePerBlock() && !forceFullSignal)
927 std::forward<MatcherType>(matcher).move(),
934 void addCheck (
const MatcherBase<SampleType>& matcher, SignalAssertionLevel assertionLevel,
bool shouldPass)
936 const bool forceFullSignal = ! shouldPass;
937 auto& group = (matcher.canOperatePerBlock() && ! forceFullSignal)
942 group.push_back({ matcher.copy(), assertionLevel,
false, shouldPass });
945 bool prepareChecks (std::vector<Check>& checks)
947 for (
auto& check : checks)
949 if (! check.matcher->supportsSampleRate (m_sampleRateHz))
952 if (! check.matcher->supportsChannelLayout (m_numInputChannels, m_numOutputChannels))
955 check.matcher->prepareWithActiveChannels (m_sampleRateHz, m_numInputChannels, m_numOutputChannels, m_blockSizeFrames);
956 check.shouldSkip =
false;
962 bool processChecks (std::vector<Check>& checksGroup,
const AudioBuffer<SampleType>& inputAudio,
const AudioBuffer<SampleType>& outputAudio, size_t baseFrameOffset)
964 for (
auto& check : checksGroup)
966 if (check.shouldSkip)
969 auto& assertionLevel = check.signalAssertionLevel;
970 auto& matcher = check.matcher;
972 const AnalysisContext<SampleType> analysisContext (inputAudio, outputAudio);
973 const bool matchPassed = matcher->match (analysisContext);
975 if (matchPassed != check.shouldPass)
977 check.shouldSkip =
true;
979 if (assertionLevel == SignalAssertionLevel::assert)
981 std::stringstream stream;
982 stream << (check.shouldPass ?
"assertTrue() failed" :
"assertFalse() failed");
984 if (! m_testLabel.empty())
985 stream <<
" at \"" << m_testLabel <<
"\"";
987 stream << std::endl <<
"Condition: " << *matcher;
988 appendFailureDetails (stream, matcher->getFailureDetails(), inputAudio, outputAudio, baseFrameOffset);
994 std::stringstream stream;
995 stream << (check.shouldPass ?
"expectTrue() failed" :
"expectFalse() failed");
997 if (!m_testLabel.empty())
998 stream <<
" at \"" << m_testLabel <<
"\"";
1000 stream << std::endl <<
"Condition: " << * matcher;
1001 appendFailureDetails (stream, matcher->getFailureDetails(), inputAudio, outputAudio, baseFrameOffset);
1003 hart::ExpectationFailureMessages::get().emplace_back (stream.str());
1016 void appendFailureDetails (std::stringstream& stream,
const MatcherFailureDetails& details,
const AudioBuffer<SampleType>& inputAudio,
const AudioBuffer<SampleType>& observedOutputAudio, size_t baseFrameOffset)
1018 const size_t frameOverall = baseFrameOffset + details
.frame;
1019 const double timestampOverall =
static_cast<
double> (frameOverall) / m_sampleRateHz;
1020 const size_t warmUpDurationFrames = (size_t) std::round (m_sampleRateHz * m_warmUpDurationSeconds);
1021 const SampleType inputSampleValue = inputAudio[details
.channel][details
.frame];
1022 const SampleType outputSampleValue = observedOutputAudio[details
.channel][details
.frame];
1025 <<
"Input signal: " << *m_inputSignal << std::endl
1026 <<
"Channel: " << details
.channel << std::endl;
1028 if (warmUpDurationFrames == 0)
1031 <<
"Frame: " << frameOverall << std::endl
1032 <<
secPrecision <<
"Timestamp: " << timestampOverall <<
" seconds";
1036 const size_t framePostWarmUp = frameOverall - warmUpDurationFrames;
1037 const double timestampPostWarmUp =
static_cast<
double> (framePostWarmUp) / m_sampleRateHz;
1039 <<
"Frame (overall): " << frameOverall << std::endl
1040 <<
"Frame (post warm-up): " << framePostWarmUp << std::endl
1042 <<
"Timestamp (overall): " << timestampOverall <<
" seconds" << std::endl
1043 <<
"Timestamp (post warm-up): " << timestampPostWarmUp <<
" seconds";
1047 <<
linPrecision <<
"Input sample value: " << inputSampleValue
1048 <<
dbPrecision <<
" (" << ratioToDecibels (std::abs (inputSampleValue)) <<
" dB)" << std::endl
1049 <<
linPrecision <<
"Output sample value: " << outputSampleValue
1050 <<
dbPrecision <<
" (" << ratioToDecibels (std::abs (outputSampleValue)) <<
" dB)" << std::endl
1059template <
typename DSPType>
1062 return AudioTestBuilder<
typename std::decay<DSPType>::type::SampleTypePublicAlias> (std::forward<DSPType>(dsp));
1070template <
typename DSPType>
1073 using SampleType =
typename DSPType::SampleTypePublicAlias;
1162using hart::processAudioWith;
1190using hart::processAudioWith;
Contains audio-related artefacts useful for analysis by matchers.
A DSP host used for building and running tests inside a test case.
AudioTestBuilder & assertTrue(std::function< Condition(const AudioBuffer< SampleType > &)> matcherFunction, const std::string &label={})
Adds an "assert" check using a function matcher.
AudioTestBuilder & withInputSignal(std::function< void(AudioBuffer< SampleType > &)> signalFunction, const std::string &label={}, Loop loop=Loop::yes)
Sets the input signal using a function-based signal definition.
AudioTestBuilder & expectTrue(std::function< Condition(const AudioBuffer< SampleType > &)> matcherFunction, const std::string &label={})
Adds an "expect" check using a function matcher.
AudioTestBuilder & inMono()
Sets number of input and output channels to one.
AudioTestBuilder & saveInputTo(AudioBuffer< SampleType > &receivingBuffer)
Enables saving input audio to a provided buffer.
AudioTestBuilder & expectFalse(std::function< Condition(const AudioBuffer< SampleType > &)> matcherFunction, const std::string &label={})
Adds a reversed "expect" check using a function matcher.
AudioTestBuilder & withDspPreparation(Preparation dspPreparation)
Sets whether to call reset() and/or prepare() on DSP testee before rendering audio.
AudioTestBuilder & assertFalse(std::function< Condition(const AudioBuffer< SampleType > &, const AudioBuffer< SampleType > &)> matcherFunction, const std::string &label={})
Adds a reversed "assert" check using a function matcher.
AudioTestBuilder & expectFalse(std::function< Condition(const AudioBuffer< SampleType > &, const AudioBuffer< SampleType > &)> matcherFunction, const std::string &label={})
Adds a reversed "expect" check using a function matcher.
AudioTestBuilder & assertFalse(std::function< Condition(AnalysisContext< SampleType >)> matcherFunction, const std::string &label={})
Adds a reversed "assert" check using a function matcher.
AudioTestBuilder & withLabel(const std::string &testLabel)
Adds a label to the test.
AudioTestBuilder & withDuration(double durationSeconds)
Sets the total duration of the input signal to be processed.
AudioTestBuilder & withStereoInput()
Sets number of input channels to two.
AudioTestBuilder & expectFalse(MatcherType &&matcher)
Adds a reversed "expect" check using a Matcher object.
AudioTestBuilder & assertFalse(MatcherType &&matcher)
Adds a reversed "assert" check using a Matcher object.
AudioTestBuilder & withInputChannels(size_t numInputChannels)
Sets arbitrary number of input channels.
AudioTestBuilder & expectTrue(std::function< Condition(const AudioBuffer< SampleType > &, const AudioBuffer< SampleType > &)> matcherFunction, const std::string &label={})
Adds an "expect" check using a function matcher.
AudioTestBuilder & expectTrue(std::function< Condition(AnalysisContext< SampleType >)> matcherFunction, const std::string &label={})
Adds an "expect" check using a function matcher.
AudioTestBuilder(DSPType &&dsp, typename std::enable_if< ! std::is_lvalue_reference< DSPType && >::value &&std::is_base_of< DSPBase< SampleType >, typename std::decay< DSPType >::type >::value >::type *=0)
Moves the DSP instance into the host.
AudioTestBuilder & withSignalPreparation(Preparation signalPreparation)
Sets whether to call reset() and/or prepare() on the input Signal before rendering audio.
AudioTestBuilder(std::unique_ptr< DSPBase< SampleType > > dsp)
Transfers the DSP smart pointer into the host.
AudioTestBuilder & expectTrue(MatcherType &&matcher)
Adds an "expect" check using a Matcher object.
AudioTestBuilder & withSampleRate(double sampleRateHz)
Sets the sample rate for the test.
AudioTestBuilder & withInputSignal(SignalBase< SampleType > &&signal)
Sets the input signal for the test by moving it.
AudioTestBuilder & assertTrue(std::function< Condition(AnalysisContext< SampleType >)> matcherFunction, const std::string &label={})
Adds an "assert" check using a function matcher.
AudioTestBuilder & saveOutputTo(AudioBuffer< SampleType > &receivingBuffer)
Enables saving output audio to a provided buffer.
AudioTestBuilder & withInputSignal(std::unique_ptr< SignalBase< SampleType > > signal)
Sets the input signal for the test by transfering its smart pointer.
AudioTestBuilder & savePlotTo(const std::string &path, Save mode=Save::always)
Enables saving a plot to an SVG file.
AudioTestBuilder & saveInputSignalTo(std::unique_ptr< SignalBase< SampleType > > &receivingSignal)
Moves the input signal after the processing into the provided smart pointer.
AudioTestBuilder & withMonoOutput()
Sets number of output channels to one.
AudioTestBuilder & assertTrue(std::function< Condition(const AudioBuffer< SampleType > &, const AudioBuffer< SampleType > &)> matcherFunction, const std::string &label={})
Adds an "assert" check using a function matcher.
AudioTestBuilder & assertTrue(MatcherType &&matcher)
Adds an "assert" check using a Matcher object.
AudioTestBuilder & withValue(int id, double value)
Sets the initial param value for the tested DSP.
AudioTestBuilder & assertFalse(std::function< Condition(const AudioBuffer< SampleType > &)> matcherFunction, const std::string &label={})
Adds a reversed "assert" check using a function matcher.
AudioTestBuilder & withWarmUp(double warmUpDurationSeconds, Preparation signalPreparation=Preparation::none, Preparation dspPreparation=Preparation::none)
Adds a warm‑up period before the main test.
AudioTestBuilder & saveOutputTo(const std::string &path, Save mode=Save::always, WavFormat wavFormat=WavFormat::pcm24)
Enables saving output audio to a wav file.
AudioTestBuilder & withInputSignal(const SignalBase< SampleType > &signal)
Sets the input signal for the test by copying it.
AudioTestBuilder & saveInputTo(std::function< void(AudioBuffer< SampleType > &&)> inputBufferSink)
Enables saving input audio via provided callback.
AudioTestBuilder & withMonoInput()
Sets number of input channels to one.
AudioTestBuilder & saveOutputTo(std::function< void(AudioBuffer< SampleType > &&)> outputBufferSink)
Enables saving output audio via provided callback.
AudioTestBuilder & withStereoOutput()
Sets number of output channels to two.
AudioTestBuilder & inStereo()
Sets number of input and output channels to two.
AudioTestBuilder & withOutputChannels(size_t numOutputChannels)
Sets arbitrary number of output channels.
std::unique_ptr< DSPBase< SampleType > > process()
Performs the test.
AudioTestBuilder & withBlockSize(size_t blockSizeFrames)
Sets the block size for the test.
AudioTestBuilder & saveInputSignalTo(std::function< void(std::unique_ptr< SignalBase< SampleType > > &&)> inputSignalSink)
Moves the input signal after the processing via provided callback.
AudioTestBuilder & expectFalse(std::function< Condition(AnalysisContext< SampleType >)> matcherFunction, const std::string &label={})
Adds a reversed "expect" check using a function matcher.
Thrown when a numbers of channels is mismatched.
A class representing some condition.
Polymorphic base for all DSP.
A DSP processor defined by a user-provided function.
Polymorphic base for all matchers.
Matcher defined by a user-provided function.
Thrown when sample rate is mismatched or invalid.
Signal defined by a user-provided function.
Thrown when an unexpected container size is encountered.
Thrown by test asserts like HART_ASSERT_TRUE() and AudioTestBuilder::assertFalse()
Thrown when an inappropriate value is encountered.
Helper class for writing audio buffers to wav files.
#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 ...
std::ostream & linPrecision(std::ostream &stream)
Sets number of decimal places for linear (sample) values.
std::ostream & secPrecision(std::ostream &stream)
Sets number of decimal places for values in seconds.
std::ostream & dbPrecision(std::ostream &stream)
Sets number of decimal places for values in decibels.
AudioTestBuilder< double > processAudioWith(std::function< void(const AudioBuffer< double > &, AudioBuffer< double > &)> dspFunction, const std::string &label={})
See the description of the float version of this function.
ResetSignal
Determines whether to reset the Signal in a given context.
AudioTestBuilder< float > processAudioWith(std::function< void(const AudioBuffer< float > &, AudioBuffer< float > &)> dspFunction, const std::string &label={})
Call this to start building your test using a block-wise non-replacing function.
Save
Determines when to save a file.
AudioTestBuilder< double > processAudioWith(std::function< double(double)> dspFunction, const std::string &label={})
See the description of the float version of this function.
AudioTestBuilder< typename std::decay< DSPType >::type::SampleTypePublicAlias > processAudioWith(DSPType &&dsp)
Call this to start building your test using a DSP object.
AudioTestBuilder< typename DSPType::SampleTypePublicAlias > processAudioWith(std::unique_ptr< DSPType > &&dsp)
Call this to start building your test using a smart pointer to a DSP object.
AudioTestBuilder< float > processAudioWith(std::function< float(float)> dspFunction, const std::string &label={})
Call this to start building your test using a sample-wise function.
AudioTestBuilder< float > processAudioWith(std::function< void(AudioBuffer< float > &)> dspFunction, const std::string &label={})
Call this to start building your test using a block-wise in-place function.
AudioTestBuilder< double > processAudioWith(std::function< void(AudioBuffer< double > &)> dspFunction, const std::string &label={})
See the description of the float version of this function.
@ no
The signal will continue from whatever state it was in.
@ yes
The signal's state will be reset.
@ whenFails
File will be saved only when the test has failed.
@ never
File will not be saved.
@ always
File will be saved always, after the test is performed.
static size_t roundToSizeT(SampleType x)
Rounds a floating point value to a size_t value.
std::unique_ptr< ObjectType > make_unique(Args &&... args)
std::make_unique() replacement for C++11
static std::string toAbsolutePath(const std::string &path)
Converts path to absolute, if it's relative.
Loop
Helper values for something that could loop, like a Signal.
Preparation
Describes whether to call reset() and/or prepare() before rendering through DSP or a Signal.
WavFormat
Audio data storage format for the wav files.
Holds values set by the user via CLI interface.
double getDefaultRenderDurationSeconds() const
size_t getDefaultNumOutputChannels() const
size_t getDefaultNumInputChannels() const
double getDefaultSampleRateHz() const
size_t getGefaultBlockSizeFrames() const
static CLIConfig & getInstance()
Get the singleton instance.
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.