tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

rms_level_unittest.cc (6718B)


      1 /*
      2 *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 #include "modules/audio_processing/rms_level.h"
     11 
     12 #include <cmath>
     13 #include <cstddef>
     14 #include <cstdint>
     15 #include <memory>
     16 #include <numbers>
     17 #include <vector>
     18 
     19 #include "api/array_view.h"
     20 #include "rtc_base/checks.h"
     21 #include "rtc_base/numerics/safe_conversions.h"
     22 #include "test/gtest.h"
     23 
     24 namespace webrtc {
     25 namespace {
     26 constexpr int kSampleRateHz = 48000;
     27 constexpr size_t kBlockSizeSamples = kSampleRateHz / 100;
     28 
     29 std::unique_ptr<RmsLevel> RunTest(ArrayView<const int16_t> input) {
     30  std::unique_ptr<RmsLevel> level(new RmsLevel);
     31  for (size_t n = 0; n + kBlockSizeSamples <= input.size();
     32       n += kBlockSizeSamples) {
     33    level->Analyze(input.subview(n, kBlockSizeSamples));
     34  }
     35  return level;
     36 }
     37 
     38 std::unique_ptr<RmsLevel> RunTest(ArrayView<const float> input) {
     39  std::unique_ptr<RmsLevel> level(new RmsLevel);
     40  for (size_t n = 0; n + kBlockSizeSamples <= input.size();
     41       n += kBlockSizeSamples) {
     42    level->Analyze(input.subview(n, kBlockSizeSamples));
     43  }
     44  return level;
     45 }
     46 
     47 std::vector<int16_t> CreateInt16Sinusoid(int frequency_hz,
     48                                         int amplitude,
     49                                         size_t num_samples) {
     50  std::vector<int16_t> x(num_samples);
     51  for (size_t n = 0; n < num_samples; ++n) {
     52    x[n] = saturated_cast<int16_t>(
     53        amplitude *
     54        std::sin(2 * std::numbers::pi * n * frequency_hz / kSampleRateHz));
     55  }
     56  return x;
     57 }
     58 
     59 std::vector<float> CreateFloatSinusoid(int frequency_hz,
     60                                       int amplitude,
     61                                       size_t num_samples) {
     62  std::vector<int16_t> x16 =
     63      CreateInt16Sinusoid(frequency_hz, amplitude, num_samples);
     64  std::vector<float> x(x16.size());
     65  for (size_t n = 0; n < x.size(); ++n) {
     66    x[n] = x16[n];
     67  }
     68  return x;
     69 }
     70 
     71 }  // namespace
     72 
     73 TEST(RmsLevelTest, VerifyIndentityBetweenFloatAndFix) {
     74  auto x_f = CreateFloatSinusoid(1000, INT16_MAX, kSampleRateHz);
     75  auto x_i = CreateFloatSinusoid(1000, INT16_MAX, kSampleRateHz);
     76  auto level_f = RunTest(x_f);
     77  auto level_i = RunTest(x_i);
     78  int avg_i = level_i->Average();
     79  int avg_f = level_f->Average();
     80  EXPECT_EQ(3, avg_i);  // -3 dBFS
     81  EXPECT_EQ(avg_f, avg_i);
     82 }
     83 
     84 TEST(RmsLevelTest, Run1000HzFullScale) {
     85  auto x = CreateInt16Sinusoid(1000, INT16_MAX, kSampleRateHz);
     86  auto level = RunTest(x);
     87  EXPECT_EQ(3, level->Average());  // -3 dBFS
     88 }
     89 
     90 TEST(RmsLevelTest, Run1000HzFullScaleAverageAndPeak) {
     91  auto x = CreateInt16Sinusoid(1000, INT16_MAX, kSampleRateHz);
     92  auto level = RunTest(x);
     93  auto stats = level->AverageAndPeak();
     94  EXPECT_EQ(3, stats.average);  // -3 dBFS
     95  EXPECT_EQ(3, stats.peak);
     96 }
     97 
     98 TEST(RmsLevelTest, Run1000HzHalfScale) {
     99  auto x = CreateInt16Sinusoid(1000, INT16_MAX / 2, kSampleRateHz);
    100  auto level = RunTest(x);
    101  EXPECT_EQ(9, level->Average());  // -9 dBFS
    102 }
    103 
    104 TEST(RmsLevelTest, RunZeros) {
    105  std::vector<int16_t> x(kSampleRateHz, 0);  // 1 second of pure silence.
    106  auto level = RunTest(x);
    107  EXPECT_EQ(127, level->Average());
    108 }
    109 
    110 TEST(RmsLevelTest, RunZerosAverageAndPeak) {
    111  std::vector<int16_t> x(kSampleRateHz, 0);  // 1 second of pure silence.
    112  auto level = RunTest(x);
    113  auto stats = level->AverageAndPeak();
    114  EXPECT_EQ(127, stats.average);
    115  EXPECT_EQ(127, stats.peak);
    116 }
    117 
    118 TEST(RmsLevelTest, NoSamples) {
    119  RmsLevel level;
    120  EXPECT_EQ(127, level.Average());  // Return minimum if no samples are given.
    121 }
    122 
    123 TEST(RmsLevelTest, NoSamplesAverageAndPeak) {
    124  RmsLevel level;
    125  auto stats = level.AverageAndPeak();
    126  EXPECT_EQ(127, stats.average);
    127  EXPECT_EQ(127, stats.peak);
    128 }
    129 
    130 TEST(RmsLevelTest, PollTwice) {
    131  auto x = CreateInt16Sinusoid(1000, INT16_MAX, kSampleRateHz);
    132  auto level = RunTest(x);
    133  level->Average();
    134  EXPECT_EQ(127, level->Average());  // Stats should be reset at this point.
    135 }
    136 
    137 TEST(RmsLevelTest, Reset) {
    138  auto x = CreateInt16Sinusoid(1000, INT16_MAX, kSampleRateHz);
    139  auto level = RunTest(x);
    140  level->Reset();
    141  EXPECT_EQ(127, level->Average());  // Stats should be reset at this point.
    142 }
    143 
    144 // Inserts 1 second of full-scale sinusoid, followed by 1 second of muted.
    145 TEST(RmsLevelTest, ProcessMuted) {
    146  auto x = CreateInt16Sinusoid(1000, INT16_MAX, kSampleRateHz);
    147  auto level = RunTest(x);
    148  const size_t kBlocksPerSecond =
    149      CheckedDivExact(static_cast<size_t>(kSampleRateHz), kBlockSizeSamples);
    150  for (size_t i = 0; i < kBlocksPerSecond; ++i) {
    151    level->AnalyzeMuted(kBlockSizeSamples);
    152  }
    153  EXPECT_EQ(6, level->Average());  // Average RMS halved due to the silence.
    154 }
    155 
    156 // Digital silence must yield 127 and anything else should yield 126 or lower.
    157 TEST(RmsLevelTest, OnlyDigitalSilenceIs127) {
    158  std::vector<int16_t> test_buffer(kSampleRateHz, 0);
    159  auto level = RunTest(test_buffer);
    160  EXPECT_EQ(127, level->Average());
    161  // Change one sample to something other than 0 to make the buffer not strictly
    162  // represent digital silence.
    163  test_buffer[0] = 1;
    164  level = RunTest(test_buffer);
    165  EXPECT_LT(level->Average(), 127);
    166 }
    167 
    168 // Inserts 1 second of half-scale sinusoid, follwed by 10 ms of full-scale, and
    169 // finally 1 second of half-scale again. Expect the average to be -9 dBFS due
    170 // to the vast majority of the signal being half-scale, and the peak to be
    171 // -3 dBFS.
    172 TEST(RmsLevelTest, RunHalfScaleAndInsertFullScale) {
    173  auto half_scale = CreateInt16Sinusoid(1000, INT16_MAX / 2, kSampleRateHz);
    174  auto full_scale = CreateInt16Sinusoid(1000, INT16_MAX, kSampleRateHz / 100);
    175  auto x = half_scale;
    176  x.insert(x.end(), full_scale.begin(), full_scale.end());
    177  x.insert(x.end(), half_scale.begin(), half_scale.end());
    178  ASSERT_EQ(static_cast<size_t>(2 * kSampleRateHz + kSampleRateHz / 100),
    179            x.size());
    180  auto level = RunTest(x);
    181  auto stats = level->AverageAndPeak();
    182  EXPECT_EQ(9, stats.average);
    183  EXPECT_EQ(3, stats.peak);
    184 }
    185 
    186 TEST(RmsLevelTest, ResetOnBlockSizeChange) {
    187  auto x = CreateInt16Sinusoid(1000, INT16_MAX, kSampleRateHz);
    188  auto level = RunTest(x);
    189  // Create a new signal with half amplitude, but double block length.
    190  auto y = CreateInt16Sinusoid(1000, INT16_MAX / 2, kBlockSizeSamples * 2);
    191  level->Analyze(y);
    192  auto stats = level->AverageAndPeak();
    193  // Expect all stats to only be influenced by the last signal (y), since the
    194  // changed block size should reset the stats.
    195  EXPECT_EQ(9, stats.average);
    196  EXPECT_EQ(9, stats.peak);
    197 }
    198 
    199 }  // namespace webrtc