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