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