| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef GARNET_BIN_MEDIA_AUDIO_CORE_MIXER_TEST_AUDIO_RESULT_H_ |
| #define GARNET_BIN_MEDIA_AUDIO_CORE_MIXER_TEST_AUDIO_RESULT_H_ |
| |
| #include <cmath> |
| |
| #include "garnet/bin/media/audio_core/mixer/constants.h" |
| #include "garnet/bin/media/audio_core/mixer/gain.h" |
| #include "garnet/bin/media/audio_core/mixer/test/frequency_set.h" |
| |
| namespace media { |
| namespace audio { |
| namespace test { |
| |
| // Audio measurements that are determined by various test cases throughout the |
| // overall set. These measurements are eventually displayed in an overall recap, |
| // after all other tests have completed. |
| // |
| // We perform frequency tests at various frequencies (kSummaryFreqs[] from |
| // frequency_set.h), storing the result for each frequency. |
| // |
| // Although these audio measurements are quantitative, there is no 'right |
| // answer' per se. Rather, we compare current measurements to those previously |
| // measured, to detect any fidelity regressions. Because the code being tested |
| // is largely mathematical (only dependencies being a few FBL functions), we |
| // will fail on ANY regression, since presumably an intentional change in our |
| // fidelity would contain in that same CL a change to these thresholds. |
| // |
| // All reference values and measured values are in decibels (+20dB => 10x magn). |
| // When comparing values to the below limits, a specified 'tolerance' refers to |
| // the maximum delta (positive OR negative) from reference value. For ALL OTHER |
| // limits (Noise Floor, FrequencyResponse, SignalToNoiseAndDistortion), values |
| // being assessed should be **greater than or equal to** the specified limit. |
| // |
| // We save previous results to 8-digit accuracy (>23 bits), exceeding float32 |
| // precision. This does not pose a risk of 'flaky test' since the math should |
| // be the same every time. With no real dependencies outside FBL, we expect |
| // any change that affects these results to be directly within the core |
| // objects (Mixer, Gain, OutputProducer), and the corresponding adjustments |
| // to these thresholds should be included with that CL. |
| // |
| // Measurements and thresholds grouped into stages (where our pipeline is |
| // represented by the 6 stages Input|Rechannel|Interpolate|Scale|Sum|Output). |
| class AudioResult { |
| public: |
| // |
| // |
| // Input |
| // |
| // For different input types (unsigned 8-bit int, signed-16, signed-24-in-32, |
| // float), we measure the translation from input signal to what is generated |
| // and deposited into the accumulator buffer. |
| // |
| // These variables store the worst-case difference (across multiple tests and |
| // frequencies) in decibels, between an input's result and the reference dB |
| // level. For certain low-frequencies, the frequency response exceeds 0 dBFS, |
| // and these variables store the worst-case measurement. |
| static double LevelToleranceSource8; |
| static double LevelToleranceSource16; |
| static double LevelToleranceSource24; |
| static double LevelToleranceSourceFloat; |
| |
| // Related to the above, these constants store the previous measurements. |
| // These are used as threshold limits -- if any current test EXCEEDS this |
| // tolerance, it is considered an error and causes the test case to fail. |
| static constexpr double kPrevLevelToleranceSource8 = 6.7219077e-02; |
| static constexpr double kPrevLevelToleranceSource16 = 1.0548786e-06; |
| static constexpr double kPrevLevelToleranceSource24 = 3.0346074e-09; |
| static constexpr double kPrevLevelToleranceSourceFloat = 5.3282082e-10; |
| |
| // These variables store the specific result magnitude (in dBFS) for the input |
| // type when a 1 kHz reference-frequency full-scale 0 dBFS signal is provided. |
| static double LevelSource8; |
| static double LevelSource16; |
| static double LevelSource24; |
| static double LevelSourceFloat; |
| |
| // Related to the above, if the current measurement (0 dBFS sinusoid at a |
| // single reference frequency) is LESS than the threshold constants listed |
| // below, it is considered an error and causes the test case to fail. |
| static constexpr double kPrevLevelSource8 = 0.0; |
| static constexpr double kPrevLevelSource16 = 0.0; |
| static constexpr double kPrevLevelSource24 = 0.0; |
| static constexpr double kPrevLevelSourceFloat = 0.0; |
| |
| // Noise floor is assessed by injecting a full-scale 1 kHz sinusoid, then |
| // measuring the root-sum-square strength of all the other frequencies besides |
| // 1 kHz. This strength is compared to a full-scale signal, with the result |
| // being a positive dBr value representing the difference between full-scale |
| // signal and noise floor. This test is performed at the same time as the |
| // above level test (which uses that same 1 kHz reference frequency), in the |
| // absence of rechannel/gain/SRC/mix. |
| |
| // These variables store the calculated dBFS noise floor for an input type. |
| // Here, a larger decibel value is more desirable. |
| static double FloorSource8; |
| static double FloorSource16; |
| static double FloorSource24; |
| static double FloorSourceFloat; |
| |
| // These constants store previous noise floors per input type. Any current |
| // measurement LESS than this threshold limit is considered a test failure. |
| static constexpr double kPrevFloorSource8 = 49.952957; |
| static constexpr double kPrevFloorSource16 = 98.104753; |
| static constexpr double kPrevFloorSource24 = 146.30926; |
| static constexpr double kPrevFloorSourceFloat = 153.74509; |
| |
| // |
| // |
| // Rechannel |
| // |
| // For mixer-provided rechannelization (currently just stereo-to-mono), we |
| // compare input signal to generated result from rechannelization processing. |
| // We assess result level accuracy and noise floor. |
| |
| // Worst-case measured tolerance, across potentially more than one test case. |
| static double LevelToleranceStereoMono; |
| // Previously-cached tolerance. If difference between input magnitude and |
| // result magnitude EXCEEDS this tolerance, then the test case fails. |
| static constexpr double kPrevLevelToleranceStereoMono = 2.9724227e-05; |
| |
| // Absolute output level measured in this test case. |
| static double LevelStereoMono; |
| // Previously-cached result that serves as a threshold limit. If result |
| // magnitude is LESS than this value, then the test case fails. |
| static constexpr double kPrevLevelStereoMono = -3.01029996; |
| |
| // Noise floor (in dBr) measured in this test case. |
| static double FloorStereoMono; |
| // Previously-cached noise floor that serves as a threshold limit. If result |
| // magnitude is LESS than this value, then the test case fails. |
| static constexpr double kPrevFloorStereoMono = 93.607405; |
| |
| // |
| // |
| // Interpolate |
| // |
| // Generally we test our interpolation fidelity using level response and |
| // SINAD, and we do so for all resamplers across a number of rate-conversion |
| // ratios and input frequencies. These rate-conversion ratios include: |
| // - 1:1 (referred to in these variables and constants as Unity) |
| // - 2:1, which equates to 96k -> 48k (referred to as Down1) |
| // - 294:160, which equates to 88.2k -> 48k (Down2) |
| // - 147:160, which equates to 44.1k -> 48k (Up1) |
| // - 1:2, which equates to 24k -> 48k, or 48k -> 96k (Up2) |
| // - 47999:48000, representing small adjustment for multi-device sync (Micro) |
| // |
| |
| // Worst-case measured tolerance, across potentially more than one test |
| // case. Compared to 1:1 accuracy (kLevelToleranceSourceFloat), |
| // LinearSampler boosts low-frequencies during any significant up-sampling |
| // (e.g. 1:2). In effect, this const represents how far above 0 dBFS we |
| // allow for those (any) freqs. |
| static double LevelToleranceInterpolation; |
| // Previously-cached tolerance. If difference between input magnitude and |
| // result magnitude EXCEEDS this tolerance, then the test case fails. |
| static constexpr double kPrevLevelToleranceInterpolation = 6.5187815e-05; |
| |
| // Frequency Response |
| // |
| // What is our received level (in dBFS), when sending sinusoids through our |
| // mixer at certain resampling ratios. PointSampler and LinearSampler are |
| // specifically targeted with resampling ratios that represent how the current |
| // system uses them. A more exhaustive set is available for in-depth testing |
| // outside of CQ (--full switch). In standard mode, we test PointSampler at |
| // 1:1 (no SRC) and 2:1 (96k-to-48k), and LinearSampler at 294:160 and 147:160 |
| // (e.g. 88.2k-to-48k and 44.1k-to-48k). Additional results are gathered if |
| // '--full' is specified. Our entire set of ratios is represented in the |
| // arrays listed below, referred to by these labels: Unity (1:1), Down1 (2:1), |
| // Down2 (294:160), Up1 (147:160), Up2 (1:2) and Micro (47999:48000). |
| |
| // For the specified resampler, and for the specified rate conversion, these |
| // are the currently-measured results (in dBFS) for level response at a set of |
| // reference frequencies. The input sinusoid is sent at 0 dBFS: thus, output |
| // results closer to 0 are better. |
| static std::array<double, FrequencySet::kNumReferenceFreqs> |
| FreqRespPointUnity; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> |
| FreqRespPointDown1; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> |
| FreqRespPointDown2; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> FreqRespPointUp1; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> FreqRespPointUp2; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> |
| FreqRespPointMicro; |
| |
| // Same as the above section, but for LinearSampler instead of PointSampler |
| static std::array<double, FrequencySet::kNumReferenceFreqs> |
| FreqRespLinearUnity; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> |
| FreqRespLinearDown1; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> |
| FreqRespLinearDown2; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> FreqRespLinearUp1; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> FreqRespLinearUp2; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> |
| FreqRespLinearMicro; |
| |
| // |
| // Val-being-checked (in dBFS) must be greater than or equal to this value. |
| // It also cannot be more than kPrevLevelToleranceInterpolation above 0.0db. |
| // For these 1:1 and N:1 ratios, PointSampler's frequency response is ideal |
| // (flat). It is actually very slightly positive (hence the tolerance check). |
| // |
| // Note: with rates other than N:1 or 1:N, interpolating resamplers dampen |
| // high frequencies -- as shown in previously-saved LinearSampler results. |
| // |
| // These are the previous-cached results for frequency response, for this |
| // sampler and this rate conversion. If any result magnitude is LESS than this |
| // value, then the test case fails. Ideal results are 0.0 for all. |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevFreqRespPointUnity; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevFreqRespPointDown1; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevFreqRespPointDown2; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevFreqRespPointUp1; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevFreqRespPointUp2; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevFreqRespPointMicro; |
| |
| // Same as the above section, but for LinearSampler instead of PointSampler |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevFreqRespLinearUnity; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevFreqRespLinearDown1; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevFreqRespLinearDown2; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevFreqRespLinearUp1; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevFreqRespLinearUp2; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevFreqRespLinearMicro; |
| |
| static std::array<double, FrequencySet::kNumReferenceFreqs> FreqRespPointNxN; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> FreqRespLinearNxN; |
| |
| // Signal-to-Noise-And-Distortion (SINAD) |
| // |
| // Sinad (signal-to-noise-and-distortion) is the ratio (in dBr) of reference |
| // signal as received (nominally from a 1kHz input), compared to the power of |
| // all OTHER frequencies (combined via root-sum-square). |
| // |
| // Distortion is often measured at one reference frequency (kReferenceFreq). |
| // We measure noise floor at only 1 kHz, and for summary SINAD tests use 40 |
| // Hz, 1 kHz and 12 kHz. For full-spectrum tests we test 47 frequencies. |
| // These arrays hold various SINAD results as measured during the test run. |
| // |
| // For the specified resampler, and for the specified rate conversion, these |
| // are the currently-measured SINAD results at a set of reference frequencies. |
| // The input sinusoid is a 0 dBFS sinusoid. Results are ratios of output- |
| // -signal-to-output-noise, measured in dBr, so larger values are better. |
| static std::array<double, FrequencySet::kNumReferenceFreqs> SinadPointUnity; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> SinadPointDown1; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> SinadPointDown2; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> SinadPointUp1; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> SinadPointUp2; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> SinadPointMicro; |
| |
| // Same as the above section, but for LinearSampler instead of PointSampler |
| static std::array<double, FrequencySet::kNumReferenceFreqs> SinadLinearUnity; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> SinadLinearDown1; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> SinadLinearDown2; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> SinadLinearUp1; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> SinadLinearUp2; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> SinadLinearMicro; |
| |
| // These are the previous-cached results for SINAD, for this sampler and this |
| // rate conversion, represented in dBr. If any current result magnitude is |
| // LESS than this value, then the test case fails. |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevSinadPointUnity; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevSinadPointDown1; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevSinadPointDown2; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevSinadPointUp1; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevSinadPointUp2; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevSinadPointMicro; |
| |
| // Same as the above section, but for LinearSampler instead of PointSampler |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevSinadLinearUnity; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevSinadLinearDown1; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevSinadLinearDown2; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevSinadLinearUp1; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevSinadLinearUp2; |
| static const std::array<double, FrequencySet::kNumReferenceFreqs> |
| kPrevSinadLinearMicro; |
| |
| // SINAD results measured for a few frequencies during the NxN tests. |
| static std::array<double, FrequencySet::kNumReferenceFreqs> SinadPointNxN; |
| static std::array<double, FrequencySet::kNumReferenceFreqs> SinadLinearNxN; |
| |
| // |
| // |
| // Scale |
| // |
| // The lowest (furthest-from-Unity) AScale with no observable attenuation on |
| // full-scale data (i.e. the smallest AScale indistinguishable from Unity). |
| // |
| // This const is determined by the number of precision bits in a float32. |
| // Conceptually, it is exactly (2^25 - 1) / (2^25) -- float32 contains 25 bits |
| // of precision, minus 1 for sign, plus 1 for rounding effects. At this value |
| // exactly (or slightly more, if it cannot be perfectly expressed in float32), |
| // all values effectly round back to their original values. |
| static constexpr float kMinGainDbUnity = -0.000000258856886667820f; |
| |
| // The highest (closest-to-Unity) AScale with an observable effect on |
| // full-scale (i.e. the largest sub-Unity AScale distinguishable from Unity). |
| // |
| // Related to kMinGainDbUnity, this const is also determined by the number of |
| // precision bits in a float32. Conceptually, it is infinitesimally less than |
| // (2^25 - 1) / (2^25). At this value, for the first time the largest values |
| // (i.e. full-scale) will not round back to their original values. |
| static constexpr float kMaxGainDbNonUnity = -0.000000258865572365570f; |
| |
| // The lowest (closest-to-zero) AScale at which full-scale data are not |
| // silenced (i.e. the smallest AScale that is distinguishable from Mute). |
| // |
| // This value would actually be infinitesimally close to zero, if it were not |
| // for our -160dB limit. kMinGainDbNonMute is essentially kMutedGainDb -- plus |
| // the smallest-possible increment that a float32 can express. Note the close |
| // relation to kMaxGainDbMute. |
| static constexpr float kMinGainDbNonMute = -159.99999f; |
| |
| // The highest (furthest-from-Mute) AScale at which full-scale data are |
| // silenced (i.e. the largest AScale that is indistinguishable from Mute). |
| // |
| // This value would actually be infinitesimally close to zero, if it were not |
| // for our -160dB limit. kMaxGainDbMute is essentially kMutedGainDb -- plus an |
| // increment that float32 ultimately CANNOT express. |
| static constexpr float kMaxGainDbMute = -159.999993f; |
| |
| static_assert(kMinGainDbUnity > kMaxGainDbNonUnity, |
| "kMaxGainDbNonUnity should be distinguishable from Unity"); |
| static_assert(kMinGainDbNonMute > kMaxGainDbMute, |
| "kMinGainDbNonMute should be distinguishable from Mute"); |
| |
| // This is the worst-case value (measured potentially across multiple test |
| // cases) for how close we can get to Unity scale while still causing |
| // different results than when using Unity scale. |
| static Gain::AScale ScaleEpsilon; |
| |
| // This is the worst-case value (measured potentially across multiple test |
| // cases) for how close we can get to zero scale (mute) while still causing |
| // a non-mute outcome. |
| static Gain::AScale MinScaleNonZero; |
| |
| // Dynamic Range |
| // (gain integrity and system response at low volume levels) |
| // |
| // Measured at a single reference frequency (kReferenceFreq), on a lone mono |
| // source without SRC. By determining the smallest possible change in gain |
| // that causes a detectable change in output (our 'gain epsilon'), we |
| // determine a system's sensitivity to gain changes. We measure not only the |
| // output level of the signal, but also the noise level across all other |
| // frequencies. Performing these same measurements (output level and noise |
| // level) with other gains as well (-30dB, -60dB, -90dB) is the standard |
| // definition of Dynamic Range testing: adding these gains to the measured |
| // signal-to-noise determines a system's usable data range (translatable into |
| // the more accessible Effective Number Of Bits metric). Level measurements at |
| // these different gains are useful not only as components of the "noise in |
| // the presence of signal" calculation, but also as avenues toward measuring a |
| // system's linearity/accuracy/precision with regard to data scaling and gain. |
| // |
| // The worst-case value (measured potentially across multiple test cases) for |
| // how far we diverge from target amplitude levels in Dynamic Range testing. |
| static double DynRangeTolerance; |
| // The previous-cached worst-case tolerance value, for Dynamic range testing. |
| // If a current tolerance EXCEEDS this value, then the test case fails. |
| static constexpr double kPrevDynRangeTolerance = 7.5380325e-03; |
| |
| // Level and unwanted artifacts, applying the smallest-detectable gain change. |
| static double LevelEpsilonDown; |
| // If current value is LESS than this value, then the test case fails. |
| static constexpr double kPrevLevelEpsilonDown = -1.6807164e-04; |
| |
| // Previously-cached sinad when applying the smallest-detectable gain change. |
| static double SinadEpsilonDown; |
| // If current value is LESS than this value, then the test case fails. |
| static constexpr double kPrevSinadEpsilonDown = 91.3090642; |
| |
| // Level and unwanted artifacts -- as well as previously-cached threshold |
| // limits for the same -- when applying -30dB gain (measures dynamic range). |
| static double Level30Down; |
| static double Level60Down; |
| static double Level90Down; |
| |
| // Current and previously-cached SINAD, when applying -30 / -60 / -90 dB gain. |
| |
| // Current measured SINAD at -30 gain. |
| static double Sinad30Down; |
| // If current value is LESS than this value, then the test case fails. |
| static constexpr double kPrevSinad30Down = 64.091308; |
| |
| // Current measured SINAD at -60 gain. |
| static double Sinad60Down; |
| // If current value is LESS than this value, then the test case fails. |
| static constexpr double kPrevSinad60Down = 34.196326; |
| |
| // Current measured SINAD at -90 gain. |
| static double Sinad90Down; |
| // If current value is LESS than this value, then the test case fails. |
| static constexpr double kPrevSinad90Down = 2.8879823; |
| |
| // |
| // |
| // Sum |
| // |
| // How close is a measured level to the reference dB level? Val-being-checked |
| // must be within this distance (above OR below) from the reference dB level. |
| // |
| // Worst-case value (measured potentially across multiple test cases) for how |
| // far our mix result level diverges from the target amplitude in Mix testing. |
| static double LevelToleranceMix8; |
| static double LevelToleranceMix16; |
| static double LevelToleranceMix24; |
| static double LevelToleranceMixFloat; |
| |
| // If current tolerance EXCEEDS this value, then the test case fails. |
| static constexpr double kPrevLevelToleranceMix8 = 6.7219077e-02; |
| static constexpr double kPrevLevelToleranceMix16 = 1.7031199e-04; |
| static constexpr double kPrevLevelToleranceMix24 = 3.0346074e-09; |
| static constexpr double kPrevLevelToleranceMixFloat = 5.3282082e-10; |
| |
| // Absolute output level (dBFS) measured in Mix tests for this input type. |
| static double LevelMix8; |
| static double LevelMix16; |
| static double LevelMix24; |
| static double LevelMixFloat; |
| |
| // If current value is LESS than this value, then the test case fails. |
| static constexpr double kPrevLevelMix8 = 0.0; |
| static constexpr double kPrevLevelMix16 = 0.0; |
| static constexpr double kPrevLevelMix24 = 0.0; |
| static constexpr double kPrevLevelMixFloat = 0.0; |
| |
| // Noise floor (dBr to full-scale) measured in Mix tests for this input type. |
| static double FloorMix8; |
| static double FloorMix16; |
| static double FloorMix24; |
| static double FloorMixFloat; |
| |
| // If current value is LESS than this value, then the test case fails. |
| static constexpr double kPrevFloorMix8 = 49.952317; |
| static constexpr double kPrevFloorMix16 = 90.677331; |
| static constexpr double kPrevFloorMix24 = 146.30926; |
| static constexpr double kPrevFloorMixFloat = 153.74509; |
| |
| // |
| // |
| // Output |
| // |
| // How close is a measured level to the reference dB level? Val-being-checked |
| // must be within this distance (above OR below) from the reference dB level. |
| // |
| // For this output type, this is the worst-case value for how far our output |
| // result level diverged from the target amplitude in Output testing. This |
| // result is measured in dBr, for input signals of 0 dBFS. |
| static double LevelToleranceOutput8; |
| static double LevelToleranceOutput16; |
| static double LevelToleranceOutput24; |
| static double LevelToleranceOutputFloat; |
| |
| // If current tolerance EXCEEDS this value, then the test case fails. |
| static constexpr double kPrevLevelToleranceOutput8 = 6.5638245e-02; |
| static constexpr double kPrevLevelToleranceOutput16 = 6.7860087e-02; |
| static constexpr double kPrevLevelToleranceOutput24 = 3.0250373e-07; |
| static constexpr double kPrevLevelToleranceOutputFloat = 6.8541681e-07; |
| |
| // Absolute output level (dBFS) measured in Output tests for this type. |
| static double LevelOutput8; |
| static double LevelOutput16; |
| static double LevelOutput24; |
| static double LevelOutputFloat; |
| |
| // If current value is LESS than this value, then the test case fails. |
| static constexpr double kPrevLevelOutput8 = 0.0; |
| static constexpr double kPrevLevelOutput16 = 0.0; |
| static constexpr double kPrevLevelOutput24 = 0.0; |
| static constexpr double kPrevLevelOutputFloat = 0.0; |
| |
| // What is our best-case noise floor in absence of rechannel/gain/SRC/mix. |
| // Val is root-sum-square of all other freqs besides the 1kHz reference, in |
| // dBr units (compared to magnitude of received reference). This is measured |
| // in dBr, relative to the expected full-scale output. Higher positive values |
| // represent "quieter" output functions and are desired. |
| static double FloorOutput8; |
| static double FloorOutput16; |
| static double FloorOutput24; |
| static double FloorOutputFloat; |
| |
| // If current value is LESS than this value, then the test case fails. |
| static constexpr double kPrevFloorOutput8 = 45.920261; |
| static constexpr double kPrevFloorOutput16 = 97.944722; |
| static constexpr double kPrevFloorOutput24 = 146.22129; |
| static constexpr double kPrevFloorOutputFloat = 153.74509; |
| |
| // class is static only - prevent attempts to instantiate it |
| AudioResult() = delete; |
| |
| // |
| // The subsequent methods are used when updating the kPrev threshold arrays to |
| // match new (presumably improved) results. They display the current run's |
| // results in an easily-imported format. Use '--dump' to trigger this. |
| // |
| static void DumpThresholdValues(); |
| |
| private: |
| static void DumpFreqRespValues(double* freq_resp_vals, std::string arr_name); |
| static void DumpSinadValues(double* sinad_vals, std::string arr_name); |
| static void DumpNoiseFloorValues(); |
| static void DumpLevelValues(); |
| static void DumpLevelToleranceValues(); |
| static void DumpDynamicRangeValues(); |
| }; |
| |
| } // namespace test |
| } // namespace audio |
| } // namespace media |
| |
| /* |
| AudioResult journal - updated upon each CL that affects these measurements |
| |
| 2018-08-31 Added running fractional source position modulo to the core |
| Mix() function, and incorporated this into the frequency |
| response tests (those are the only tests that break a large Mix |
| pass into multiple chunks). In contrast to slight inaccuracies |
| in Rate, small imprecisions in Starting Position do not compound |
| over time and hence do not significantly impact fidelity. After |
| this change, as expected there was a measureable but negligible |
| improvement in audio fidelity, shown in updates to the threshold |
| values. For this reason, the internal clients (AudioCapturerImpl |
| and StandardOutputBase) do not yet adopt this feature. |
| 2018-07-16 Added high-precision fixed-point data type 24-in-32-integer |
| support in the normalize and output functions (mixer_utils.h and |
| output_formatter.cc, respectively). Added level and noise-floor |
| test thresholds for 24-bit sources, outputs and mixes. |
| 2018-06-29 Converted internal processing pipeline to 32-bit floating-point. |
| Gain-scaling, stereo-to-mono rechannelization, interpolation and |
| summing are all done in the float domain (although PTS subframes |
| are still 19.13 fixed-point). Converted all generic frequency |
| response and dynamic range tests over to use float data type. |
| Also added level and noise-floor test thresholds for float |
| sources, outputs and mixes. |
| 2018-05-08 Added rate_modulo & denominator parameters, to express |
| resampling precision that cannot be captured by a single |
| frac_step_size uint32. We can now send mix jobs of any size |
| (even 64k) without accumulating position error. |
| With this fix, our first round of audio fidelity improvements is |
| complete. One remaining future focus could be to achieve flatter |
| frequency response, presumably via a higher-order resampler. |
| 2018-05-01 Added new rate ratio for micro-SRC testing: 47999:48000. Also |
| increased our mix job size to 20 ms (see 04-23 below), to better |
| show the effects of accumulated fractional position errors. |
| 2018-04-30 Converted internal accumulator pipeline to 18-bit fixed-point |
| rather than 16-bit. This will improve noise-floor and other |
| measurements by up to 12 dB, in cases where quality is not gated |
| by other factors (such as the bit-width of the input or output). |
| 2018-04-24 Converted fidelity tests to float-based input, instead of 16-bit |
| signed integers -- enabling higher-resolution measurement (and |
| requiring updates to most thresholds). |
| 2018-04-23 Moved fidelity tests to call Mixer objects in smaller mix jobs, |
| to emulate how these objects are used by their callers elsewhere |
| in audio_core. By forcing source-to-accumulator buffer lengths |
| to match the required ratios, we directly expose a longstanding |
| source of distortion, MTWN-49 (the "step_size" bug). |
| 2018-03-28 Full-spectrum frequency response and distortion tests: in all, |
| 47 frequencies, from DC, 13Hz, 20Hz to 22kHz, 24kHz and beyond. |
| Down-sampling tests show significant aliasing. |
| 2018-03-28 Initial mix floor tests: 8- and 16-bit for accumulation. |
| 2018-03-26 Initial dynamic range tests. kPrevScaleEpsilon = 0FFFFFFF for |
| incoming positive values; 0FFFE000 for negative values. |
| 2018-03-21 Initial frequency response / sinad tests: 1kHz, 40Hz, 12kHz. |
| 2018-03-20 Initial source/output noise floor tests: 8- & 16-bit, 1kHz. |
| */ |
| |
| #endif // GARNET_BIN_MEDIA_AUDIO_CORE_MIXER_TEST_AUDIO_RESULT_H_ |