tor-browser

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

acm_remixing.cc (4294B)


      1 /*
      2 *  Copyright (c) 2019 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_coding/acm2/acm_remixing.h"
     12 
     13 #include <algorithm>
     14 #include <cstddef>
     15 #include <cstdint>
     16 #include <vector>
     17 
     18 #include "api/array_view.h"
     19 #include "api/audio/audio_frame.h"
     20 #include "rtc_base/checks.h"
     21 #include "rtc_base/numerics/safe_conversions.h"
     22 
     23 namespace webrtc {
     24 
     25 void DownMixFrame(const AudioFrame& input, ArrayView<int16_t> output) {
     26  RTC_DCHECK_EQ(input.num_channels_, 2);
     27  RTC_DCHECK_EQ(output.size(), input.samples_per_channel_);
     28 
     29  if (input.muted()) {
     30    std::fill(output.begin(), output.begin() + input.samples_per_channel_, 0);
     31  } else {
     32    const int16_t* const input_data = input.data();
     33    for (size_t n = 0; n < input.samples_per_channel_; ++n) {
     34      output[n] = dchecked_cast<int16_t>(
     35          (int32_t{input_data[2 * n]} + int32_t{input_data[2 * n + 1]}) >> 1);
     36    }
     37  }
     38 }
     39 
     40 void ReMixFrame(const AudioFrame& input,
     41                size_t num_output_channels,
     42                std::vector<int16_t>* output) {
     43  const size_t output_size = num_output_channels * input.samples_per_channel_;
     44  RTC_DCHECK(!(input.num_channels_ == 0 && num_output_channels > 0 &&
     45               input.samples_per_channel_ > 0));
     46 
     47  if (output->size() != output_size) {
     48    output->resize(output_size);
     49  }
     50 
     51  // For muted frames, fill the frame with zeros.
     52  if (input.muted()) {
     53    std::fill(output->begin(), output->end(), 0);
     54    return;
     55  }
     56 
     57  // Ensure that the special case of zero input channels is handled correctly
     58  // (zero samples per channel is already handled correctly in the code below).
     59  if (input.num_channels_ == 0) {
     60    return;
     61  }
     62 
     63  const int16_t* const input_data = input.data();
     64  size_t out_index = 0;
     65 
     66  // When upmixing is needed and the input is mono copy the left channel
     67  // into the left and right channels, and set any remaining channels to zero.
     68  if (input.num_channels_ == 1 && input.num_channels_ < num_output_channels) {
     69    for (size_t k = 0; k < input.samples_per_channel_; ++k) {
     70      (*output)[out_index++] = input_data[k];
     71      (*output)[out_index++] = input_data[k];
     72      for (size_t j = 2; j < num_output_channels; ++j) {
     73        (*output)[out_index++] = 0;
     74      }
     75      RTC_DCHECK_EQ(out_index, (k + 1) * num_output_channels);
     76    }
     77    RTC_DCHECK_EQ(out_index, input.samples_per_channel_ * num_output_channels);
     78    return;
     79  }
     80 
     81  size_t in_index = 0;
     82 
     83  // When upmixing is needed and the output is surround, copy the available
     84  // channels directly, and set the remaining channels to zero.
     85  if (input.num_channels_ < num_output_channels) {
     86    for (size_t k = 0; k < input.samples_per_channel_; ++k) {
     87      for (size_t j = 0; j < input.num_channels_; ++j) {
     88        (*output)[out_index++] = input_data[in_index++];
     89      }
     90      for (size_t j = input.num_channels_; j < num_output_channels; ++j) {
     91        (*output)[out_index++] = 0;
     92      }
     93      RTC_DCHECK_EQ(in_index, (k + 1) * input.num_channels_);
     94      RTC_DCHECK_EQ(out_index, (k + 1) * num_output_channels);
     95    }
     96    RTC_DCHECK_EQ(in_index, input.samples_per_channel_ * input.num_channels_);
     97    RTC_DCHECK_EQ(out_index, input.samples_per_channel_ * num_output_channels);
     98 
     99    return;
    100  }
    101 
    102  // When downmixing is needed, and the input is stereo, average the channels.
    103  if (input.num_channels_ == 2) {
    104    for (size_t n = 0; n < input.samples_per_channel_; ++n) {
    105      (*output)[n] = dchecked_cast<int16_t>(
    106          (int32_t{input_data[2 * n]} + int32_t{input_data[2 * n + 1]}) >> 1);
    107    }
    108    return;
    109  }
    110 
    111  // When downmixing is needed, and the input is multichannel, drop the surplus
    112  // channels.
    113  const size_t num_channels_to_drop = input.num_channels_ - num_output_channels;
    114  for (size_t k = 0; k < input.samples_per_channel_; ++k) {
    115    for (size_t j = 0; j < num_output_channels; ++j) {
    116      (*output)[out_index++] = input_data[in_index++];
    117    }
    118    in_index += num_channels_to_drop;
    119  }
    120 }
    121 
    122 }  // namespace webrtc