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