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