tor-browser

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

audio_frame_operations.cc (7311B)


      1 /*
      2 *  Copyright (c) 2012 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 "audio/utility/audio_frame_operations.h"
     12 
     13 #include <algorithm>
     14 #include <cstdint>
     15 #include <cstring>
     16 #include <utility>
     17 
     18 #include "api/audio/audio_frame.h"
     19 #include "api/audio/audio_view.h"
     20 #include "common_audio/include/audio_util.h"
     21 #include "rtc_base/checks.h"
     22 #include "rtc_base/numerics/safe_conversions.h"
     23 
     24 namespace webrtc {
     25 namespace {
     26 
     27 // 2.7ms @ 48kHz, 4ms @ 32kHz, 8ms @ 16kHz.
     28 const size_t kMuteFadeFrames = 128;
     29 const float kMuteFadeInc = 1.0f / kMuteFadeFrames;
     30 
     31 }  // namespace
     32 
     33 void AudioFrameOperations::QuadToStereo(
     34    InterleavedView<const int16_t> src_audio,
     35    InterleavedView<int16_t> dst_audio) {
     36  RTC_DCHECK_EQ(NumChannels(src_audio), 4);
     37  RTC_DCHECK_EQ(NumChannels(dst_audio), 2);
     38  RTC_DCHECK_EQ(SamplesPerChannel(src_audio), SamplesPerChannel(dst_audio));
     39  for (size_t i = 0; i < SamplesPerChannel(src_audio); ++i) {
     40    auto dst_frame = i * 2;
     41    dst_audio[dst_frame] =
     42        (static_cast<int32_t>(src_audio[4 * i]) + src_audio[4 * i + 1]) >> 1;
     43    dst_audio[dst_frame + 1] =
     44        (static_cast<int32_t>(src_audio[4 * i + 2]) + src_audio[4 * i + 3]) >>
     45        1;
     46  }
     47 }
     48 
     49 int AudioFrameOperations::QuadToStereo(AudioFrame* frame) {
     50  if (frame->num_channels_ != 4) {
     51    return -1;
     52  }
     53 
     54  RTC_DCHECK_LE(frame->samples_per_channel_ * 4,
     55                AudioFrame::kMaxDataSizeSamples);
     56 
     57  if (!frame->muted()) {
     58    // Note that `src` and `dst` will map in to the same buffer, but the call
     59    // to `mutable_data()` changes the layout of `frame`, so `src` and `dst`
     60    // will have different dimensions (important to call `data_view()` first).
     61    auto src = frame->data_view();
     62    auto dst = frame->mutable_data(frame->samples_per_channel_, 2);
     63    QuadToStereo(src, dst);
     64  } else {
     65    frame->num_channels_ = 2;
     66  }
     67 
     68  return 0;
     69 }
     70 
     71 void AudioFrameOperations::DownmixChannels(
     72    InterleavedView<const int16_t> src_audio,
     73    InterleavedView<int16_t> dst_audio) {
     74  RTC_DCHECK_EQ(SamplesPerChannel(src_audio), SamplesPerChannel(dst_audio));
     75  if (NumChannels(src_audio) > 1 && IsMono(dst_audio)) {
     76    // TODO(tommi): change DownmixInterleavedToMono to support InterleavedView
     77    // and MonoView.
     78    DownmixInterleavedToMono(&src_audio.data()[0], SamplesPerChannel(src_audio),
     79                             NumChannels(src_audio), &dst_audio.data()[0]);
     80  } else if (NumChannels(src_audio) == 4 && NumChannels(dst_audio) == 2) {
     81    QuadToStereo(src_audio, dst_audio);
     82  } else {
     83    RTC_DCHECK_NOTREACHED() << "src_channels: " << NumChannels(src_audio)
     84                            << ", dst_channels: " << NumChannels(dst_audio);
     85  }
     86 }
     87 
     88 void AudioFrameOperations::DownmixChannels(size_t dst_channels,
     89                                           AudioFrame* frame) {
     90  RTC_DCHECK_LE(frame->samples_per_channel_ * frame->num_channels_,
     91                AudioFrame::kMaxDataSizeSamples);
     92  if (frame->num_channels_ > 1 && dst_channels == 1) {
     93    if (!frame->muted()) {
     94      DownmixInterleavedToMono(frame->data(), frame->samples_per_channel_,
     95                               frame->num_channels_, frame->mutable_data());
     96    }
     97    frame->num_channels_ = 1;
     98  } else if (frame->num_channels_ == 4 && dst_channels == 2) {
     99    int err = QuadToStereo(frame);
    100    RTC_DCHECK_EQ(err, 0);
    101  } else {
    102    RTC_DCHECK_NOTREACHED() << "src_channels: " << frame->num_channels_
    103                            << ", dst_channels: " << dst_channels;
    104  }
    105 }
    106 
    107 void AudioFrameOperations::UpmixChannels(size_t target_number_of_channels,
    108                                         AudioFrame* frame) {
    109  RTC_DCHECK_EQ(frame->num_channels_, 1);
    110  RTC_DCHECK_LE(frame->samples_per_channel_ * target_number_of_channels,
    111                AudioFrame::kMaxDataSizeSamples);
    112 
    113  if (frame->num_channels_ != 1 ||
    114      frame->samples_per_channel_ * target_number_of_channels >
    115          AudioFrame::kMaxDataSizeSamples) {
    116    return;
    117  }
    118 
    119  if (!frame->muted()) {
    120    // Up-mixing done in place. Going backwards through the frame ensure nothing
    121    // is irrevocably overwritten.
    122    auto frame_data = frame->mutable_data(frame->samples_per_channel_,
    123                                          target_number_of_channels);
    124    for (int i = frame->samples_per_channel_ - 1; i >= 0; --i) {
    125      for (size_t j = 0; j < target_number_of_channels; ++j) {
    126        frame_data[target_number_of_channels * i + j] = frame_data[i];
    127      }
    128    }
    129  } else {
    130    frame->num_channels_ = target_number_of_channels;
    131  }
    132 }
    133 
    134 void AudioFrameOperations::SwapStereoChannels(AudioFrame* frame) {
    135  RTC_DCHECK(frame);
    136  if (frame->num_channels_ != 2 || frame->muted()) {
    137    return;
    138  }
    139 
    140  int16_t* frame_data = frame->mutable_data();
    141  for (size_t i = 0; i < frame->samples_per_channel_ * 2; i += 2) {
    142    std::swap(frame_data[i], frame_data[i + 1]);
    143  }
    144 }
    145 
    146 void AudioFrameOperations::Mute(AudioFrame* frame,
    147                                bool previous_frame_muted,
    148                                bool current_frame_muted) {
    149  RTC_DCHECK(frame);
    150  if (!previous_frame_muted && !current_frame_muted) {
    151    // Not muted, don't touch.
    152  } else if (previous_frame_muted && current_frame_muted) {
    153    // Frame fully muted.
    154    size_t total_samples = frame->samples_per_channel_ * frame->num_channels_;
    155    RTC_DCHECK_GE(AudioFrame::kMaxDataSizeSamples, total_samples);
    156    frame->Mute();
    157  } else {
    158    // Fade is a no-op on a muted frame.
    159    if (frame->muted()) {
    160      return;
    161    }
    162 
    163    // Limit number of samples to fade, if frame isn't long enough.
    164    size_t count = kMuteFadeFrames;
    165    float inc = kMuteFadeInc;
    166    if (frame->samples_per_channel_ < kMuteFadeFrames) {
    167      count = frame->samples_per_channel_;
    168      if (count > 0) {
    169        inc = 1.0f / count;
    170      }
    171    }
    172 
    173    size_t start = 0;
    174    size_t end = count;
    175    float start_g = 0.0f;
    176    if (current_frame_muted) {
    177      // Fade out the last `count` samples of frame.
    178      RTC_DCHECK(!previous_frame_muted);
    179      start = frame->samples_per_channel_ - count;
    180      end = frame->samples_per_channel_;
    181      start_g = 1.0f;
    182      inc = -inc;
    183    } else {
    184      // Fade in the first `count` samples of frame.
    185      RTC_DCHECK(previous_frame_muted);
    186    }
    187 
    188    // Perform fade.
    189    int16_t* frame_data = frame->mutable_data();
    190    size_t channels = frame->num_channels_;
    191    for (size_t j = 0; j < channels; ++j) {
    192      float g = start_g;
    193      for (size_t i = start * channels; i < end * channels; i += channels) {
    194        g += inc;
    195        frame_data[i + j] *= g;
    196      }
    197    }
    198  }
    199 }
    200 
    201 void AudioFrameOperations::Mute(AudioFrame* frame) {
    202  Mute(frame, true, true);
    203 }
    204 
    205 int AudioFrameOperations::ScaleWithSat(float scale, AudioFrame* frame) {
    206  if (frame->muted()) {
    207    return 0;
    208  }
    209 
    210  int16_t* frame_data = frame->mutable_data();
    211  for (size_t i = 0; i < frame->samples_per_channel_ * frame->num_channels_;
    212       i++) {
    213    frame_data[i] = saturated_cast<int16_t>(scale * frame_data[i]);
    214  }
    215  return 0;
    216 }
    217 }  // namespace webrtc