blob: 4b0ca20d820237a7ea65f4394ec10e36d8678472 [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 Åhgrend47941e2019-08-22 11:51:13 +020026constexpr size_t kSamplesPer32kHzChannel = 320;
27constexpr size_t kSamplesPer48kHzChannel = 480;
Per Åhgren3e8bf282019-08-29 23:38:40 +020028constexpr size_t kMaxSamplesPerChannel = AudioBuffer::kMaxSampleRate / 100;
Alejandro Luebs5a92aa82015-04-27 11:34:45 -070029
Per Åhgrend47941e2019-08-22 11:51:13 +020030size_t NumBandsFromFramesPerChannel(size_t num_frames) {
31 if (num_frames == kSamplesPer32kHzChannel) {
32 return 2;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000033 }
Per Åhgrend47941e2019-08-22 11:51:13 +020034 if (num_frames == kSamplesPer48kHzChannel) {
35 return 3;
36 }
37 return 1;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000038}
39
niklase@google.com470e71d2011-07-07 08:21:25 +000040} // namespace
41
Per Åhgrend47941e2019-08-22 11:51:13 +020042AudioBuffer::AudioBuffer(size_t input_rate,
43 size_t input_num_channels,
44 size_t buffer_rate,
45 size_t buffer_num_channels,
46 size_t output_rate,
47 size_t output_num_channels)
Per Åhgren2ca0b362019-08-26 11:21:16 +020048 : AudioBuffer(static_cast<int>(input_rate) / 100,
Per Åhgrend47941e2019-08-22 11:51:13 +020049 input_num_channels,
Per Åhgren2ca0b362019-08-26 11:21:16 +020050 static_cast<int>(buffer_rate) / 100,
Per Åhgrend47941e2019-08-22 11:51:13 +020051 buffer_num_channels,
Per Åhgren2ca0b362019-08-26 11:21:16 +020052 static_cast<int>(output_rate) / 100) {}
Per Åhgrend47941e2019-08-22 11:51:13 +020053
Steve Antonf254e9e2019-08-21 17:52:28 +000054AudioBuffer::AudioBuffer(size_t input_num_frames,
Per Åhgrend47941e2019-08-22 11:51:13 +020055 size_t input_num_channels,
56 size_t buffer_num_frames,
57 size_t buffer_num_channels,
Steve Antonf254e9e2019-08-21 17:52:28 +000058 size_t output_num_frames)
59 : input_num_frames_(input_num_frames),
Per Åhgrend47941e2019-08-22 11:51:13 +020060 input_num_channels_(input_num_channels),
61 buffer_num_frames_(buffer_num_frames),
62 buffer_num_channels_(buffer_num_channels),
Steve Antonf254e9e2019-08-21 17:52:28 +000063 output_num_frames_(output_num_frames),
Per Åhgrend47941e2019-08-22 11:51:13 +020064 output_num_channels_(0),
65 num_channels_(buffer_num_channels),
66 num_bands_(NumBandsFromFramesPerChannel(buffer_num_frames_)),
67 num_split_frames_(rtc::CheckedDivExact(buffer_num_frames_, num_bands_)),
68 data_(new ChannelBuffer<float>(buffer_num_frames_, buffer_num_channels_)),
69 output_buffer_(
70 new ChannelBuffer<float>(output_num_frames_, num_channels_)) {
kwibergaf476c72016-11-28 15:21:39 -080071 RTC_DCHECK_GT(input_num_frames_, 0);
Per Åhgrend47941e2019-08-22 11:51:13 +020072 RTC_DCHECK_GT(buffer_num_frames_, 0);
kwibergaf476c72016-11-28 15:21:39 -080073 RTC_DCHECK_GT(output_num_frames_, 0);
Per Åhgrend47941e2019-08-22 11:51:13 +020074 RTC_DCHECK_GT(input_num_channels_, 0);
75 RTC_DCHECK_GT(buffer_num_channels_, 0);
76 RTC_DCHECK_LE(buffer_num_channels_, input_num_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +000077
Per Åhgrend47941e2019-08-22 11:51:13 +020078 const bool input_resampling_needed = input_num_frames_ != buffer_num_frames_;
79 const bool output_resampling_needed =
80 output_num_frames_ != buffer_num_frames_;
81 if (input_resampling_needed) {
82 for (size_t i = 0; i < buffer_num_channels_; ++i) {
83 input_resamplers_.push_back(std::unique_ptr<PushSincResampler>(
84 new PushSincResampler(input_num_frames_, buffer_num_frames_)));
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000085 }
Per Åhgrend47941e2019-08-22 11:51:13 +020086 }
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000087
Per Åhgrend47941e2019-08-22 11:51:13 +020088 if (output_resampling_needed) {
89 for (size_t i = 0; i < buffer_num_channels_; ++i) {
90 output_resamplers_.push_back(std::unique_ptr<PushSincResampler>(
91 new PushSincResampler(buffer_num_frames_, output_num_frames_)));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000092 }
93 }
94
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000095 if (num_bands_ > 1) {
Per Åhgrend47941e2019-08-22 11:51:13 +020096 split_data_.reset(new ChannelBuffer<float>(
97 buffer_num_frames_, buffer_num_channels_, num_bands_));
98 splitting_filter_.reset(new SplittingFilter(
99 buffer_num_channels_, num_bands_, buffer_num_frames_));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000100 }
101}
102
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000103AudioBuffer::~AudioBuffer() {}
104
Per Åhgrend47941e2019-08-22 11:51:13 +0200105void AudioBuffer::set_downmixing_to_specific_channel(size_t channel) {
106 downmix_by_averaging_ = false;
107 RTC_DCHECK_GT(input_num_channels_, channel);
108 channel_for_downmixing_ = std::min(channel, input_num_channels_ - 1);
109}
110
111void AudioBuffer::set_downmixing_by_averaging() {
112 downmix_by_averaging_ = true;
113}
114
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000115void AudioBuffer::CopyFrom(const float* const* data,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700116 const StreamConfig& stream_config) {
kwiberg9e2be5f2016-09-14 05:23:22 -0700117 RTC_DCHECK_EQ(stream_config.num_frames(), input_num_frames_);
Per Åhgrend47941e2019-08-22 11:51:13 +0200118 RTC_DCHECK_EQ(stream_config.num_channels(), input_num_channels_);
119 RestoreNumChannels();
120 const bool downmix_needed = input_num_channels_ > 1 && num_channels_ == 1;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000121
Per Åhgrend47941e2019-08-22 11:51:13 +0200122 const bool resampling_needed = input_num_frames_ != buffer_num_frames_;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000123
Per Åhgrend47941e2019-08-22 11:51:13 +0200124 if (downmix_needed) {
Per Åhgren3e8bf282019-08-29 23:38:40 +0200125 RTC_DCHECK_GE(kMaxSamplesPerChannel, input_num_frames_);
Per Åhgrend47941e2019-08-22 11:51:13 +0200126
127 std::array<float, kMaxSamplesPerChannel> downmix;
128 if (downmix_by_averaging_) {
129 const float kOneByNumChannels = 1.f / input_num_channels_;
130 for (size_t i = 0; i < input_num_frames_; ++i) {
131 float value = data[0][i];
132 for (size_t j = 1; j < input_num_channels_; ++j) {
133 value += data[j][i];
134 }
135 downmix[i] = value * kOneByNumChannels;
136 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000137 }
Per Åhgrend47941e2019-08-22 11:51:13 +0200138 const float* downmixed_data =
139 downmix_by_averaging_ ? downmix.data() : data[channel_for_downmixing_];
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000140
Per Åhgrend47941e2019-08-22 11:51:13 +0200141 if (resampling_needed) {
142 input_resamplers_[0]->Resample(downmixed_data, input_num_frames_,
143 data_->channels()[0], buffer_num_frames_);
144 }
145 const float* data_to_convert =
146 resampling_needed ? data_->channels()[0] : downmixed_data;
147 FloatToFloatS16(data_to_convert, buffer_num_frames_, data_->channels()[0]);
148 } else {
149 if (resampling_needed) {
150 for (size_t i = 0; i < num_channels_; ++i) {
151 input_resamplers_[i]->Resample(data[i], input_num_frames_,
152 data_->channels()[i],
153 buffer_num_frames_);
154 FloatToFloatS16(data_->channels()[i], buffer_num_frames_,
155 data_->channels()[i]);
156 }
157 } else {
158 for (size_t i = 0; i < num_channels_; ++i) {
159 FloatToFloatS16(data[i], buffer_num_frames_, data_->channels()[i]);
160 }
161 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000162 }
163}
164
Michael Graczyk86c6d332015-07-23 11:41:39 -0700165void AudioBuffer::CopyTo(const StreamConfig& stream_config,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000166 float* const* data) {
kwiberg9e2be5f2016-09-14 05:23:22 -0700167 RTC_DCHECK_EQ(stream_config.num_frames(), output_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000168
Per Åhgrend47941e2019-08-22 11:51:13 +0200169 const bool resampling_needed = output_num_frames_ != buffer_num_frames_;
170 if (resampling_needed) {
Peter Kasting69558702016-01-12 16:26:35 -0800171 for (size_t i = 0; i < num_channels_; ++i) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200172 FloatS16ToFloat(data_->channels()[i], buffer_num_frames_,
173 data_->channels()[i]);
174 output_resamplers_[i]->Resample(data_->channels()[i], buffer_num_frames_,
175 data[i], output_num_frames_);
176 }
177 } else {
178 for (size_t i = 0; i < num_channels_; ++i) {
179 FloatS16ToFloat(data_->channels()[i], buffer_num_frames_, data[i]);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000180 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000181 }
aluebsb2328d12016-01-11 20:32:29 -0800182
Peter Kasting69558702016-01-12 16:26:35 -0800183 for (size_t i = num_channels_; i < stream_config.num_channels(); ++i) {
aluebsb2328d12016-01-11 20:32:29 -0800184 memcpy(data[i], data[0], output_num_frames_ * sizeof(**data));
185 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000186}
187
Per Åhgrend47941e2019-08-22 11:51:13 +0200188void AudioBuffer::RestoreNumChannels() {
189 num_channels_ = buffer_num_channels_;
190 data_->set_num_channels(buffer_num_channels_);
Alejandro Luebsa181c9a2016-06-30 15:33:37 -0700191 if (split_data_.get()) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200192 split_data_->set_num_channels(buffer_num_channels_);
Alejandro Luebsa181c9a2016-06-30 15:33:37 -0700193 }
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000194}
195
Peter Kasting69558702016-01-12 16:26:35 -0800196void AudioBuffer::set_num_channels(size_t num_channels) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200197 RTC_DCHECK_GE(buffer_num_channels_, num_channels);
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000198 num_channels_ = num_channels;
Alejandro Luebsa181c9a2016-06-30 15:33:37 -0700199 data_->set_num_channels(num_channels);
200 if (split_data_.get()) {
201 split_data_->set_num_channels(num_channels);
202 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000203}
204
Alejandro Luebs05c76052015-05-20 14:39:39 -0700205// The resampler is only for supporting 48kHz to 16kHz in the reverse stream.
Per Åhgrend47941e2019-08-22 11:51:13 +0200206void AudioBuffer::CopyFrom(const AudioFrame* frame) {
207 RTC_DCHECK_EQ(frame->num_channels_, input_num_channels_);
kwiberg9e2be5f2016-09-14 05:23:22 -0700208 RTC_DCHECK_EQ(frame->samples_per_channel_, input_num_frames_);
Per Åhgrend47941e2019-08-22 11:51:13 +0200209 RestoreNumChannels();
niklase@google.com470e71d2011-07-07 08:21:25 +0000210
Per Åhgrend47941e2019-08-22 11:51:13 +0200211 const bool resampling_required = input_num_frames_ != buffer_num_frames_;
Per Åhgren81c0cf22019-08-21 15:02:37 +0200212
Per Åhgrend47941e2019-08-22 11:51:13 +0200213 const int16_t* interleaved = frame->data();
214 if (num_channels_ == 1) {
215 if (input_num_channels_ == 1) {
216 if (resampling_required) {
217 std::array<float, kMaxSamplesPerChannel> float_buffer;
218 S16ToFloatS16(interleaved, input_num_frames_, float_buffer.data());
219 input_resamplers_[0]->Resample(float_buffer.data(), input_num_frames_,
220 data_->channels()[0],
221 buffer_num_frames_);
222 } else {
223 S16ToFloatS16(interleaved, input_num_frames_, data_->channels()[0]);
224 }
225 } else {
226 std::array<float, kMaxSamplesPerChannel> float_buffer;
227 float* downmixed_data =
228 resampling_required ? float_buffer.data() : data_->channels()[0];
229 if (downmix_by_averaging_) {
230 for (size_t j = 0, k = 0; j < input_num_frames_; ++j) {
231 int32_t sum = 0;
232 for (size_t i = 0; i < input_num_channels_; ++i, ++k) {
233 sum += interleaved[k];
234 }
235 downmixed_data[j] = sum / static_cast<int16_t>(input_num_channels_);
236 }
237 } else {
238 for (size_t j = 0, k = channel_for_downmixing_; j < input_num_frames_;
239 ++j, k += input_num_channels_) {
240 downmixed_data[j] = interleaved[k];
241 }
242 }
243
244 if (resampling_required) {
245 input_resamplers_[0]->Resample(downmixed_data, input_num_frames_,
246 data_->channels()[0],
247 buffer_num_frames_);
248 }
249 }
250 } else {
251 auto deinterleave_channel = [](size_t channel, size_t num_channels,
252 size_t samples_per_channel, const int16_t* x,
253 float* y) {
254 for (size_t j = 0, k = channel; j < samples_per_channel;
255 ++j, k += num_channels) {
256 y[j] = x[k];
257 }
258 };
259
260 if (resampling_required) {
261 std::array<float, kMaxSamplesPerChannel> float_buffer;
262 for (size_t i = 0; i < num_channels_; ++i) {
263 deinterleave_channel(i, num_channels_, input_num_frames_, interleaved,
264 float_buffer.data());
265 input_resamplers_[i]->Resample(float_buffer.data(), input_num_frames_,
266 data_->channels()[i],
267 buffer_num_frames_);
268 }
269 } else {
270 for (size_t i = 0; i < num_channels_; ++i) {
271 deinterleave_channel(i, num_channels_, input_num_frames_, interleaved,
272 data_->channels()[i]);
273 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000274 }
275 }
276}
277
Per Åhgrend47941e2019-08-22 11:51:13 +0200278void AudioBuffer::CopyTo(AudioFrame* frame) const {
kwiberg9e2be5f2016-09-14 05:23:22 -0700279 RTC_DCHECK(frame->num_channels_ == num_channels_ || num_channels_ == 1);
280 RTC_DCHECK_EQ(frame->samples_per_channel_, output_num_frames_);
ekmeyerson60d9b332015-08-14 10:35:55 -0700281
Per Åhgrend47941e2019-08-22 11:51:13 +0200282 const bool resampling_required = buffer_num_frames_ != output_num_frames_;
Per Åhgren81c0cf22019-08-21 15:02:37 +0200283
Per Åhgrend47941e2019-08-22 11:51:13 +0200284 int16_t* interleaved = frame->mutable_data();
285 if (num_channels_ == 1) {
286 std::array<float, kMaxSamplesPerChannel> float_buffer;
287
288 if (resampling_required) {
289 output_resamplers_[0]->Resample(data_->channels()[0], buffer_num_frames_,
290 float_buffer.data(), output_num_frames_);
291 }
292 const float* deinterleaved =
293 resampling_required ? float_buffer.data() : data_->channels()[0];
294
295 if (frame->num_channels_ == 1) {
296 for (size_t j = 0; j < output_num_frames_; ++j) {
297 interleaved[j] = FloatS16ToS16(deinterleaved[j]);
298 }
299 } else {
300 for (size_t i = 0, k = 0; i < output_num_frames_; ++i) {
301 float tmp = FloatS16ToS16(deinterleaved[i]);
302 for (size_t j = 0; j < frame->num_channels_; ++j, ++k) {
303 interleaved[k] = tmp;
304 }
305 }
306 }
ekmeyerson60d9b332015-08-14 10:35:55 -0700307 } else {
Per Åhgrend47941e2019-08-22 11:51:13 +0200308 auto interleave_channel = [](size_t channel, size_t num_channels,
309 size_t samples_per_channel, const float* x,
310 int16_t* y) {
311 for (size_t k = 0, j = channel; k < samples_per_channel;
312 ++k, j += num_channels) {
313 y[j] = FloatS16ToS16(x[k]);
314 }
315 };
316
317 if (resampling_required) {
318 for (size_t i = 0; i < num_channels_; ++i) {
319 std::array<float, kMaxSamplesPerChannel> float_buffer;
320 output_resamplers_[i]->Resample(data_->channels()[i],
321 buffer_num_frames_, float_buffer.data(),
322 output_num_frames_);
323 interleave_channel(i, frame->num_channels_, output_num_frames_,
324 float_buffer.data(), interleaved);
325 }
326 } else {
327 for (size_t i = 0; i < num_channels_; ++i) {
328 interleave_channel(i, frame->num_channels_, output_num_frames_,
329 data_->channels()[i], interleaved);
330 }
331 }
332
333 for (size_t i = num_channels_; i < frame->num_channels_; ++i) {
334 for (size_t j = 0, k = i, n = num_channels_; j < output_num_frames_;
335 ++j, k += frame->num_channels_, n += frame->num_channels_) {
336 interleaved[k] = interleaved[n];
337 }
338 }
ekmeyerson60d9b332015-08-14 10:35:55 -0700339 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000340}
341
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000342void AudioBuffer::SplitIntoFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000343 splitting_filter_->Analysis(data_.get(), split_data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000344}
345
346void AudioBuffer::MergeFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000347 splitting_filter_->Synthesis(split_data_.get(), data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000348}
349
Per Åhgrend47941e2019-08-22 11:51:13 +0200350void AudioBuffer::ExportSplitChannelData(size_t channel,
Per Åhgren928146f2019-08-20 09:19:21 +0200351 int16_t* const* split_band_data) {
352 for (size_t k = 0; k < num_bands(); ++k) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200353 const float* band_data = split_bands(channel)[k];
354
Per Åhgren928146f2019-08-20 09:19:21 +0200355 RTC_DCHECK(split_band_data[k]);
356 RTC_DCHECK(band_data);
357 for (size_t i = 0; i < num_frames_per_band(); ++i) {
358 split_band_data[k][i] = FloatS16ToS16(band_data[i]);
359 }
360 }
361}
362
Per Åhgrend47941e2019-08-22 11:51:13 +0200363void AudioBuffer::ImportSplitChannelData(
Per Åhgren928146f2019-08-20 09:19:21 +0200364 size_t channel,
365 const int16_t* const* split_band_data) {
366 for (size_t k = 0; k < num_bands(); ++k) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200367 float* band_data = split_bands(channel)[k];
Per Åhgren928146f2019-08-20 09:19:21 +0200368 RTC_DCHECK(split_band_data[k]);
369 RTC_DCHECK(band_data);
370 for (size_t i = 0; i < num_frames_per_band(); ++i) {
371 band_data[i] = split_band_data[k][i];
372 }
373 }
374}
375
niklase@google.com470e71d2011-07-07 08:21:25 +0000376} // namespace webrtc