tor-browser

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

debug_dump_test.cc (18279B)


      1 /*
      2 *  Copyright (c) 2015 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 <stdio.h>
     12 
     13 #include <cstddef>
     14 #include <cstdint>
     15 #include <cstdio>
     16 #include <cstring>
     17 #include <memory>
     18 #include <optional>
     19 #include <string>
     20 #include <vector>
     21 
     22 #include "absl/strings/string_view.h"
     23 #include "api/audio/audio_processing.h"
     24 #include "api/audio/builtin_audio_processing_builder.h"
     25 #include "api/environment/environment_factory.h"
     26 #include "api/scoped_refptr.h"
     27 #include "common_audio/channel_buffer.h"
     28 #include "common_audio/include/audio_util.h"
     29 #include "modules/audio_coding/neteq/tools/resample_input_audio_file.h"
     30 #include "modules/audio_processing/aec_dump/aec_dump_factory.h"
     31 #include "modules/audio_processing/test/debug_dump_replayer.h"
     32 #include "modules/audio_processing/test/protobuf_utils.h"
     33 #include "rtc_base/checks.h"
     34 #include "rtc_base/task_queue_for_test.h"
     35 #include "test/gtest.h"
     36 #include "test/testsupport/file_utils.h"
     37 
     38 namespace webrtc {
     39 namespace test {
     40 
     41 namespace {
     42 
     43 void MaybeResetBuffer(std::unique_ptr<ChannelBuffer<float>>* buffer,
     44                      const StreamConfig& config) {
     45  auto& buffer_ref = *buffer;
     46  if (!buffer_ref || buffer_ref->num_frames() != config.num_frames() ||
     47      buffer_ref->num_channels() != config.num_channels()) {
     48    buffer_ref.reset(
     49        new ChannelBuffer<float>(config.num_frames(), config.num_channels()));
     50  }
     51 }
     52 
     53 class DebugDumpGenerator {
     54 public:
     55  DebugDumpGenerator(absl::string_view input_file_name,
     56                     int input_rate_hz,
     57                     int input_channels,
     58                     absl::string_view reverse_file_name,
     59                     int reverse_rate_hz,
     60                     int reverse_channels,
     61                     absl::string_view dump_file_name,
     62                     bool enable_pre_amplifier);
     63 
     64  // Constructor that uses default input files.
     65  explicit DebugDumpGenerator(const AudioProcessing::Config& apm_config);
     66 
     67  ~DebugDumpGenerator();
     68 
     69  // Changes the sample rate of the input audio to the APM.
     70  void SetInputRate(int rate_hz);
     71 
     72  // Sets if converts stereo input signal to mono by discarding other channels.
     73  void ForceInputMono(bool mono);
     74 
     75  // Changes the sample rate of the reverse audio to the APM.
     76  void SetReverseRate(int rate_hz);
     77 
     78  // Sets if converts stereo reverse signal to mono by discarding other
     79  // channels.
     80  void ForceReverseMono(bool mono);
     81 
     82  // Sets the required sample rate of the APM output.
     83  void SetOutputRate(int rate_hz);
     84 
     85  // Sets the required channels of the APM output.
     86  void SetOutputChannels(int channels);
     87 
     88  std::string dump_file_name() const { return dump_file_name_; }
     89 
     90  void StartRecording();
     91  void Process(size_t num_blocks);
     92  void StopRecording();
     93  AudioProcessing* apm() const { return apm_.get(); }
     94 
     95 private:
     96  static void ReadAndDeinterleave(ResampleInputAudioFile* audio,
     97                                  int channels,
     98                                  const StreamConfig& config,
     99                                  float* const* buffer);
    100 
    101  // APM input/output settings.
    102  StreamConfig input_config_;
    103  StreamConfig reverse_config_;
    104  StreamConfig output_config_;
    105 
    106  // Input file format.
    107  const std::string input_file_name_;
    108  ResampleInputAudioFile input_audio_;
    109  const int input_file_channels_;
    110 
    111  // Reverse file format.
    112  const std::string reverse_file_name_;
    113  ResampleInputAudioFile reverse_audio_;
    114  const int reverse_file_channels_;
    115 
    116  // Buffer for APM input/output.
    117  std::unique_ptr<ChannelBuffer<float>> input_;
    118  std::unique_ptr<ChannelBuffer<float>> reverse_;
    119  std::unique_ptr<ChannelBuffer<float>> output_;
    120 
    121  bool enable_pre_amplifier_;
    122 
    123  TaskQueueForTest worker_queue_;
    124  scoped_refptr<AudioProcessing> apm_;
    125 
    126  const std::string dump_file_name_;
    127 };
    128 
    129 DebugDumpGenerator::DebugDumpGenerator(absl::string_view input_file_name,
    130                                       int input_rate_hz,
    131                                       int input_channels,
    132                                       absl::string_view reverse_file_name,
    133                                       int reverse_rate_hz,
    134                                       int reverse_channels,
    135                                       absl::string_view dump_file_name,
    136                                       bool enable_pre_amplifier)
    137    : input_config_(input_rate_hz, input_channels),
    138      reverse_config_(reverse_rate_hz, reverse_channels),
    139      output_config_(input_rate_hz, input_channels),
    140      input_audio_(input_file_name, input_rate_hz, input_rate_hz),
    141      input_file_channels_(input_channels),
    142      reverse_audio_(reverse_file_name, reverse_rate_hz, reverse_rate_hz),
    143      reverse_file_channels_(reverse_channels),
    144      input_(new ChannelBuffer<float>(input_config_.num_frames(),
    145                                      input_config_.num_channels())),
    146      reverse_(new ChannelBuffer<float>(reverse_config_.num_frames(),
    147                                        reverse_config_.num_channels())),
    148      output_(new ChannelBuffer<float>(output_config_.num_frames(),
    149                                       output_config_.num_channels())),
    150      enable_pre_amplifier_(enable_pre_amplifier),
    151      worker_queue_("debug_dump_generator_worker_queue"),
    152      dump_file_name_(dump_file_name) {
    153  apm_ = BuiltinAudioProcessingBuilder().Build(CreateEnvironment());
    154 }
    155 
    156 DebugDumpGenerator::DebugDumpGenerator(
    157    const AudioProcessing::Config& apm_config)
    158    : DebugDumpGenerator(ResourcePath("near32_stereo", "pcm"),
    159                         32000,
    160                         2,
    161                         ResourcePath("far32_stereo", "pcm"),
    162                         32000,
    163                         2,
    164                         TempFilename(OutputPath(), "debug_aec"),
    165                         apm_config.pre_amplifier.enabled) {
    166  apm_->ApplyConfig(apm_config);
    167 }
    168 
    169 DebugDumpGenerator::~DebugDumpGenerator() {
    170  remove(dump_file_name_.c_str());
    171 }
    172 
    173 void DebugDumpGenerator::SetInputRate(int rate_hz) {
    174  input_audio_.set_output_rate_hz(rate_hz);
    175  input_config_.set_sample_rate_hz(rate_hz);
    176  MaybeResetBuffer(&input_, input_config_);
    177 }
    178 
    179 void DebugDumpGenerator::ForceInputMono(bool mono) {
    180  const int channels = mono ? 1 : input_file_channels_;
    181  input_config_.set_num_channels(channels);
    182  MaybeResetBuffer(&input_, input_config_);
    183 }
    184 
    185 void DebugDumpGenerator::SetReverseRate(int rate_hz) {
    186  reverse_audio_.set_output_rate_hz(rate_hz);
    187  reverse_config_.set_sample_rate_hz(rate_hz);
    188  MaybeResetBuffer(&reverse_, reverse_config_);
    189 }
    190 
    191 void DebugDumpGenerator::ForceReverseMono(bool mono) {
    192  const int channels = mono ? 1 : reverse_file_channels_;
    193  reverse_config_.set_num_channels(channels);
    194  MaybeResetBuffer(&reverse_, reverse_config_);
    195 }
    196 
    197 void DebugDumpGenerator::SetOutputRate(int rate_hz) {
    198  output_config_.set_sample_rate_hz(rate_hz);
    199  MaybeResetBuffer(&output_, output_config_);
    200 }
    201 
    202 void DebugDumpGenerator::SetOutputChannels(int channels) {
    203  output_config_.set_num_channels(channels);
    204  MaybeResetBuffer(&output_, output_config_);
    205 }
    206 
    207 void DebugDumpGenerator::StartRecording() {
    208  apm_->AttachAecDump(
    209      AecDumpFactory::Create(dump_file_name_.c_str(), -1, worker_queue_.Get()));
    210 }
    211 
    212 void DebugDumpGenerator::Process(size_t num_blocks) {
    213  for (size_t i = 0; i < num_blocks; ++i) {
    214    ReadAndDeinterleave(&reverse_audio_, reverse_file_channels_,
    215                        reverse_config_, reverse_->channels());
    216    ReadAndDeinterleave(&input_audio_, input_file_channels_, input_config_,
    217                        input_->channels());
    218    RTC_CHECK_EQ(AudioProcessing::kNoError, apm_->set_stream_delay_ms(100));
    219    apm_->set_stream_analog_level(100);
    220    if (enable_pre_amplifier_) {
    221      apm_->SetRuntimeSetting(
    222          AudioProcessing::RuntimeSetting::CreateCapturePreGain(1 + i % 10));
    223    }
    224    apm_->set_stream_key_pressed(i % 10 == 9);
    225    RTC_CHECK_EQ(AudioProcessing::kNoError,
    226                 apm_->ProcessStream(input_->channels(), input_config_,
    227                                     output_config_, output_->channels()));
    228 
    229    RTC_CHECK_EQ(
    230        AudioProcessing::kNoError,
    231        apm_->ProcessReverseStream(reverse_->channels(), reverse_config_,
    232                                   reverse_config_, reverse_->channels()));
    233  }
    234 }
    235 
    236 void DebugDumpGenerator::StopRecording() {
    237  apm_->DetachAecDump();
    238 }
    239 
    240 void DebugDumpGenerator::ReadAndDeinterleave(ResampleInputAudioFile* audio,
    241                                             int channels,
    242                                             const StreamConfig& config,
    243                                             float* const* buffer) {
    244  const size_t num_frames = config.num_frames();
    245  const int out_channels = config.num_channels();
    246 
    247  std::vector<int16_t> signal(channels * num_frames);
    248 
    249  audio->Read(num_frames * channels, &signal[0]);
    250 
    251  // We only allow reducing number of channels by discarding some channels.
    252  RTC_CHECK_LE(out_channels, channels);
    253  for (int channel = 0; channel < out_channels; ++channel) {
    254    for (size_t i = 0; i < num_frames; ++i) {
    255      buffer[channel][i] = S16ToFloat(signal[i * channels + channel]);
    256    }
    257  }
    258 }
    259 
    260 }  // namespace
    261 
    262 class DebugDumpTest : public ::testing::Test {
    263 public:
    264  // VerifyDebugDump replays a debug dump using APM and verifies that the result
    265  // is bit-exact-identical to the output channel in the dump. This is only
    266  // guaranteed if the debug dump is started on the first frame.
    267  void VerifyDebugDump(absl::string_view in_filename);
    268 
    269 private:
    270  DebugDumpReplayer debug_dump_replayer_;
    271 };
    272 
    273 void DebugDumpTest::VerifyDebugDump(absl::string_view in_filename) {
    274  ASSERT_TRUE(debug_dump_replayer_.SetDumpFile(in_filename));
    275 
    276  while (const std::optional<audioproc::Event> event =
    277             debug_dump_replayer_.GetNextEvent()) {
    278    debug_dump_replayer_.RunNextEvent();
    279    if (event->type() == audioproc::Event::STREAM) {
    280      const audioproc::Stream* msg = &event->stream();
    281      const StreamConfig output_config = debug_dump_replayer_.GetOutputConfig();
    282      const ChannelBuffer<float>* output = debug_dump_replayer_.GetOutput();
    283      // Check that output of APM is bit-exact to the output in the dump.
    284      ASSERT_EQ(output_config.num_channels(),
    285                static_cast<size_t>(msg->output_channel_size()));
    286      ASSERT_EQ(output_config.num_frames() * sizeof(float),
    287                msg->output_channel(0).size());
    288      for (int i = 0; i < msg->output_channel_size(); ++i) {
    289        ASSERT_EQ(0,
    290                  memcmp(output->channels()[i], msg->output_channel(i).data(),
    291                         msg->output_channel(i).size()));
    292      }
    293    }
    294  }
    295 }
    296 
    297 TEST_F(DebugDumpTest, SimpleCase) {
    298  DebugDumpGenerator generator(/*apm_config=*/{});
    299  generator.StartRecording();
    300  generator.Process(100);
    301  generator.StopRecording();
    302  VerifyDebugDump(generator.dump_file_name());
    303 }
    304 
    305 // TODO(bugs.webrtc.org/345674542): Fix/enable.
    306 #if defined(__has_feature) && __has_feature(undefined_behavior_sanitizer)
    307 TEST_F(DebugDumpTest, DISABLED_ChangeInputFormat) {
    308 #else
    309 TEST_F(DebugDumpTest, ChangeInputFormat) {
    310 #endif
    311  DebugDumpGenerator generator(/*apm_config=*/{});
    312 
    313  generator.StartRecording();
    314  generator.Process(100);
    315  generator.SetInputRate(48000);
    316 
    317  generator.ForceInputMono(true);
    318  // Number of output channel should not be larger than that of input. APM will
    319  // fail otherwise.
    320  generator.SetOutputChannels(1);
    321 
    322  generator.Process(100);
    323  generator.StopRecording();
    324  VerifyDebugDump(generator.dump_file_name());
    325 }
    326 
    327 // TODO(bugs.webrtc.org/345674542): Fix/enable.
    328 #if defined(__has_feature) && __has_feature(undefined_behavior_sanitizer)
    329 TEST_F(DebugDumpTest, DISABLED_ChangeReverseFormat) {
    330 #else
    331 TEST_F(DebugDumpTest, ChangeReverseFormat) {
    332 #endif
    333  DebugDumpGenerator generator(/*apm_config=*/{});
    334  generator.StartRecording();
    335  generator.Process(100);
    336  generator.SetReverseRate(48000);
    337  generator.ForceReverseMono(true);
    338  generator.Process(100);
    339  generator.StopRecording();
    340  VerifyDebugDump(generator.dump_file_name());
    341 }
    342 
    343 TEST_F(DebugDumpTest, ChangeOutputFormat) {
    344  DebugDumpGenerator generator(/*apm_config=*/{});
    345  generator.StartRecording();
    346  generator.Process(100);
    347  generator.SetOutputRate(48000);
    348  generator.SetOutputChannels(1);
    349  generator.Process(100);
    350  generator.StopRecording();
    351  VerifyDebugDump(generator.dump_file_name());
    352 }
    353 
    354 TEST_F(DebugDumpTest, ToggleAec) {
    355  AudioProcessing::Config apm_config;
    356  apm_config.echo_canceller.enabled = true;
    357  DebugDumpGenerator generator(apm_config);
    358  generator.StartRecording();
    359  generator.Process(100);
    360 
    361  apm_config.echo_canceller.enabled = false;
    362  generator.apm()->ApplyConfig(apm_config);
    363 
    364  generator.Process(100);
    365  generator.StopRecording();
    366  VerifyDebugDump(generator.dump_file_name());
    367 }
    368 
    369 TEST_F(DebugDumpTest, VerifyCombinedExperimentalStringInclusive) {
    370  AudioProcessing::Config apm_config;
    371  apm_config.echo_canceller.enabled = true;
    372  apm_config.gain_controller1.analog_gain_controller.enabled = true;
    373  apm_config.gain_controller1.analog_gain_controller.startup_min_volume = 0;
    374  DebugDumpGenerator generator(apm_config);
    375  generator.StartRecording();
    376  generator.Process(100);
    377  generator.StopRecording();
    378 
    379  DebugDumpReplayer debug_dump_replayer_;
    380 
    381  ASSERT_TRUE(debug_dump_replayer_.SetDumpFile(generator.dump_file_name()));
    382 
    383  while (const std::optional<audioproc::Event> event =
    384             debug_dump_replayer_.GetNextEvent()) {
    385    debug_dump_replayer_.RunNextEvent();
    386    if (event->type() == audioproc::Event::CONFIG) {
    387      const audioproc::Config* msg = &event->config();
    388      ASSERT_TRUE(msg->has_experiments_description());
    389      EXPECT_PRED_FORMAT2(::testing::IsSubstring, "EchoController",
    390                          msg->experiments_description().c_str());
    391    }
    392  }
    393 }
    394 
    395 TEST_F(DebugDumpTest, VerifyCombinedExperimentalStringExclusive) {
    396  AudioProcessing::Config apm_config;
    397  apm_config.echo_canceller.enabled = true;
    398  DebugDumpGenerator generator(apm_config);
    399  generator.StartRecording();
    400  generator.Process(100);
    401  generator.StopRecording();
    402 
    403  DebugDumpReplayer debug_dump_replayer_;
    404 
    405  ASSERT_TRUE(debug_dump_replayer_.SetDumpFile(generator.dump_file_name()));
    406 
    407  while (const std::optional<audioproc::Event> event =
    408             debug_dump_replayer_.GetNextEvent()) {
    409    debug_dump_replayer_.RunNextEvent();
    410    if (event->type() == audioproc::Event::CONFIG) {
    411      const audioproc::Config* msg = &event->config();
    412      ASSERT_TRUE(msg->has_experiments_description());
    413      EXPECT_PRED_FORMAT2(::testing::IsNotSubstring,
    414                          "AgcClippingLevelExperiment",
    415                          msg->experiments_description().c_str());
    416    }
    417  }
    418 }
    419 
    420 TEST_F(DebugDumpTest, VerifyAec3ExperimentalString) {
    421  AudioProcessing::Config apm_config;
    422  apm_config.echo_canceller.enabled = true;
    423  DebugDumpGenerator generator(apm_config);
    424  generator.StartRecording();
    425  generator.Process(100);
    426  generator.StopRecording();
    427 
    428  DebugDumpReplayer debug_dump_replayer_;
    429 
    430  ASSERT_TRUE(debug_dump_replayer_.SetDumpFile(generator.dump_file_name()));
    431 
    432  while (const std::optional<audioproc::Event> event =
    433             debug_dump_replayer_.GetNextEvent()) {
    434    debug_dump_replayer_.RunNextEvent();
    435    if (event->type() == audioproc::Event::CONFIG) {
    436      const audioproc::Config* msg = &event->config();
    437      ASSERT_TRUE(msg->has_experiments_description());
    438      EXPECT_PRED_FORMAT2(::testing::IsSubstring, "EchoController",
    439                          msg->experiments_description().c_str());
    440    }
    441  }
    442 }
    443 
    444 TEST_F(DebugDumpTest, VerifyEmptyExperimentalString) {
    445  DebugDumpGenerator generator(/*apm_config=*/{});
    446  generator.StartRecording();
    447  generator.Process(100);
    448  generator.StopRecording();
    449 
    450  DebugDumpReplayer debug_dump_replayer_;
    451 
    452  ASSERT_TRUE(debug_dump_replayer_.SetDumpFile(generator.dump_file_name()));
    453 
    454  while (const std::optional<audioproc::Event> event =
    455             debug_dump_replayer_.GetNextEvent()) {
    456    debug_dump_replayer_.RunNextEvent();
    457    if (event->type() == audioproc::Event::CONFIG) {
    458      const audioproc::Config* msg = &event->config();
    459      ASSERT_TRUE(msg->has_experiments_description());
    460      EXPECT_EQ(0u, msg->experiments_description().size());
    461    }
    462  }
    463 }
    464 
    465 // AGC is not supported on Android or iOS.
    466 #if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
    467 #define MAYBE_ToggleAgc DISABLED_ToggleAgc
    468 #else
    469 #define MAYBE_ToggleAgc ToggleAgc
    470 #endif
    471 TEST_F(DebugDumpTest, MAYBE_ToggleAgc) {
    472  DebugDumpGenerator generator(/*apm_config=*/{});
    473  generator.StartRecording();
    474  generator.Process(100);
    475 
    476  AudioProcessing::Config apm_config = generator.apm()->GetConfig();
    477  apm_config.gain_controller1.enabled = !apm_config.gain_controller1.enabled;
    478  generator.apm()->ApplyConfig(apm_config);
    479 
    480  generator.Process(100);
    481  generator.StopRecording();
    482  VerifyDebugDump(generator.dump_file_name());
    483 }
    484 
    485 TEST_F(DebugDumpTest, ToggleNs) {
    486  DebugDumpGenerator generator(/*apm_config=*/{});
    487  generator.StartRecording();
    488  generator.Process(100);
    489 
    490  AudioProcessing::Config apm_config = generator.apm()->GetConfig();
    491  apm_config.noise_suppression.enabled = !apm_config.noise_suppression.enabled;
    492  generator.apm()->ApplyConfig(apm_config);
    493 
    494  generator.Process(100);
    495  generator.StopRecording();
    496  VerifyDebugDump(generator.dump_file_name());
    497 }
    498 
    499 TEST_F(DebugDumpTest, TransientSuppressionOn) {
    500  DebugDumpGenerator generator(/*apm_config=*/{});
    501 
    502  AudioProcessing::Config apm_config = generator.apm()->GetConfig();
    503  apm_config.transient_suppression.enabled = true;
    504  generator.apm()->ApplyConfig(apm_config);
    505 
    506  generator.StartRecording();
    507  generator.Process(100);
    508  generator.StopRecording();
    509  VerifyDebugDump(generator.dump_file_name());
    510 }
    511 
    512 TEST_F(DebugDumpTest, PreAmplifierIsOn) {
    513  AudioProcessing::Config apm_config;
    514  apm_config.pre_amplifier.enabled = true;
    515  DebugDumpGenerator generator(apm_config);
    516  generator.StartRecording();
    517  generator.Process(100);
    518  generator.StopRecording();
    519  VerifyDebugDump(generator.dump_file_name());
    520 }
    521 
    522 }  // namespace test
    523 }  // namespace webrtc