tor-browser

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

channel_mixer.cc (4147B)


      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/channel_mixer.h"
     12 
     13 #include <cstddef>
     14 #include <cstdint>
     15 #include <cstring>
     16 
     17 #include "api/audio/audio_frame.h"
     18 #include "api/audio/channel_layout.h"
     19 #include "audio/utility/channel_mixing_matrix.h"
     20 #include "rtc_base/checks.h"
     21 #include "rtc_base/numerics/safe_conversions.h"
     22 
     23 namespace webrtc {
     24 
     25 ChannelMixer::ChannelMixer(ChannelLayout input_layout,
     26                           size_t input_channels,
     27                           ChannelLayout output_layout,
     28                           size_t output_channels)
     29    : input_layout_(input_layout),
     30      output_layout_(output_layout),
     31      input_channels_(input_channels),
     32      output_channels_(output_channels) {
     33  // Create the transformation matrix.
     34  ChannelMixingMatrix matrix_builder(input_layout_, input_channels_,
     35                                     output_layout_, output_channels_);
     36  remapping_ = matrix_builder.CreateTransformationMatrix(&matrix_);
     37 }
     38 
     39 ChannelMixer::ChannelMixer(ChannelLayout input_layout,
     40                           ChannelLayout output_layout)
     41    : ChannelMixer(input_layout,
     42                   ChannelLayoutToChannelCount(input_layout),
     43                   output_layout,
     44                   ChannelLayoutToChannelCount(output_layout)) {}
     45 
     46 ChannelMixer::~ChannelMixer() = default;
     47 
     48 void ChannelMixer::Transform(AudioFrame* frame) {
     49  RTC_DCHECK(frame);
     50  RTC_DCHECK_EQ(matrix_[0].size(), static_cast<size_t>(input_channels_));
     51  RTC_DCHECK_EQ(matrix_.size(), static_cast<size_t>(output_channels_));
     52 
     53  // Leave the audio frame intact if the channel layouts for in and out are
     54  // identical.
     55  if (input_layout_ == output_layout_) {
     56    return;
     57  }
     58 
     59  if (IsUpMixing()) {
     60    RTC_CHECK_LE(frame->samples_per_channel() * output_channels_,
     61                 frame->max_16bit_samples());
     62  }
     63 
     64  // Only change the number of output channels if the audio frame is muted.
     65  if (frame->muted()) {
     66    frame->SetLayoutAndNumChannels(output_layout_, output_channels_);
     67    return;
     68  }
     69 
     70  const int16_t* in_audio = frame->data();
     71 
     72  // Only allocate fresh memory at first access or if the required size has
     73  // increased.
     74  // TODO(henrika): we might be able to do downmixing in-place and thereby avoid
     75  // extra memory allocation and a memcpy.
     76  const size_t num_elements = frame->samples_per_channel() * output_channels_;
     77  if (audio_vector_ == nullptr || num_elements > audio_vector_size_) {
     78    audio_vector_.reset(new int16_t[num_elements]);
     79    audio_vector_size_ = num_elements;
     80  }
     81  int16_t* out_audio = audio_vector_.get();
     82 
     83  // Modify the number of channels by creating a weighted sum of input samples
     84  // where the weights (scale factors) for each output sample are given by the
     85  // transformation matrix.
     86  for (size_t i = 0; i < frame->samples_per_channel(); i++) {
     87    for (size_t output_ch = 0; output_ch < output_channels_; ++output_ch) {
     88      float acc_value = 0.0f;
     89      for (size_t input_ch = 0; input_ch < input_channels_; ++input_ch) {
     90        const float scale = matrix_[output_ch][input_ch];
     91        // Scale should always be positive.
     92        RTC_DCHECK_GE(scale, 0);
     93        // Each output sample is a weighted sum of input samples.
     94        acc_value += scale * in_audio[i * input_channels_ + input_ch];
     95      }
     96      const size_t index = output_channels_ * i + output_ch;
     97      RTC_CHECK_LE(index, audio_vector_size_);
     98      out_audio[index] = saturated_cast<int16_t>(acc_value);
     99    }
    100  }
    101 
    102  // Update channel information.
    103  frame->SetLayoutAndNumChannels(output_layout_, output_channels_);
    104 
    105  // Copy the output result to the audio frame in `frame`.
    106  memcpy(
    107      frame->mutable_data(), out_audio,
    108      sizeof(int16_t) * frame->samples_per_channel() * frame->num_channels());
    109 }
    110 
    111 }  // namespace webrtc