tor-browser

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

alignment_mixer_unittest.cc (7221B)


      1 /*
      2 *  Copyright (c) 2019 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 
     11 #include "modules/audio_processing/aec3/alignment_mixer.h"
     12 
     13 #include <algorithm>
     14 #include <array>
     15 #include <cstddef>
     16 #include <string>
     17 
     18 #include "api/array_view.h"
     19 #include "modules/audio_processing/aec3/aec3_common.h"
     20 #include "modules/audio_processing/aec3/block.h"
     21 #include "rtc_base/checks.h"
     22 #include "rtc_base/strings/string_builder.h"
     23 #include "test/gmock.h"
     24 #include "test/gtest.h"
     25 
     26 using ::testing::AllOf;
     27 using ::testing::Each;
     28 
     29 namespace webrtc {
     30 namespace {
     31 std::string ProduceDebugText(bool initial_silence,
     32                             bool huge_activity_threshold,
     33                             bool prefer_first_two_channels,
     34                             int num_channels,
     35                             int strongest_ch) {
     36  StringBuilder ss;
     37  ss << ", Initial silence: " << initial_silence;
     38  ss << ", Huge activity threshold: " << huge_activity_threshold;
     39  ss << ", Prefer first two channels: " << prefer_first_two_channels;
     40  ss << ", Number of channels: " << num_channels;
     41  ss << ", Strongest channel: " << strongest_ch;
     42  return ss.Release();
     43 }
     44 
     45 }  // namespace
     46 
     47 TEST(AlignmentMixer, GeneralAdaptiveMode) {
     48  constexpr int kChannelOffset = 100;
     49  constexpr int kMaxChannelsToTest = 8;
     50  constexpr float kStrongestSignalScaling =
     51      kMaxChannelsToTest * kChannelOffset * 100;
     52 
     53  for (bool initial_silence : {false, true}) {
     54    for (bool huge_activity_threshold : {false, true}) {
     55      for (bool prefer_first_two_channels : {false, true}) {
     56        for (int num_channels = 2; num_channels < 8; ++num_channels) {
     57          for (int strongest_ch = 0; strongest_ch < num_channels;
     58               ++strongest_ch) {
     59            SCOPED_TRACE(ProduceDebugText(
     60                initial_silence, huge_activity_threshold,
     61                prefer_first_two_channels, num_channels, strongest_ch));
     62            const float excitation_limit =
     63                huge_activity_threshold ? 1000000000.f : 0.001f;
     64            AlignmentMixer am(num_channels, /*downmix*/ false,
     65                              /*adaptive_selection*/ true, excitation_limit,
     66                              prefer_first_two_channels);
     67 
     68            Block x(
     69                /*num_bands=*/1, num_channels);
     70            if (initial_silence) {
     71              std::array<float, kBlockSize> y;
     72              for (int frame = 0; frame < 10 * kNumBlocksPerSecond; ++frame) {
     73                am.ProduceOutput(x, y);
     74              }
     75            }
     76 
     77            for (int frame = 0; frame < 2 * kNumBlocksPerSecond; ++frame) {
     78              const auto channel_value = [&](int frame_index,
     79                                             int channel_index) {
     80                return static_cast<float>(frame_index +
     81                                          channel_index * kChannelOffset);
     82              };
     83 
     84              for (int ch = 0; ch < num_channels; ++ch) {
     85                float scaling =
     86                    ch == strongest_ch ? kStrongestSignalScaling : 1.f;
     87                auto x_ch = x.View(/*band=*/0, ch);
     88                std::fill(x_ch.begin(), x_ch.end(),
     89                          channel_value(frame, ch) * scaling);
     90              }
     91 
     92              std::array<float, kBlockSize> y;
     93              y.fill(-1.f);
     94              am.ProduceOutput(x, y);
     95 
     96              if (frame > 1 * kNumBlocksPerSecond) {
     97                if (!prefer_first_two_channels || huge_activity_threshold) {
     98                  EXPECT_THAT(y,
     99                              AllOf(Each(x.View(/*band=*/0, strongest_ch)[0])));
    100                } else {
    101                  bool left_or_right_chosen;
    102                  for (int ch = 0; ch < 2; ++ch) {
    103                    left_or_right_chosen = true;
    104                    const auto x_ch = x.View(/*band=*/0, ch);
    105                    for (size_t k = 0; k < kBlockSize; ++k) {
    106                      if (y[k] != x_ch[k]) {
    107                        left_or_right_chosen = false;
    108                        break;
    109                      }
    110                    }
    111                    if (left_or_right_chosen) {
    112                      break;
    113                    }
    114                  }
    115                  EXPECT_TRUE(left_or_right_chosen);
    116                }
    117              }
    118            }
    119          }
    120        }
    121      }
    122    }
    123  }
    124 }
    125 
    126 TEST(AlignmentMixer, DownmixMode) {
    127  for (int num_channels = 1; num_channels < 8; ++num_channels) {
    128    AlignmentMixer am(num_channels, /*downmix*/ true,
    129                      /*adaptive_selection*/ false, /*excitation_limit*/ 1.f,
    130                      /*prefer_first_two_channels*/ false);
    131 
    132    Block x(/*num_bands=*/1, num_channels);
    133    const auto channel_value = [](int frame_index, int channel_index) {
    134      return static_cast<float>(frame_index + channel_index);
    135    };
    136    for (int frame = 0; frame < 10; ++frame) {
    137      for (int ch = 0; ch < num_channels; ++ch) {
    138        auto x_ch = x.View(/*band=*/0, ch);
    139        std::fill(x_ch.begin(), x_ch.end(), channel_value(frame, ch));
    140      }
    141 
    142      std::array<float, kBlockSize> y;
    143      y.fill(-1.f);
    144      am.ProduceOutput(x, y);
    145 
    146      float expected_mixed_value = 0.f;
    147      for (int ch = 0; ch < num_channels; ++ch) {
    148        expected_mixed_value += channel_value(frame, ch);
    149      }
    150      expected_mixed_value *= 1.f / num_channels;
    151 
    152      EXPECT_THAT(y, AllOf(Each(expected_mixed_value)));
    153    }
    154  }
    155 }
    156 
    157 TEST(AlignmentMixer, FixedMode) {
    158  for (int num_channels = 1; num_channels < 8; ++num_channels) {
    159    AlignmentMixer am(num_channels, /*downmix*/ false,
    160                      /*adaptive_selection*/ false, /*excitation_limit*/ 1.f,
    161                      /*prefer_first_two_channels*/ false);
    162 
    163    Block x(/*num_bands=*/1, num_channels);
    164    const auto channel_value = [](int frame_index, int channel_index) {
    165      return static_cast<float>(frame_index + channel_index);
    166    };
    167    for (int frame = 0; frame < 10; ++frame) {
    168      for (int ch = 0; ch < num_channels; ++ch) {
    169        auto x_ch = x.View(/*band=*/0, ch);
    170        std::fill(x_ch.begin(), x_ch.end(), channel_value(frame, ch));
    171      }
    172 
    173      std::array<float, kBlockSize> y;
    174      y.fill(-1.f);
    175      am.ProduceOutput(x, y);
    176      EXPECT_THAT(y, AllOf(Each(x.View(/*band=*/0, /*channel=*/0)[0])));
    177    }
    178  }
    179 }
    180 
    181 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
    182 
    183 TEST(AlignmentMixerDeathTest, ZeroNumChannels) {
    184  EXPECT_DEATH(
    185      AlignmentMixer(/*num_channels*/ 0, /*downmix*/ false,
    186                     /*adaptive_selection*/ false, /*excitation_limit*/ 1.f,
    187                     /*prefer_first_two_channels*/ false);
    188      , "");
    189 }
    190 
    191 TEST(AlignmentMixerDeathTest, IncorrectVariant) {
    192  EXPECT_DEATH(
    193      AlignmentMixer(/*num_channels*/ 1, /*downmix*/ true,
    194                     /*adaptive_selection*/ true, /*excitation_limit*/ 1.f,
    195                     /*prefer_first_two_channels*/ false);
    196      , "");
    197 }
    198 
    199 #endif
    200 
    201 }  // namespace webrtc