tor-browser

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

fine_audio_buffer.cc (5708B)


      1 /*
      2 *  Copyright (c) 2013 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_device/fine_audio_buffer.h"
     12 
     13 #include <cstdint>
     14 #include <cstring>
     15 #include <optional>
     16 
     17 #include "api/array_view.h"
     18 #include "modules/audio_device/audio_device_buffer.h"
     19 #include "rtc_base/checks.h"
     20 #include "rtc_base/logging.h"
     21 #include "rtc_base/numerics/safe_conversions.h"
     22 
     23 namespace webrtc {
     24 
     25 FineAudioBuffer::FineAudioBuffer(AudioDeviceBuffer* audio_device_buffer)
     26    : audio_device_buffer_(audio_device_buffer),
     27      playout_samples_per_channel_10ms_(dchecked_cast<size_t>(
     28          audio_device_buffer->PlayoutSampleRate() * 10 / 1000)),
     29      record_samples_per_channel_10ms_(dchecked_cast<size_t>(
     30          audio_device_buffer->RecordingSampleRate() * 10 / 1000)),
     31      playout_channels_(audio_device_buffer->PlayoutChannels()),
     32      record_channels_(audio_device_buffer->RecordingChannels()) {
     33  RTC_DCHECK(audio_device_buffer_);
     34  RTC_DLOG(LS_INFO) << __FUNCTION__;
     35  if (IsReadyForPlayout()) {
     36    RTC_DLOG(LS_INFO) << "playout_samples_per_channel_10ms: "
     37                      << playout_samples_per_channel_10ms_;
     38    RTC_DLOG(LS_INFO) << "playout_channels: " << playout_channels_;
     39  }
     40  if (IsReadyForRecord()) {
     41    RTC_DLOG(LS_INFO) << "record_samples_per_channel_10ms: "
     42                      << record_samples_per_channel_10ms_;
     43    RTC_DLOG(LS_INFO) << "record_channels: " << record_channels_;
     44  }
     45 }
     46 
     47 FineAudioBuffer::~FineAudioBuffer() {
     48  RTC_DLOG(LS_INFO) << __FUNCTION__;
     49 }
     50 
     51 void FineAudioBuffer::ResetPlayout() {
     52  playout_buffer_.Clear();
     53 }
     54 
     55 void FineAudioBuffer::ResetRecord() {
     56  record_buffer_.Clear();
     57 }
     58 
     59 bool FineAudioBuffer::IsReadyForPlayout() const {
     60  return playout_samples_per_channel_10ms_ > 0 && playout_channels_ > 0;
     61 }
     62 
     63 bool FineAudioBuffer::IsReadyForRecord() const {
     64  return record_samples_per_channel_10ms_ > 0 && record_channels_ > 0;
     65 }
     66 
     67 void FineAudioBuffer::GetPlayoutData(ArrayView<int16_t> audio_buffer,
     68                                     int playout_delay_ms) {
     69  RTC_DCHECK(IsReadyForPlayout());
     70  // Ask WebRTC for new data in chunks of 10ms until we have enough to
     71  // fulfill the request. It is possible that the buffer already contains
     72  // enough samples from the last round.
     73  while (playout_buffer_.size() < audio_buffer.size()) {
     74    // Get 10ms decoded audio from WebRTC. The ADB knows about number of
     75    // channels; hence we can ask for number of samples per channel here.
     76    if (audio_device_buffer_->RequestPlayoutData(
     77            playout_samples_per_channel_10ms_) ==
     78        static_cast<int32_t>(playout_samples_per_channel_10ms_)) {
     79      // Append 10ms to the end of the local buffer taking number of channels
     80      // into account.
     81      const size_t num_elements_10ms =
     82          playout_channels_ * playout_samples_per_channel_10ms_;
     83      const size_t written_elements = playout_buffer_.AppendData(
     84          num_elements_10ms, [&](ArrayView<int16_t> buf) {
     85            const size_t samples_per_channel_10ms =
     86                audio_device_buffer_->GetPlayoutData(buf.data());
     87            return playout_channels_ * samples_per_channel_10ms;
     88          });
     89      RTC_DCHECK_EQ(num_elements_10ms, written_elements);
     90    } else {
     91      // Provide silence if AudioDeviceBuffer::RequestPlayoutData() fails.
     92      // Can e.g. happen when an AudioTransport has not been registered.
     93      const size_t num_bytes = audio_buffer.size() * sizeof(int16_t);
     94      std::memset(audio_buffer.data(), 0, num_bytes);
     95      return;
     96    }
     97  }
     98 
     99  // Provide the requested number of bytes to the consumer.
    100  const size_t num_bytes = audio_buffer.size() * sizeof(int16_t);
    101  memcpy(audio_buffer.data(), playout_buffer_.data(), num_bytes);
    102  // Move remaining samples to start of buffer to prepare for next round.
    103  memmove(playout_buffer_.data(), playout_buffer_.data() + audio_buffer.size(),
    104          (playout_buffer_.size() - audio_buffer.size()) * sizeof(int16_t));
    105  playout_buffer_.SetSize(playout_buffer_.size() - audio_buffer.size());
    106  // Cache playout latency for usage in DeliverRecordedData();
    107  playout_delay_ms_ = playout_delay_ms;
    108 }
    109 
    110 void FineAudioBuffer::DeliverRecordedData(
    111    ArrayView<const int16_t> audio_buffer,
    112    int record_delay_ms,
    113    std::optional<int64_t> capture_time_ns) {
    114  RTC_DCHECK(IsReadyForRecord());
    115  // Always append new data and grow the buffer when needed.
    116  record_buffer_.AppendData(audio_buffer.data(), audio_buffer.size());
    117  // Consume samples from buffer in chunks of 10ms until there is not
    118  // enough data left. The number of remaining samples in the cache is given by
    119  // the new size of the internal `record_buffer_`.
    120  const size_t num_elements_10ms =
    121      record_channels_ * record_samples_per_channel_10ms_;
    122  while (record_buffer_.size() >= num_elements_10ms) {
    123    audio_device_buffer_->SetRecordedBuffer(record_buffer_.data(),
    124                                            record_samples_per_channel_10ms_,
    125                                            capture_time_ns);
    126    audio_device_buffer_->SetVQEData(playout_delay_ms_, record_delay_ms);
    127    audio_device_buffer_->DeliverRecordedData();
    128    memmove(record_buffer_.data(), record_buffer_.data() + num_elements_10ms,
    129            (record_buffer_.size() - num_elements_10ms) * sizeof(int16_t));
    130    record_buffer_.SetSize(record_buffer_.size() - num_elements_10ms);
    131  }
    132 }
    133 
    134 }  // namespace webrtc