tor-browser

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

audio_frame.cc (8125B)


      1 /*
      2 *  Copyright (c) 2018 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 "api/audio/audio_frame.h"
     12 
     13 #include <cstdint>
     14 #include <cstring>
     15 #include <optional>
     16 
     17 #include "api/array_view.h"
     18 #include "api/audio/audio_view.h"
     19 #include "api/audio/channel_layout.h"
     20 #include "api/rtp_packet_infos.h"
     21 #include "rtc_base/checks.h"
     22 
     23 namespace webrtc {
     24 
     25 AudioFrame::AudioFrame() {
     26  // Visual Studio doesn't like this in the class definition.
     27  static_assert(sizeof(data_) == kMaxDataSizeBytes, "kMaxDataSizeBytes");
     28 }
     29 
     30 AudioFrame::AudioFrame(int sample_rate_hz,
     31                       size_t num_channels,
     32                       ChannelLayout layout /*= CHANNEL_LAYOUT_UNSUPPORTED*/)
     33    : samples_per_channel_(SampleRateToDefaultChannelSize(sample_rate_hz)),
     34      sample_rate_hz_(sample_rate_hz),
     35      num_channels_(num_channels),
     36      channel_layout_(layout == CHANNEL_LAYOUT_UNSUPPORTED
     37                          ? GuessChannelLayout(num_channels)
     38                          : layout) {
     39  RTC_DCHECK_LE(num_channels_, kMaxNumberOfAudioChannels);
     40  RTC_DCHECK_GT(sample_rate_hz_, 0);
     41  RTC_DCHECK_GT(samples_per_channel_, 0u);
     42 }
     43 
     44 void AudioFrame::Reset() {
     45  ResetWithoutMuting();
     46  muted_ = true;
     47 }
     48 
     49 void AudioFrame::ResetWithoutMuting() {
     50  // TODO(wu): Zero is a valid value for `timestamp_`. We should initialize
     51  // to an invalid value, or add a new member to indicate invalidity.
     52  timestamp_ = 0;
     53  elapsed_time_ms_ = -1;
     54  ntp_time_ms_ = -1;
     55  samples_per_channel_ = 0;
     56  sample_rate_hz_ = 0;
     57  num_channels_ = 0;
     58  channel_layout_ = CHANNEL_LAYOUT_NONE;
     59  speech_type_ = kUndefined;
     60  vad_activity_ = kVadUnknown;
     61  packet_infos_ = RtpPacketInfos();
     62  absolute_capture_timestamp_ms_ = std::nullopt;
     63 }
     64 
     65 void AudioFrame::UpdateFrame(uint32_t timestamp,
     66                             const int16_t* data,
     67                             size_t samples_per_channel,
     68                             int sample_rate_hz,
     69                             SpeechType speech_type,
     70                             VADActivity vad_activity,
     71                             size_t num_channels) {
     72  RTC_CHECK_LE(num_channels, kMaxNumberOfAudioChannels);
     73  timestamp_ = timestamp;
     74  samples_per_channel_ = samples_per_channel;
     75  sample_rate_hz_ = sample_rate_hz;
     76  speech_type_ = speech_type;
     77  vad_activity_ = vad_activity;
     78  num_channels_ = num_channels;
     79  channel_layout_ = GuessChannelLayout(num_channels);
     80  if (channel_layout_ != CHANNEL_LAYOUT_UNSUPPORTED) {
     81    RTC_DCHECK_EQ(num_channels, ChannelLayoutToChannelCount(channel_layout_));
     82  }
     83 
     84  const size_t length = samples_per_channel * num_channels;
     85  RTC_CHECK_LE(length, data_.size());
     86  if (data != nullptr) {
     87    memcpy(data_.data(), data, sizeof(int16_t) * length);
     88    muted_ = false;
     89  } else {
     90    muted_ = true;
     91  }
     92 }
     93 
     94 void AudioFrame::CopyFrom(const AudioFrame& src) {
     95  if (this == &src)
     96    return;
     97 
     98  if (muted_ && !src.muted()) {
     99    // TODO: bugs.webrtc.org/5647 - Since the default value for `muted_` is
    100    // false and `data_` may still be uninitialized (because we don't initialize
    101    // data_ as part of construction), we clear the full buffer here before
    102    // copying over new values. If we don't, msan might complain in some tests.
    103    // Consider locking down construction, avoiding the default constructor and
    104    // prefering construction that initializes all state.
    105    ClearSamples(data_);
    106  }
    107 
    108  timestamp_ = src.timestamp_;
    109  elapsed_time_ms_ = src.elapsed_time_ms_;
    110  ntp_time_ms_ = src.ntp_time_ms_;
    111  packet_infos_ = src.packet_infos_;
    112  muted_ = src.muted();
    113  samples_per_channel_ = src.samples_per_channel_;
    114  sample_rate_hz_ = src.sample_rate_hz_;
    115  speech_type_ = src.speech_type_;
    116  vad_activity_ = src.vad_activity_;
    117  num_channels_ = src.num_channels_;
    118  channel_layout_ = src.channel_layout_;
    119  absolute_capture_timestamp_ms_ = src.absolute_capture_timestamp_ms();
    120 
    121  auto data = src.data_view();
    122  RTC_CHECK_LE(data.size(), data_.size());
    123  if (!muted_ && !data.empty()) {
    124    memcpy(&data_[0], &data[0], sizeof(int16_t) * data.size());
    125  }
    126 }
    127 
    128 const int16_t* AudioFrame::data() const {
    129  return muted_ ? zeroed_data().begin() : data_.data();
    130 }
    131 
    132 InterleavedView<const int16_t> AudioFrame::data_view() const {
    133  // If you get a nullptr from `data_view()`, it's likely because the
    134  // samples_per_channel_ and/or num_channels_ members haven't been properly
    135  // set. Since `data_view()` returns an InterleavedView<> (which internally
    136  // uses ArrayView<>), we inherit the behavior in InterleavedView when
    137  // the view size is 0 that ArrayView<>::data() returns nullptr. So, even when
    138  // an AudioFrame is muted and we want to return `zeroed_data()`, if
    139  // samples_per_channel_ or  num_channels_ is 0, the view will point to
    140  // nullptr.
    141  return InterleavedView<const int16_t>(muted_ ? &zeroed_data()[0] : &data_[0],
    142                                        samples_per_channel_, num_channels_);
    143 }
    144 
    145 int16_t* AudioFrame::mutable_data() {
    146  // TODO: bugs.webrtc.org/5647 - Can we skip zeroing the buffer?
    147  // Consider instead if we should rather zero the buffer when `muted_` is set
    148  // to `true`.
    149  if (muted_) {
    150    ClearSamples(data_);
    151    muted_ = false;
    152  }
    153  return &data_[0];
    154 }
    155 
    156 InterleavedView<int16_t> AudioFrame::mutable_data(size_t samples_per_channel,
    157                                                  size_t num_channels) {
    158  const size_t total_samples = samples_per_channel * num_channels;
    159  RTC_CHECK_LE(total_samples, data_.size());
    160  RTC_CHECK_LE(num_channels, kMaxNumberOfAudioChannels);
    161  // Sanity check for valid argument values during development.
    162  // If `samples_per_channel` is < `num_channels` but larger than 0,
    163  // then chances are the order of arguments is incorrect.
    164  RTC_DCHECK((samples_per_channel == 0 && num_channels == 0) ||
    165             num_channels <= samples_per_channel)
    166      << "samples_per_channel=" << samples_per_channel
    167      << "num_channels=" << num_channels;
    168 
    169  // TODO: bugs.webrtc.org/5647 - Can we skip zeroing the buffer?
    170  // Consider instead if we should rather zero the whole buffer when `muted_` is
    171  // set to `true`.
    172  if (muted_) {
    173    ClearSamples(data_, total_samples);
    174    muted_ = false;
    175  }
    176  samples_per_channel_ = samples_per_channel;
    177  num_channels_ = num_channels;
    178  return InterleavedView<int16_t>(&data_[0], samples_per_channel, num_channels);
    179 }
    180 
    181 void AudioFrame::Mute() {
    182  muted_ = true;
    183 }
    184 
    185 bool AudioFrame::muted() const {
    186  return muted_;
    187 }
    188 
    189 void AudioFrame::SetLayoutAndNumChannels(ChannelLayout layout,
    190                                         size_t num_channels) {
    191  channel_layout_ = layout;
    192  num_channels_ = num_channels;
    193 #if RTC_DCHECK_IS_ON
    194  // Do a sanity check that the layout and num_channels match.
    195  // If this lookup yield 0u, then the layout is likely CHANNEL_LAYOUT_DISCRETE.
    196  auto expected_num_channels = ChannelLayoutToChannelCount(layout);
    197  if (expected_num_channels) {  // If expected_num_channels is 0
    198    RTC_DCHECK_EQ(expected_num_channels, num_channels_);
    199  }
    200 #endif
    201  RTC_CHECK_LE(samples_per_channel_ * num_channels_, data_.size());
    202 }
    203 
    204 void AudioFrame::SetSampleRateAndChannelSize(int sample_rate) {
    205  sample_rate_hz_ = sample_rate;
    206  // We could call `AudioProcessing::GetFrameSize()` here, but that requires
    207  // adding a dependency on the ":audio_processing" build target, which can
    208  // complicate the dependency tree. Some refactoring is probably in order to
    209  // get some consistency around this since there are many places across the
    210  // code that assume this default buffer size.
    211  samples_per_channel_ = SampleRateToDefaultChannelSize(sample_rate_hz_);
    212 }
    213 
    214 // static
    215 ArrayView<const int16_t> AudioFrame::zeroed_data() {
    216  static int16_t* null_data = new int16_t[kMaxDataSizeSamples]();
    217  return ArrayView<const int16_t>(null_data, kMaxDataSizeSamples);
    218 }
    219 
    220 }  // namespace webrtc