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>& observedAudio) override
41 {
42 for (size_t channel = 0; channel < observedAudio.getNumChannels(); ++channel)
43 {
44 if (! this->appliesToChannel (channel))
45 continue;
46
47 for (size_t frame = 0; frame < observedAudio.getNumFrames(); ++frame)
48 {
49 const SampleType observedPeakLinear = std::abs (observedAudio[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() override
65 {
66 return true;
67 }
68
69 void reset() override {}
70
72 {
73 std::stringstream stream;
74 stream << "Observed audio peaks at at least "
75 << dbPrecision << m_observedPeakDb << " dB";
76
78 details.frame = m_failedFrame;
79 details.channel = m_failedChannel;
80 details.description = stream.str();
81 return details;
82 }
83
84 void represent (std::ostream& stream) const override
85 {
86 stream << "PeaksBelow ("
87 << dbPrecision << m_thresholdDb << "_dB, "
88 << linPrecision << m_thresholdLinear << ')';
89 }
90
91private:
92 const SampleType m_thresholdDb;
93 const SampleType m_thresholdLinear;
94
95 size_t m_failedFrame = 0;
96 size_t m_failedChannel = 0;
97 SampleType m_observedPeakDb = (SampleType) 0;
98};
99
101
102} // namespace hart
Base for audio matchers.
Checks whether the audio peaks below specific level.
bool match(const AudioBuffer< SampleType > &observedAudio) 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() 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 ...
void reset() override
Resets the matcher to its initial state.
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.