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:
CopyConverter(size_t src_channels,size_t src_frames,size_t dst_channels,size_t dst_frames)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) {}
~CopyConverter()31   ~CopyConverter() override {};
32 
Convert(const float * const * src,size_t src_size,float * const * dst,size_t dst_capacity)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:
UpmixConverter(size_t src_channels,size_t src_frames,size_t dst_channels,size_t dst_frames)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) {}
~UpmixConverter()48   ~UpmixConverter() override {};
49 
Convert(const float * const * src,size_t src_size,float * const * dst,size_t dst_capacity)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:
DownmixConverter(size_t src_channels,size_t src_frames,size_t dst_channels,size_t dst_frames)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   }
~DownmixConverter()67   ~DownmixConverter() override {};
68 
Convert(const float * const * src,size_t src_size,float * const * dst,size_t dst_capacity)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:
ResampleConverter(size_t src_channels,size_t src_frames,size_t dst_channels,size_t dst_frames)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   }
~ResampleConverter()91   ~ResampleConverter() override {};
92 
Convert(const float * const * src,size_t src_size,float * const * dst,size_t dst_capacity)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:
CompositionConverter(ScopedVector<AudioConverter> converters)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   }
~CompositionConverter()116   ~CompositionConverter() override {};
117 
Convert(const float * const * src,size_t src_size,float * const * dst,size_t dst_capacity)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 
Create(size_t src_channels,size_t src_frames,size_t dst_channels,size_t dst_frames)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.
AudioConverter()180 AudioConverter::AudioConverter()
181     : src_channels_(0),
182       src_frames_(0),
183       dst_channels_(0),
184       dst_frames_(0) {}
185 
AudioConverter(size_t src_channels,size_t src_frames,size_t dst_channels,size_t dst_frames)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 
CheckSizes(size_t src_size,size_t dst_capacity) const196 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