blob: e1d5b3af29a52e582c23d194e24b0ed883d746bb [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
andrew@webrtc.org63a50982012-05-02 23:56:37 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_processing/audio_buffer.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
Yves Gerey988cc082018-10-23 12:03:01 +020013#include <string.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
Yves Gerey988cc082018-10-23 12:03:01 +020015#include <cstdint>
16
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "common_audio/channel_buffer.h"
18#include "common_audio/include/audio_util.h"
19#include "common_audio/resampler/push_sinc_resampler.h"
Yves Gerey988cc082018-10-23 12:03:01 +020020#include "modules/audio_processing/splitting_filter.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "rtc_base/checks.h"
andrew@webrtc.org755b04a2011-11-15 16:57:56 +000022
niklase@google.com470e71d2011-07-07 08:21:25 +000023namespace webrtc {
24namespace {
25
Per Åhgren81c0cf22019-08-21 15:02:37 +020026constexpr size_t kSamplesPer32kHzChannel = 320;
27constexpr size_t kSamplesPer48kHzChannel = 480;
28constexpr size_t kSamplesPer192kHzChannel = 1920;
29constexpr size_t kMaxSamplesPerChannel = kSamplesPer192kHzChannel;
Alejandro Luebs5a92aa82015-04-27 11:34:45 -070030
Per Åhgren81c0cf22019-08-21 15:02:37 +020031size_t NumBandsFromFramesPerChannel(size_t num_frames) {
32 if (num_frames == kSamplesPer32kHzChannel) {
33 return 2;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000034 }
Per Åhgren81c0cf22019-08-21 15:02:37 +020035 if (num_frames == kSamplesPer48kHzChannel) {
36 return 3;
37 }
38 return 1;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000039}
40
niklase@google.com470e71d2011-07-07 08:21:25 +000041} // namespace
42
Per Åhgren81c0cf22019-08-21 15:02:37 +020043AudioBuffer::AudioBuffer(size_t input_rate,
44 size_t input_num_channels,
45 size_t buffer_rate,
46 size_t buffer_num_channels,
47 size_t output_rate)
48 : input_num_frames_(
49 rtc::CheckedDivExact(static_cast<int>(input_rate), 100)),
50 input_num_channels_(input_num_channels),
51 buffer_num_frames_(
52 rtc::CheckedDivExact(static_cast<int>(buffer_rate), 100)),
53 buffer_num_channels_(buffer_num_channels),
54 output_num_frames_(
55 rtc::CheckedDivExact(static_cast<int>(output_rate), 100)),
56 num_channels_(buffer_num_channels),
57 num_bands_(NumBandsFromFramesPerChannel(buffer_num_frames_)),
58 num_split_frames_(rtc::CheckedDivExact(buffer_num_frames_, num_bands_)),
59 data_(new ChannelBuffer<float>(buffer_num_frames_, buffer_num_channels_)),
60 output_buffer_(
61 new ChannelBuffer<float>(output_num_frames_, num_channels_)) {
kwibergaf476c72016-11-28 15:21:39 -080062 RTC_DCHECK_GT(input_num_frames_, 0);
Per Åhgren81c0cf22019-08-21 15:02:37 +020063 RTC_DCHECK_GT(buffer_num_frames_, 0);
kwibergaf476c72016-11-28 15:21:39 -080064 RTC_DCHECK_GT(output_num_frames_, 0);
Per Åhgren81c0cf22019-08-21 15:02:37 +020065 RTC_DCHECK_GT(input_num_channels_, 0);
66 RTC_DCHECK_GT(buffer_num_channels_, 0);
67 RTC_DCHECK_LE(buffer_num_channels_, input_num_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +000068
Per Åhgren81c0cf22019-08-21 15:02:37 +020069 const bool input_resampling_needed = input_num_frames_ != buffer_num_frames_;
70 const bool output_resampling_needed =
71 output_num_frames_ != buffer_num_frames_;
72 if (input_resampling_needed) {
73 for (size_t i = 0; i < buffer_num_channels_; ++i) {
74 input_resamplers_.push_back(std::unique_ptr<PushSincResampler>(
75 new PushSincResampler(input_num_frames_, buffer_num_frames_)));
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000076 }
Per Åhgren81c0cf22019-08-21 15:02:37 +020077 }
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000078
Per Åhgren81c0cf22019-08-21 15:02:37 +020079 if (output_resampling_needed) {
80 for (size_t i = 0; i < buffer_num_channels_; ++i) {
81 output_resamplers_.push_back(std::unique_ptr<PushSincResampler>(
82 new PushSincResampler(buffer_num_frames_, output_num_frames_)));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000083 }
84 }
85
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000086 if (num_bands_ > 1) {
Per Åhgren81c0cf22019-08-21 15:02:37 +020087 split_data_.reset(new ChannelBuffer<float>(
88 buffer_num_frames_, buffer_num_channels_, num_bands_));
89 splitting_filter_.reset(new SplittingFilter(
90 buffer_num_channels_, num_bands_, buffer_num_frames_));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000091 }
92}
93
andrew@webrtc.org103657b2014-04-24 18:28:56 +000094AudioBuffer::~AudioBuffer() {}
95
Per Åhgren81c0cf22019-08-21 15:02:37 +020096void AudioBuffer::set_downmixing_to_specific_channel(size_t channel) {
97 downmix_by_averaging_ = false;
98 RTC_DCHECK_GT(input_num_channels_, channel);
99 channel_for_downmixing_ = std::min(channel, input_num_channels_ - 1);
100}
101
102void AudioBuffer::set_downmixing_by_averaging() {
103 downmix_by_averaging_ = true;
104}
105
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000106void AudioBuffer::CopyFrom(const float* const* data,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700107 const StreamConfig& stream_config) {
kwiberg9e2be5f2016-09-14 05:23:22 -0700108 RTC_DCHECK_EQ(stream_config.num_frames(), input_num_frames_);
Per Åhgren81c0cf22019-08-21 15:02:37 +0200109 RTC_DCHECK_EQ(stream_config.num_channels(), input_num_channels_);
110 RestoreNumChannels();
111 const bool downmix_needed = input_num_channels_ > 1 && num_channels_ == 1;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000112
Per Åhgren81c0cf22019-08-21 15:02:37 +0200113 const bool resampling_needed = input_num_frames_ != buffer_num_frames_;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000114
Per Åhgren81c0cf22019-08-21 15:02:37 +0200115 if (downmix_needed) {
116 RTC_DCHECK_GT(kMaxSamplesPerChannel, input_num_frames_);
117
118 std::array<float, kMaxSamplesPerChannel> downmix;
119 if (downmix_by_averaging_) {
120 const float kOneByNumChannels = 1.f / input_num_channels_;
121 for (size_t i = 0; i < input_num_frames_; ++i) {
122 float value = data[0][i];
123 for (size_t j = 1; j < input_num_channels_; ++j) {
124 value += data[j][i];
125 }
126 downmix[i] = value * kOneByNumChannels;
127 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000128 }
Per Åhgren81c0cf22019-08-21 15:02:37 +0200129 const float* downmixed_data =
130 downmix_by_averaging_ ? downmix.data() : data[channel_for_downmixing_];
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000131
Per Åhgren81c0cf22019-08-21 15:02:37 +0200132 if (resampling_needed) {
133 input_resamplers_[0]->Resample(downmixed_data, input_num_frames_,
134 data_->channels()[0], buffer_num_frames_);
135 }
136 const float* data_to_convert =
137 resampling_needed ? data_->channels()[0] : downmixed_data;
138 FloatToFloatS16(data_to_convert, buffer_num_frames_, data_->channels()[0]);
139 } else {
140 if (resampling_needed) {
141 for (size_t i = 0; i < num_channels_; ++i) {
142 input_resamplers_[i]->Resample(data[i], input_num_frames_,
143 data_->channels()[i],
144 buffer_num_frames_);
145 FloatToFloatS16(data_->channels()[i], buffer_num_frames_,
146 data_->channels()[i]);
147 }
148 } else {
149 for (size_t i = 0; i < num_channels_; ++i) {
150 FloatToFloatS16(data[i], buffer_num_frames_, data_->channels()[i]);
151 }
152 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000153 }
154}
155
Michael Graczyk86c6d332015-07-23 11:41:39 -0700156void AudioBuffer::CopyTo(const StreamConfig& stream_config,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000157 float* const* data) {
kwiberg9e2be5f2016-09-14 05:23:22 -0700158 RTC_DCHECK_EQ(stream_config.num_frames(), output_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000159
Per Åhgren81c0cf22019-08-21 15:02:37 +0200160 const bool resampling_needed = output_num_frames_ != buffer_num_frames_;
161 if (resampling_needed) {
Peter Kasting69558702016-01-12 16:26:35 -0800162 for (size_t i = 0; i < num_channels_; ++i) {
Per Åhgren81c0cf22019-08-21 15:02:37 +0200163 FloatS16ToFloat(data_->channels()[i], buffer_num_frames_,
164 data_->channels()[i]);
165 output_resamplers_[i]->Resample(data_->channels()[i], buffer_num_frames_,
166 data[i], output_num_frames_);
167 }
168 } else {
169 for (size_t i = 0; i < num_channels_; ++i) {
170 FloatS16ToFloat(data_->channels()[i], buffer_num_frames_, data[i]);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000171 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000172 }
aluebsb2328d12016-01-11 20:32:29 -0800173
Peter Kasting69558702016-01-12 16:26:35 -0800174 for (size_t i = num_channels_; i < stream_config.num_channels(); ++i) {
aluebsb2328d12016-01-11 20:32:29 -0800175 memcpy(data[i], data[0], output_num_frames_ * sizeof(**data));
176 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000177}
178
Per Åhgren81c0cf22019-08-21 15:02:37 +0200179void AudioBuffer::RestoreNumChannels() {
180 num_channels_ = buffer_num_channels_;
181 data_->set_num_channels(buffer_num_channels_);
Alejandro Luebsa181c9a2016-06-30 15:33:37 -0700182 if (split_data_.get()) {
Per Åhgren81c0cf22019-08-21 15:02:37 +0200183 split_data_->set_num_channels(buffer_num_channels_);
Alejandro Luebsa181c9a2016-06-30 15:33:37 -0700184 }
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000185}
186
Peter Kasting69558702016-01-12 16:26:35 -0800187void AudioBuffer::set_num_channels(size_t num_channels) {
Per Åhgren81c0cf22019-08-21 15:02:37 +0200188 RTC_DCHECK_GE(buffer_num_channels_, num_channels);
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000189 num_channels_ = num_channels;
Alejandro Luebsa181c9a2016-06-30 15:33:37 -0700190 data_->set_num_channels(num_channels);
191 if (split_data_.get()) {
192 split_data_->set_num_channels(num_channels);
193 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000194}
195
Alejandro Luebs05c76052015-05-20 14:39:39 -0700196// The resampler is only for supporting 48kHz to 16kHz in the reverse stream.
Per Åhgren81c0cf22019-08-21 15:02:37 +0200197void AudioBuffer::CopyFrom(const AudioFrame* frame) {
198 RTC_DCHECK_EQ(frame->num_channels_, input_num_channels_);
kwiberg9e2be5f2016-09-14 05:23:22 -0700199 RTC_DCHECK_EQ(frame->samples_per_channel_, input_num_frames_);
Per Åhgren81c0cf22019-08-21 15:02:37 +0200200 RestoreNumChannels();
niklase@google.com470e71d2011-07-07 08:21:25 +0000201
Per Åhgren81c0cf22019-08-21 15:02:37 +0200202 const bool resampling_required = input_num_frames_ != buffer_num_frames_;
Alejandro Luebs05c76052015-05-20 14:39:39 -0700203
Per Åhgren81c0cf22019-08-21 15:02:37 +0200204 const int16_t* interleaved = frame->data();
205 if (num_channels_ == 1) {
206 if (input_num_channels_ == 1) {
207 if (resampling_required) {
208 std::array<float, kMaxSamplesPerChannel> float_buffer;
209 S16ToFloatS16(interleaved, input_num_frames_, float_buffer.data());
210 input_resamplers_[0]->Resample(float_buffer.data(), input_num_frames_,
211 data_->channels()[0],
212 buffer_num_frames_);
213 } else {
214 S16ToFloatS16(interleaved, input_num_frames_, data_->channels()[0]);
215 }
216 } else {
217 std::array<float, kMaxSamplesPerChannel> float_buffer;
218 float* downmixed_data =
219 resampling_required ? float_buffer.data() : data_->channels()[0];
220 if (downmix_by_averaging_) {
221 for (size_t j = 0, k = 0; j < input_num_frames_; ++j) {
222 int32_t sum = 0;
223 for (size_t i = 0; i < input_num_channels_; ++i, ++k) {
224 sum += interleaved[k];
225 }
226 downmixed_data[j] = sum / static_cast<int16_t>(input_num_channels_);
227 }
228 } else {
229 for (size_t j = 0, k = channel_for_downmixing_; j < input_num_frames_;
230 ++j, k += input_num_channels_) {
231 downmixed_data[j] = interleaved[k];
232 }
233 }
234
235 if (resampling_required) {
236 input_resamplers_[0]->Resample(downmixed_data, input_num_frames_,
237 data_->channels()[0],
238 buffer_num_frames_);
239 }
240 }
241 } else {
242 auto deinterleave_channel = [](size_t channel, size_t num_channels,
243 size_t samples_per_channel, const int16_t* x,
244 float* y) {
245 for (size_t j = 0, k = channel; j < samples_per_channel;
246 ++j, k += num_channels) {
247 y[j] = x[k];
248 }
249 };
250
251 if (resampling_required) {
252 std::array<float, kMaxSamplesPerChannel> float_buffer;
253 for (size_t i = 0; i < num_channels_; ++i) {
254 deinterleave_channel(i, num_channels_, input_num_frames_, interleaved,
255 float_buffer.data());
256 input_resamplers_[i]->Resample(float_buffer.data(), input_num_frames_,
257 data_->channels()[i],
258 buffer_num_frames_);
259 }
260 } else {
261 for (size_t i = 0; i < num_channels_; ++i) {
262 deinterleave_channel(i, num_channels_, input_num_frames_, interleaved,
263 data_->channels()[i]);
264 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000265 }
266 }
267}
268
Per Åhgren81c0cf22019-08-21 15:02:37 +0200269void AudioBuffer::CopyTo(AudioFrame* frame) const {
kwiberg9e2be5f2016-09-14 05:23:22 -0700270 RTC_DCHECK(frame->num_channels_ == num_channels_ || num_channels_ == 1);
271 RTC_DCHECK_EQ(frame->samples_per_channel_, output_num_frames_);
ekmeyerson60d9b332015-08-14 10:35:55 -0700272
Per Åhgren81c0cf22019-08-21 15:02:37 +0200273 const bool resampling_required = buffer_num_frames_ != output_num_frames_;
ekmeyerson60d9b332015-08-14 10:35:55 -0700274
Per Åhgren81c0cf22019-08-21 15:02:37 +0200275 int16_t* interleaved = frame->mutable_data();
276 if (num_channels_ == 1) {
277 std::array<float, kMaxSamplesPerChannel> float_buffer;
278
279 if (resampling_required) {
280 output_resamplers_[0]->Resample(data_->channels()[0], buffer_num_frames_,
281 float_buffer.data(), output_num_frames_);
282 }
283 const float* deinterleaved =
284 resampling_required ? float_buffer.data() : data_->channels()[0];
285
286 if (frame->num_channels_ == 1) {
287 for (size_t j = 0; j < output_num_frames_; ++j) {
288 interleaved[j] = FloatS16ToS16(deinterleaved[j]);
289 }
290 } else {
291 for (size_t i = 0, k = 0; i < output_num_frames_; ++i) {
292 float tmp = FloatS16ToS16(deinterleaved[i]);
293 for (size_t j = 0; j < frame->num_channels_; ++j, ++k) {
294 interleaved[k] = tmp;
295 }
296 }
297 }
ekmeyerson60d9b332015-08-14 10:35:55 -0700298 } else {
Per Åhgren81c0cf22019-08-21 15:02:37 +0200299 auto interleave_channel = [](size_t channel, size_t num_channels,
300 size_t samples_per_channel, const float* x,
301 int16_t* y) {
302 for (size_t k = 0, j = channel; k < samples_per_channel;
303 ++k, j += num_channels) {
304 y[j] = FloatS16ToS16(x[k]);
305 }
306 };
307
308 if (resampling_required) {
309 for (size_t i = 0; i < num_channels_; ++i) {
310 std::array<float, kMaxSamplesPerChannel> float_buffer;
311 output_resamplers_[i]->Resample(data_->channels()[i],
312 buffer_num_frames_, float_buffer.data(),
313 output_num_frames_);
314 interleave_channel(i, frame->num_channels_, output_num_frames_,
315 float_buffer.data(), interleaved);
316 }
317 } else {
318 for (size_t i = 0; i < num_channels_; ++i) {
319 interleave_channel(i, frame->num_channels_, output_num_frames_,
320 data_->channels()[i], interleaved);
321 }
322 }
323
324 for (size_t i = num_channels_; i < frame->num_channels_; ++i) {
325 for (size_t j = 0, k = i, n = num_channels_; j < output_num_frames_;
326 ++j, k += frame->num_channels_, n += frame->num_channels_) {
327 interleaved[k] = interleaved[n];
328 }
329 }
ekmeyerson60d9b332015-08-14 10:35:55 -0700330 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000331}
332
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000333void AudioBuffer::SplitIntoFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000334 splitting_filter_->Analysis(data_.get(), split_data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000335}
336
337void AudioBuffer::MergeFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000338 splitting_filter_->Synthesis(split_data_.get(), data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000339}
340
Per Åhgren81c0cf22019-08-21 15:02:37 +0200341void AudioBuffer::ExportSplitChannelData(size_t channel,
Per Åhgren928146f2019-08-20 09:19:21 +0200342 int16_t* const* split_band_data) {
343 for (size_t k = 0; k < num_bands(); ++k) {
Per Åhgren81c0cf22019-08-21 15:02:37 +0200344 const float* band_data = split_bands(channel)[k];
345
Per Åhgren928146f2019-08-20 09:19:21 +0200346 RTC_DCHECK(split_band_data[k]);
347 RTC_DCHECK(band_data);
348 for (size_t i = 0; i < num_frames_per_band(); ++i) {
349 split_band_data[k][i] = FloatS16ToS16(band_data[i]);
350 }
351 }
352}
353
Per Åhgren81c0cf22019-08-21 15:02:37 +0200354void AudioBuffer::ImportSplitChannelData(
Per Åhgren928146f2019-08-20 09:19:21 +0200355 size_t channel,
356 const int16_t* const* split_band_data) {
357 for (size_t k = 0; k < num_bands(); ++k) {
Per Åhgren81c0cf22019-08-21 15:02:37 +0200358 float* band_data = split_bands(channel)[k];
Per Åhgren928146f2019-08-20 09:19:21 +0200359 RTC_DCHECK(split_band_data[k]);
360 RTC_DCHECK(band_data);
361 for (size_t i = 0; i < num_frames_per_band(); ++i) {
362 band_data[i] = split_band_data[k][i];
363 }
364 }
365}
366
niklase@google.com470e71d2011-07-07 08:21:25 +0000367} // namespace webrtc