tor-browser

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

audio_converter.cc (8012B)


      1 /*
      2 *  Copyright (c) 2014 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 "common_audio/audio_converter.h"
     12 
     13 #include <cstring>
     14 #include <memory>
     15 #include <utility>
     16 #include <vector>
     17 
     18 #include "common_audio/channel_buffer.h"
     19 #include "common_audio/resampler/push_sinc_resampler.h"
     20 #include "rtc_base/checks.h"
     21 
     22 namespace webrtc {
     23 
     24 class CopyConverter : public AudioConverter {
     25 public:
     26  CopyConverter(size_t src_channels,
     27                size_t src_frames,
     28                size_t dst_channels,
     29                size_t dst_frames)
     30      : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
     31  ~CopyConverter() override {}
     32 
     33  void Convert(const float* const* src,
     34               size_t src_size,
     35               float* const* dst,
     36               size_t dst_capacity) override {
     37    CheckSizes(src_size, dst_capacity);
     38    if (src != dst) {
     39      for (size_t i = 0; i < src_channels(); ++i)
     40        std::memcpy(dst[i], src[i], dst_frames() * sizeof(*dst[i]));
     41    }
     42  }
     43 };
     44 
     45 class UpmixConverter : public AudioConverter {
     46 public:
     47  UpmixConverter(size_t src_channels,
     48                 size_t src_frames,
     49                 size_t dst_channels,
     50                 size_t dst_frames)
     51      : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
     52  ~UpmixConverter() override {}
     53 
     54  void Convert(const float* const* src,
     55               size_t src_size,
     56               float* const* dst,
     57               size_t dst_capacity) override {
     58    CheckSizes(src_size, dst_capacity);
     59    for (size_t i = 0; i < dst_frames(); ++i) {
     60      const float value = src[0][i];
     61      for (size_t j = 0; j < dst_channels(); ++j)
     62        dst[j][i] = value;
     63    }
     64  }
     65 };
     66 
     67 class DownmixConverter : public AudioConverter {
     68 public:
     69  DownmixConverter(size_t src_channels,
     70                   size_t src_frames,
     71                   size_t dst_channels,
     72                   size_t dst_frames)
     73      : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
     74  ~DownmixConverter() override {}
     75 
     76  void Convert(const float* const* src,
     77               size_t src_size,
     78               float* const* dst,
     79               size_t dst_capacity) override {
     80    CheckSizes(src_size, dst_capacity);
     81    float* dst_mono = dst[0];
     82    for (size_t i = 0; i < src_frames(); ++i) {
     83      float sum = 0;
     84      for (size_t j = 0; j < src_channels(); ++j)
     85        sum += src[j][i];
     86      dst_mono[i] = sum / src_channels();
     87    }
     88  }
     89 };
     90 
     91 class ResampleConverter : public AudioConverter {
     92 public:
     93  ResampleConverter(size_t src_channels,
     94                    size_t src_frames,
     95                    size_t dst_channels,
     96                    size_t dst_frames)
     97      : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {
     98    resamplers_.reserve(src_channels);
     99    for (size_t i = 0; i < src_channels; ++i)
    100      resamplers_.push_back(std::unique_ptr<PushSincResampler>(
    101          new PushSincResampler(src_frames, dst_frames)));
    102  }
    103  ~ResampleConverter() override {}
    104 
    105  void Convert(const float* const* src,
    106               size_t src_size,
    107               float* const* dst,
    108               size_t dst_capacity) override {
    109    CheckSizes(src_size, dst_capacity);
    110    for (size_t i = 0; i < resamplers_.size(); ++i)
    111      resamplers_[i]->Resample(src[i], src_frames(), dst[i], dst_frames());
    112  }
    113 
    114 private:
    115  std::vector<std::unique_ptr<PushSincResampler>> resamplers_;
    116 };
    117 
    118 // Apply a vector of converters in serial, in the order given. At least two
    119 // converters must be provided.
    120 class CompositionConverter : public AudioConverter {
    121 public:
    122  explicit CompositionConverter(
    123      std::vector<std::unique_ptr<AudioConverter>> converters)
    124      : converters_(std::move(converters)) {
    125    RTC_CHECK_GE(converters_.size(), 2);
    126    // We need an intermediate buffer after every converter.
    127    for (auto it = converters_.begin(); it != converters_.end() - 1; ++it)
    128      buffers_.push_back(
    129          std::unique_ptr<ChannelBuffer<float>>(new ChannelBuffer<float>(
    130              (*it)->dst_frames(), (*it)->dst_channels())));
    131  }
    132  ~CompositionConverter() override {}
    133 
    134  void Convert(const float* const* src,
    135               size_t src_size,
    136               float* const* dst,
    137               size_t dst_capacity) override {
    138    converters_.front()->Convert(src, src_size, buffers_.front()->channels(),
    139                                 buffers_.front()->size());
    140    for (size_t i = 2; i < converters_.size(); ++i) {
    141      auto& src_buffer = buffers_[i - 2];
    142      auto& dst_buffer = buffers_[i - 1];
    143      converters_[i]->Convert(src_buffer->channels(), src_buffer->size(),
    144                              dst_buffer->channels(), dst_buffer->size());
    145    }
    146    converters_.back()->Convert(buffers_.back()->channels(),
    147                                buffers_.back()->size(), dst, dst_capacity);
    148  }
    149 
    150 private:
    151  std::vector<std::unique_ptr<AudioConverter>> converters_;
    152  std::vector<std::unique_ptr<ChannelBuffer<float>>> buffers_;
    153 };
    154 
    155 std::unique_ptr<AudioConverter> AudioConverter::Create(size_t src_channels,
    156                                                       size_t src_frames,
    157                                                       size_t dst_channels,
    158                                                       size_t dst_frames) {
    159  std::unique_ptr<AudioConverter> sp;
    160  if (src_channels > dst_channels) {
    161    if (src_frames != dst_frames) {
    162      std::vector<std::unique_ptr<AudioConverter>> converters;
    163      converters.push_back(std::unique_ptr<AudioConverter>(new DownmixConverter(
    164          src_channels, src_frames, dst_channels, src_frames)));
    165      converters.push_back(
    166          std::unique_ptr<AudioConverter>(new ResampleConverter(
    167              dst_channels, src_frames, dst_channels, dst_frames)));
    168      sp.reset(new CompositionConverter(std::move(converters)));
    169    } else {
    170      sp.reset(new DownmixConverter(src_channels, src_frames, dst_channels,
    171                                    dst_frames));
    172    }
    173  } else if (src_channels < dst_channels) {
    174    if (src_frames != dst_frames) {
    175      std::vector<std::unique_ptr<AudioConverter>> converters;
    176      converters.push_back(
    177          std::unique_ptr<AudioConverter>(new ResampleConverter(
    178              src_channels, src_frames, src_channels, dst_frames)));
    179      converters.push_back(std::unique_ptr<AudioConverter>(new UpmixConverter(
    180          src_channels, dst_frames, dst_channels, dst_frames)));
    181      sp.reset(new CompositionConverter(std::move(converters)));
    182    } else {
    183      sp.reset(new UpmixConverter(src_channels, src_frames, dst_channels,
    184                                  dst_frames));
    185    }
    186  } else if (src_frames != dst_frames) {
    187    sp.reset(new ResampleConverter(src_channels, src_frames, dst_channels,
    188                                   dst_frames));
    189  } else {
    190    sp.reset(
    191        new CopyConverter(src_channels, src_frames, dst_channels, dst_frames));
    192  }
    193 
    194  return sp;
    195 }
    196 
    197 // For CompositionConverter.
    198 AudioConverter::AudioConverter()
    199    : src_channels_(0), src_frames_(0), dst_channels_(0), dst_frames_(0) {}
    200 
    201 AudioConverter::AudioConverter(size_t src_channels,
    202                               size_t src_frames,
    203                               size_t dst_channels,
    204                               size_t dst_frames)
    205    : src_channels_(src_channels),
    206      src_frames_(src_frames),
    207      dst_channels_(dst_channels),
    208      dst_frames_(dst_frames) {
    209  RTC_CHECK(dst_channels == src_channels || dst_channels == 1 ||
    210            src_channels == 1);
    211 }
    212 
    213 void AudioConverter::CheckSizes(size_t src_size, size_t dst_capacity) const {
    214  RTC_CHECK_EQ(src_size, src_channels() * src_frames());
    215  RTC_CHECK_GE(dst_capacity, dst_channels() * dst_frames());
    216 }
    217 
    218 }  // namespace webrtc