HART  0.2.0
High level Audio Regression and Testing
Loading...
Searching...
No Matches
hart_peaksbelow.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cmath> // abs()
4#include <iomanip>
5#include <sstream>
6
8#include "matchers/hart_matcher.hpp"
9#include "hart_utils.hpp" // decibelsToRatio()
10
11namespace hart
12{
13
14/// @brief Checks whether the audio peaks below specific level
15/// @details This matcher will calculate peak value on a block-by-block basis.
16/// It checks where all selected channels peak collectively, not for each individual channel.
17/// To do more strict per channel checks, use multiple matchers with @ref atChannel(), so that
18/// each matcher only targets one specific channel.
19/// @note Tip: To check if the audio peaks @em above some level, just flip your assertion, e.g.
20/// @code expectFalse (PeaksBelow (-3_Db)) @endcode or @code assertFalse (PeaksBelow (-3_Db)) @endcode
21/// @attention It checks the sample peaks, not the inter-sample peaks (a popular metric in audio
22/// mastering community). Fon inter-sample peak checking, you can make your own custom Matcher..
23/// @ingroup Matchers
24template<typename SampleType>
26 public Matcher<SampleType, PeaksBelow<SampleType>>
27{
28public:
29 /// @brief Creates a matcher for a specific peak level
30 /// @param thresholdDb Expected sample peak threshold in decibels
31 /// @param toleranceLinear Absolute tolerance for comparing frames, in linear domain (not decibels)
32 PeaksBelow (double thresholdDb, double toleranceLinear = 1e-3):
33 m_thresholdDb ((SampleType) thresholdDb),
34 m_thresholdLinear (static_cast<SampleType> (decibelsToRatio (thresholdDb) + toleranceLinear))
35 {
36 }
37
38 void prepare (double /*sampleRateHz*/, size_t /* numChannels */, size_t /* maxBlockSizeFrames */) override {}
39
40 bool match (const AudioBuffer<SampleType>& /* inputAudio */, const AudioBuffer<SampleType>& observedOutputAudio) override
41 {
42 for (size_t channel = 0; channel < observedOutputAudio.getNumChannels(); ++channel)
43 {
44 if (! this->appliesToChannel (channel))
45 continue;
46
47 for (size_t frame = 0; frame < observedOutputAudio.getNumFrames(); ++frame)
48 {
49 const SampleType observedPeakLinear = std::abs (observedOutputAudio[channel][frame]);
50
51 if (observedPeakLinear > m_thresholdLinear)
52 {
53 m_failedFrame = frame;
54 m_failedChannel = channel;
55 m_observedPeakDb = ratioToDecibels (observedPeakLinear);
56 return false;
57 }
58 }
59 }
60
61 return true;
62 }
63
64 bool canOperatePerBlock() const override
65 {
66 return true;
67 }
68
70 {
71 std::stringstream stream;
72 stream << "Observed audio peaks at at least "
73 << dbPrecision << m_observedPeakDb << " dB";
74
76 details.frame = m_failedFrame;
77 details.channel = m_failedChannel;
78 details.description = stream.str();
79 return details;
80 }
81
82 void represent (std::ostream& stream) const override
83 {
84 stream << "PeaksBelow ("
85 << dbPrecision << m_thresholdDb << "_dB, "
86 << linPrecision << m_thresholdLinear << ')';
87 }
88
89private:
90 const SampleType m_thresholdDb;
91 const SampleType m_thresholdLinear;
92
93 size_t m_failedFrame = 0;
94 size_t m_failedChannel = 0;
95 SampleType m_observedPeakDb = (SampleType) 0;
96};
97
99
100} // namespace hart
Container for audio data.
Base for audio matchers.
Checks whether the audio peaks below specific level.
bool match(const AudioBuffer< SampleType > &, const AudioBuffer< SampleType > &observedOutputAudio) override
Tells the host if the piece of audio satisfies Matcher's condition or not.
void represent(std::ostream &stream) const override
Makes a text representation of this Matcher for test failure outputs.
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.
PeaksBelow(double thresholdDb, double toleranceLinear=1e-3)
Creates a matcher for a specific peak level.
void prepare(double, size_t, size_t) override
Prepare for processing It is guaranteed that all subsequent process() calls will be in line with the ...
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.
static SampleType decibelsToRatio(SampleType valueDb)
Converts dB to linear value (ratio)
#define HART_MATCHER_DECLARE_ALIASES_FOR(ClassName)
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.