tor-browser

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

test_audio_device_impl.cc (6197B)


      1 /*
      2 *  Copyright (c) 2023 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_device/test_audio_device_impl.h"
     11 
     12 #include <cstddef>
     13 #include <cstdint>
     14 #include <memory>
     15 #include <optional>
     16 #include <utility>
     17 
     18 #include "api/array_view.h"
     19 #include "api/environment/environment.h"
     20 #include "api/task_queue/task_queue_factory.h"
     21 #include "api/units/time_delta.h"
     22 #include "modules/audio_device/audio_device_buffer.h"
     23 #include "modules/audio_device/audio_device_generic.h"
     24 #include "modules/audio_device/include/test_audio_device.h"
     25 #include "rtc_base/checks.h"
     26 #include "rtc_base/synchronization/mutex.h"
     27 #include "rtc_base/task_utils/repeating_task.h"
     28 
     29 namespace webrtc {
     30 namespace {
     31 
     32 constexpr int kFrameLengthUs = 10000;
     33 
     34 }  // namespace
     35 
     36 TestAudioDevice::TestAudioDevice(
     37    const Environment& env,
     38    std::unique_ptr<TestAudioDeviceModule::Capturer> capturer,
     39    std::unique_ptr<TestAudioDeviceModule::Renderer> renderer,
     40    float speed)
     41    : env_(env),
     42      capturer_(std::move(capturer)),
     43      renderer_(std::move(renderer)),
     44      process_interval_us_(kFrameLengthUs / speed),
     45      audio_buffer_(nullptr),
     46      rendering_(false),
     47      capturing_(false) {
     48  auto good_sample_rate = [](int sr) {
     49    return sr == 8000 || sr == 16000 || sr == 24000 || sr == 32000 ||
     50           sr == 44100 || sr == 48000;
     51  };
     52 
     53  if (renderer_) {
     54    const int sample_rate = renderer_->SamplingFrequency();
     55    playout_buffer_.resize(TestAudioDeviceModule::SamplesPerFrame(sample_rate) *
     56                               renderer_->NumChannels(),
     57                           0);
     58    RTC_CHECK(good_sample_rate(sample_rate));
     59  }
     60  if (capturer_) {
     61    RTC_CHECK(good_sample_rate(capturer_->SamplingFrequency()));
     62  }
     63 }
     64 
     65 AudioDeviceGeneric::InitStatus TestAudioDevice::Init() {
     66  task_queue_ = env_.task_queue_factory().CreateTaskQueue(
     67      "TestAudioDeviceModuleImpl", TaskQueueFactory::Priority::NORMAL);
     68 
     69  RepeatingTaskHandle::Start(task_queue_.get(), [this]() {
     70    ProcessAudio();
     71    return TimeDelta::Micros(process_interval_us_);
     72  });
     73  return InitStatus::OK;
     74 }
     75 
     76 int32_t TestAudioDevice::PlayoutIsAvailable(bool& available) {
     77  MutexLock lock(&lock_);
     78  available = renderer_ != nullptr;
     79  return 0;
     80 }
     81 
     82 int32_t TestAudioDevice::InitPlayout() {
     83  MutexLock lock(&lock_);
     84 
     85  if (rendering_) {
     86    return -1;
     87  }
     88 
     89  if (audio_buffer_ != nullptr && renderer_ != nullptr) {
     90    // Update webrtc audio buffer with the selected parameters
     91    audio_buffer_->SetPlayoutSampleRate(renderer_->SamplingFrequency());
     92    audio_buffer_->SetPlayoutChannels(renderer_->NumChannels());
     93  }
     94  rendering_initialized_ = true;
     95  return 0;
     96 }
     97 
     98 bool TestAudioDevice::PlayoutIsInitialized() const {
     99  MutexLock lock(&lock_);
    100  return rendering_initialized_;
    101 }
    102 
    103 int32_t TestAudioDevice::StartPlayout() {
    104  MutexLock lock(&lock_);
    105  RTC_CHECK(renderer_);
    106  rendering_ = true;
    107  return 0;
    108 }
    109 
    110 int32_t TestAudioDevice::StopPlayout() {
    111  MutexLock lock(&lock_);
    112  rendering_ = false;
    113  return 0;
    114 }
    115 
    116 int32_t TestAudioDevice::RecordingIsAvailable(bool& available) {
    117  MutexLock lock(&lock_);
    118  available = capturer_ != nullptr;
    119  return 0;
    120 }
    121 
    122 int32_t TestAudioDevice::InitRecording() {
    123  MutexLock lock(&lock_);
    124 
    125  if (capturing_) {
    126    return -1;
    127  }
    128 
    129  if (audio_buffer_ != nullptr && capturer_ != nullptr) {
    130    // Update webrtc audio buffer with the selected parameters
    131    audio_buffer_->SetRecordingSampleRate(capturer_->SamplingFrequency());
    132    audio_buffer_->SetRecordingChannels(capturer_->NumChannels());
    133  }
    134  capturing_initialized_ = true;
    135  return 0;
    136 }
    137 
    138 bool TestAudioDevice::RecordingIsInitialized() const {
    139  MutexLock lock(&lock_);
    140  return capturing_initialized_;
    141 }
    142 
    143 int32_t TestAudioDevice::StartRecording() {
    144  MutexLock lock(&lock_);
    145  capturing_ = true;
    146  return 0;
    147 }
    148 
    149 int32_t TestAudioDevice::StopRecording() {
    150  MutexLock lock(&lock_);
    151  capturing_ = false;
    152  return 0;
    153 }
    154 
    155 bool TestAudioDevice::Playing() const {
    156  MutexLock lock(&lock_);
    157  return rendering_;
    158 }
    159 
    160 bool TestAudioDevice::Recording() const {
    161  MutexLock lock(&lock_);
    162  return capturing_;
    163 }
    164 
    165 void TestAudioDevice::ProcessAudio() {
    166  MutexLock lock(&lock_);
    167  if (audio_buffer_ == nullptr) {
    168    return;
    169  }
    170  if (capturing_ && capturer_ != nullptr) {
    171    // Capture 10ms of audio. 2 bytes per sample.
    172    const bool keep_capturing = capturer_->Capture(&recording_buffer_);
    173    if (!recording_buffer_.empty()) {
    174      audio_buffer_->SetRecordedBuffer(
    175          recording_buffer_.data(),
    176          recording_buffer_.size() / capturer_->NumChannels(),
    177          std::make_optional(env_.clock().CurrentTime().ns()));
    178      audio_buffer_->DeliverRecordedData();
    179    }
    180    if (!keep_capturing) {
    181      capturing_ = false;
    182    }
    183  }
    184  if (rendering_) {
    185    const int sampling_frequency = renderer_->SamplingFrequency();
    186    int32_t samples_per_channel = audio_buffer_->RequestPlayoutData(
    187        TestAudioDeviceModule::SamplesPerFrame(sampling_frequency));
    188    audio_buffer_->GetPlayoutData(playout_buffer_.data());
    189    size_t samples_out = samples_per_channel * renderer_->NumChannels();
    190    RTC_CHECK_LE(samples_out, playout_buffer_.size());
    191    const bool keep_rendering = renderer_->Render(
    192        ArrayView<const int16_t>(playout_buffer_.data(), samples_out));
    193    if (!keep_rendering) {
    194      rendering_ = false;
    195    }
    196  }
    197 }
    198 
    199 void TestAudioDevice::AttachAudioBuffer(AudioDeviceBuffer* audio_buffer) {
    200  MutexLock lock(&lock_);
    201  RTC_DCHECK(audio_buffer || audio_buffer_);
    202  audio_buffer_ = audio_buffer;
    203 
    204  if (renderer_ != nullptr) {
    205    audio_buffer_->SetPlayoutSampleRate(renderer_->SamplingFrequency());
    206    audio_buffer_->SetPlayoutChannels(renderer_->NumChannels());
    207  }
    208  if (capturer_ != nullptr) {
    209    audio_buffer_->SetRecordingSampleRate(capturer_->SamplingFrequency());
    210    audio_buffer_->SetRecordingChannels(capturer_->NumChannels());
    211  }
    212 }
    213 
    214 }  // namespace webrtc