blob: 5ac4f94d309bbca13688fb213c1361fce5b7bf88 [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;
28constexpr size_t kSamplesPer192kHzChannel = 1920;
29constexpr size_t kMaxSamplesPerChannel = kSamplesPer192kHzChannel;
Alejandro Luebs5a92aa82015-04-27 11:34:45 -070030
Per Åhgrend47941e2019-08-22 11:51:13 +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 Åhgrend47941e2019-08-22 11:51:13 +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 Åhgrend47941e2019-08-22 11:51:13 +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 size_t output_num_channels)
Per Åhgren2ca0b362019-08-26 11:21:16 +020049 : AudioBuffer(static_cast<int>(input_rate) / 100,
Per Åhgrend47941e2019-08-22 11:51:13 +020050 input_num_channels,
Per Åhgren2ca0b362019-08-26 11:21:16 +020051 static_cast<int>(buffer_rate) / 100,
Per Åhgrend47941e2019-08-22 11:51:13 +020052 buffer_num_channels,
Per Åhgren2ca0b362019-08-26 11:21:16 +020053 static_cast<int>(output_rate) / 100) {}
Per Åhgrend47941e2019-08-22 11:51:13 +020054
Steve Antonf254e9e2019-08-21 17:52:28 +000055AudioBuffer::AudioBuffer(size_t input_num_frames,
Per Åhgrend47941e2019-08-22 11:51:13 +020056 size_t input_num_channels,
57 size_t buffer_num_frames,
58 size_t buffer_num_channels,
Steve Antonf254e9e2019-08-21 17:52:28 +000059 size_t output_num_frames)
60 : input_num_frames_(input_num_frames),
Per Åhgrend47941e2019-08-22 11:51:13 +020061 input_num_channels_(input_num_channels),
62 buffer_num_frames_(buffer_num_frames),
63 buffer_num_channels_(buffer_num_channels),
Steve Antonf254e9e2019-08-21 17:52:28 +000064 output_num_frames_(output_num_frames),
Per Åhgrend47941e2019-08-22 11:51:13 +020065 output_num_channels_(0),
66 num_channels_(buffer_num_channels),
67 num_bands_(NumBandsFromFramesPerChannel(buffer_num_frames_)),
68 num_split_frames_(rtc::CheckedDivExact(buffer_num_frames_, num_bands_)),
69 data_(new ChannelBuffer<float>(buffer_num_frames_, buffer_num_channels_)),
70 output_buffer_(
71 new ChannelBuffer<float>(output_num_frames_, num_channels_)) {
kwibergaf476c72016-11-28 15:21:39 -080072 RTC_DCHECK_GT(input_num_frames_, 0);
Per Åhgrend47941e2019-08-22 11:51:13 +020073 RTC_DCHECK_GT(buffer_num_frames_, 0);
kwibergaf476c72016-11-28 15:21:39 -080074 RTC_DCHECK_GT(output_num_frames_, 0);
Per Åhgrend47941e2019-08-22 11:51:13 +020075 RTC_DCHECK_GT(input_num_channels_, 0);
76 RTC_DCHECK_GT(buffer_num_channels_, 0);
77 RTC_DCHECK_LE(buffer_num_channels_, input_num_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +000078
Per Åhgrend47941e2019-08-22 11:51:13 +020079 const bool input_resampling_needed = input_num_frames_ != buffer_num_frames_;
80 const bool output_resampling_needed =
81 output_num_frames_ != buffer_num_frames_;
82 if (input_resampling_needed) {
83 for (size_t i = 0; i < buffer_num_channels_; ++i) {
84 input_resamplers_.push_back(std::unique_ptr<PushSincResampler>(
85 new PushSincResampler(input_num_frames_, buffer_num_frames_)));
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000086 }
Per Åhgrend47941e2019-08-22 11:51:13 +020087 }
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000088
Per Åhgrend47941e2019-08-22 11:51:13 +020089 if (output_resampling_needed) {
90 for (size_t i = 0; i < buffer_num_channels_; ++i) {
91 output_resamplers_.push_back(std::unique_ptr<PushSincResampler>(
92 new PushSincResampler(buffer_num_frames_, output_num_frames_)));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000093 }
94 }
95
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000096 if (num_bands_ > 1) {
Per Åhgrend47941e2019-08-22 11:51:13 +020097 split_data_.reset(new ChannelBuffer<float>(
98 buffer_num_frames_, buffer_num_channels_, num_bands_));
99 splitting_filter_.reset(new SplittingFilter(
100 buffer_num_channels_, num_bands_, buffer_num_frames_));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000101 }
102}
103
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000104AudioBuffer::~AudioBuffer() {}
105
Per Åhgrend47941e2019-08-22 11:51:13 +0200106void AudioBuffer::set_downmixing_to_specific_channel(size_t channel) {
107 downmix_by_averaging_ = false;
108 RTC_DCHECK_GT(input_num_channels_, channel);
109 channel_for_downmixing_ = std::min(channel, input_num_channels_ - 1);
110}
111
112void AudioBuffer::set_downmixing_by_averaging() {
113 downmix_by_averaging_ = true;
114}
115
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000116void AudioBuffer::CopyFrom(const float* const* data,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700117 const StreamConfig& stream_config) {
kwiberg9e2be5f2016-09-14 05:23:22 -0700118 RTC_DCHECK_EQ(stream_config.num_frames(), input_num_frames_);
Per Åhgrend47941e2019-08-22 11:51:13 +0200119 RTC_DCHECK_EQ(stream_config.num_channels(), input_num_channels_);
120 RestoreNumChannels();
121 const bool downmix_needed = input_num_channels_ > 1 && num_channels_ == 1;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000122
Per Åhgrend47941e2019-08-22 11:51:13 +0200123 const bool resampling_needed = input_num_frames_ != buffer_num_frames_;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000124
Per Åhgrend47941e2019-08-22 11:51:13 +0200125 if (downmix_needed) {
126 RTC_DCHECK_GT(kMaxSamplesPerChannel, input_num_frames_);
127
128 std::array<float, kMaxSamplesPerChannel> downmix;
129 if (downmix_by_averaging_) {
130 const float kOneByNumChannels = 1.f / input_num_channels_;
131 for (size_t i = 0; i < input_num_frames_; ++i) {
132 float value = data[0][i];
133 for (size_t j = 1; j < input_num_channels_; ++j) {
134 value += data[j][i];
135 }
136 downmix[i] = value * kOneByNumChannels;
137 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000138 }
Per Åhgrend47941e2019-08-22 11:51:13 +0200139 const float* downmixed_data =
140 downmix_by_averaging_ ? downmix.data() : data[channel_for_downmixing_];
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000141
Per Åhgrend47941e2019-08-22 11:51:13 +0200142 if (resampling_needed) {
143 input_resamplers_[0]->Resample(downmixed_data, input_num_frames_,
144 data_->channels()[0], buffer_num_frames_);
145 }
146 const float* data_to_convert =
147 resampling_needed ? data_->channels()[0] : downmixed_data;
148 FloatToFloatS16(data_to_convert, buffer_num_frames_, data_->channels()[0]);
149 } else {
150 if (resampling_needed) {
151 for (size_t i = 0; i < num_channels_; ++i) {
152 input_resamplers_[i]->Resample(data[i], input_num_frames_,
153 data_->channels()[i],
154 buffer_num_frames_);
155 FloatToFloatS16(data_->channels()[i], buffer_num_frames_,
156 data_->channels()[i]);
157 }
158 } else {
159 for (size_t i = 0; i < num_channels_; ++i) {
160 FloatToFloatS16(data[i], buffer_num_frames_, data_->channels()[i]);
161 }
162 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000163 }
164}
165
Michael Graczyk86c6d332015-07-23 11:41:39 -0700166void AudioBuffer::CopyTo(const StreamConfig& stream_config,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000167 float* const* data) {
kwiberg9e2be5f2016-09-14 05:23:22 -0700168 RTC_DCHECK_EQ(stream_config.num_frames(), output_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000169
Per Åhgrend47941e2019-08-22 11:51:13 +0200170 const bool resampling_needed = output_num_frames_ != buffer_num_frames_;
171 if (resampling_needed) {
Peter Kasting69558702016-01-12 16:26:35 -0800172 for (size_t i = 0; i < num_channels_; ++i) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200173 FloatS16ToFloat(data_->channels()[i], buffer_num_frames_,
174 data_->channels()[i]);
175 output_resamplers_[i]->Resample(data_->channels()[i], buffer_num_frames_,
176 data[i], output_num_frames_);
177 }
178 } else {
179 for (size_t i = 0; i < num_channels_; ++i) {
180 FloatS16ToFloat(data_->channels()[i], buffer_num_frames_, data[i]);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000181 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000182 }
aluebsb2328d12016-01-11 20:32:29 -0800183
Peter Kasting69558702016-01-12 16:26:35 -0800184 for (size_t i = num_channels_; i < stream_config.num_channels(); ++i) {
aluebsb2328d12016-01-11 20:32:29 -0800185 memcpy(data[i], data[0], output_num_frames_ * sizeof(**data));
186 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000187}
188
Per Åhgrend47941e2019-08-22 11:51:13 +0200189void AudioBuffer::RestoreNumChannels() {
190 num_channels_ = buffer_num_channels_;
191 data_->set_num_channels(buffer_num_channels_);
Alejandro Luebsa181c9a2016-06-30 15:33:37 -0700192 if (split_data_.get()) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200193 split_data_->set_num_channels(buffer_num_channels_);
Alejandro Luebsa181c9a2016-06-30 15:33:37 -0700194 }
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000195}
196
Peter Kasting69558702016-01-12 16:26:35 -0800197void AudioBuffer::set_num_channels(size_t num_channels) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200198 RTC_DCHECK_GE(buffer_num_channels_, num_channels);
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000199 num_channels_ = num_channels;
Alejandro Luebsa181c9a2016-06-30 15:33:37 -0700200 data_->set_num_channels(num_channels);
201 if (split_data_.get()) {
202 split_data_->set_num_channels(num_channels);
203 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000204}
205
Alejandro Luebs05c76052015-05-20 14:39:39 -0700206// The resampler is only for supporting 48kHz to 16kHz in the reverse stream.
Per Åhgrend47941e2019-08-22 11:51:13 +0200207void AudioBuffer::CopyFrom(const AudioFrame* frame) {
208 RTC_DCHECK_EQ(frame->num_channels_, input_num_channels_);
kwiberg9e2be5f2016-09-14 05:23:22 -0700209 RTC_DCHECK_EQ(frame->samples_per_channel_, input_num_frames_);
Per Åhgrend47941e2019-08-22 11:51:13 +0200210 RestoreNumChannels();
niklase@google.com470e71d2011-07-07 08:21:25 +0000211
Per Åhgrend47941e2019-08-22 11:51:13 +0200212 const bool resampling_required = input_num_frames_ != buffer_num_frames_;
Per Åhgren81c0cf22019-08-21 15:02:37 +0200213
Per Åhgrend47941e2019-08-22 11:51:13 +0200214 const int16_t* interleaved = frame->data();
215 if (num_channels_ == 1) {
216 if (input_num_channels_ == 1) {
217 if (resampling_required) {
218 std::array<float, kMaxSamplesPerChannel> float_buffer;
219 S16ToFloatS16(interleaved, input_num_frames_, float_buffer.data());
220 input_resamplers_[0]->Resample(float_buffer.data(), input_num_frames_,
221 data_->channels()[0],
222 buffer_num_frames_);
223 } else {
224 S16ToFloatS16(interleaved, input_num_frames_, data_->channels()[0]);
225 }
226 } else {
227 std::array<float, kMaxSamplesPerChannel> float_buffer;
228 float* downmixed_data =
229 resampling_required ? float_buffer.data() : data_->channels()[0];
230 if (downmix_by_averaging_) {
231 for (size_t j = 0, k = 0; j < input_num_frames_; ++j) {
232 int32_t sum = 0;
233 for (size_t i = 0; i < input_num_channels_; ++i, ++k) {
234 sum += interleaved[k];
235 }
236 downmixed_data[j] = sum / static_cast<int16_t>(input_num_channels_);
237 }
238 } else {
239 for (size_t j = 0, k = channel_for_downmixing_; j < input_num_frames_;
240 ++j, k += input_num_channels_) {
241 downmixed_data[j] = interleaved[k];
242 }
243 }
244
245 if (resampling_required) {
246 input_resamplers_[0]->Resample(downmixed_data, input_num_frames_,
247 data_->channels()[0],
248 buffer_num_frames_);
249 }
250 }
251 } else {
252 auto deinterleave_channel = [](size_t channel, size_t num_channels,
253 size_t samples_per_channel, const int16_t* x,
254 float* y) {
255 for (size_t j = 0, k = channel; j < samples_per_channel;
256 ++j, k += num_channels) {
257 y[j] = x[k];
258 }
259 };
260
261 if (resampling_required) {
262 std::array<float, kMaxSamplesPerChannel> float_buffer;
263 for (size_t i = 0; i < num_channels_; ++i) {
264 deinterleave_channel(i, num_channels_, input_num_frames_, interleaved,
265 float_buffer.data());
266 input_resamplers_[i]->Resample(float_buffer.data(), input_num_frames_,
267 data_->channels()[i],
268 buffer_num_frames_);
269 }
270 } else {
271 for (size_t i = 0; i < num_channels_; ++i) {
272 deinterleave_channel(i, num_channels_, input_num_frames_, interleaved,
273 data_->channels()[i]);
274 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000275 }
276 }
277}
278
Per Åhgrend47941e2019-08-22 11:51:13 +0200279void AudioBuffer::CopyTo(AudioFrame* frame) const {
kwiberg9e2be5f2016-09-14 05:23:22 -0700280 RTC_DCHECK(frame->num_channels_ == num_channels_ || num_channels_ == 1);
281 RTC_DCHECK_EQ(frame->samples_per_channel_, output_num_frames_);
ekmeyerson60d9b332015-08-14 10:35:55 -0700282
Per Åhgrend47941e2019-08-22 11:51:13 +0200283 const bool resampling_required = buffer_num_frames_ != output_num_frames_;
Per Åhgren81c0cf22019-08-21 15:02:37 +0200284
Per Åhgrend47941e2019-08-22 11:51:13 +0200285 int16_t* interleaved = frame->mutable_data();
286 if (num_channels_ == 1) {
287 std::array<float, kMaxSamplesPerChannel> float_buffer;
288
289 if (resampling_required) {
290 output_resamplers_[0]->Resample(data_->channels()[0], buffer_num_frames_,
291 float_buffer.data(), output_num_frames_);
292 }
293 const float* deinterleaved =
294 resampling_required ? float_buffer.data() : data_->channels()[0];
295
296 if (frame->num_channels_ == 1) {
297 for (size_t j = 0; j < output_num_frames_; ++j) {
298 interleaved[j] = FloatS16ToS16(deinterleaved[j]);
299 }
300 } else {
301 for (size_t i = 0, k = 0; i < output_num_frames_; ++i) {
302 float tmp = FloatS16ToS16(deinterleaved[i]);
303 for (size_t j = 0; j < frame->num_channels_; ++j, ++k) {
304 interleaved[k] = tmp;
305 }
306 }
307 }
ekmeyerson60d9b332015-08-14 10:35:55 -0700308 } else {
Per Åhgrend47941e2019-08-22 11:51:13 +0200309 auto interleave_channel = [](size_t channel, size_t num_channels,
310 size_t samples_per_channel, const float* x,
311 int16_t* y) {
312 for (size_t k = 0, j = channel; k < samples_per_channel;
313 ++k, j += num_channels) {
314 y[j] = FloatS16ToS16(x[k]);
315 }
316 };
317
318 if (resampling_required) {
319 for (size_t i = 0; i < num_channels_; ++i) {
320 std::array<float, kMaxSamplesPerChannel> float_buffer;
321 output_resamplers_[i]->Resample(data_->channels()[i],
322 buffer_num_frames_, float_buffer.data(),
323 output_num_frames_);
324 interleave_channel(i, frame->num_channels_, output_num_frames_,
325 float_buffer.data(), interleaved);
326 }
327 } else {
328 for (size_t i = 0; i < num_channels_; ++i) {
329 interleave_channel(i, frame->num_channels_, output_num_frames_,
330 data_->channels()[i], interleaved);
331 }
332 }
333
334 for (size_t i = num_channels_; i < frame->num_channels_; ++i) {
335 for (size_t j = 0, k = i, n = num_channels_; j < output_num_frames_;
336 ++j, k += frame->num_channels_, n += frame->num_channels_) {
337 interleaved[k] = interleaved[n];
338 }
339 }
ekmeyerson60d9b332015-08-14 10:35:55 -0700340 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000341}
342
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000343void AudioBuffer::SplitIntoFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000344 splitting_filter_->Analysis(data_.get(), split_data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000345}
346
347void AudioBuffer::MergeFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000348 splitting_filter_->Synthesis(split_data_.get(), data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000349}
350
Per Åhgrend47941e2019-08-22 11:51:13 +0200351void AudioBuffer::ExportSplitChannelData(size_t channel,
Per Åhgren928146f2019-08-20 09:19:21 +0200352 int16_t* const* split_band_data) {
353 for (size_t k = 0; k < num_bands(); ++k) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200354 const float* band_data = split_bands(channel)[k];
355
Per Åhgren928146f2019-08-20 09:19:21 +0200356 RTC_DCHECK(split_band_data[k]);
357 RTC_DCHECK(band_data);
358 for (size_t i = 0; i < num_frames_per_band(); ++i) {
359 split_band_data[k][i] = FloatS16ToS16(band_data[i]);
360 }
361 }
362}
363
Per Åhgrend47941e2019-08-22 11:51:13 +0200364void AudioBuffer::ImportSplitChannelData(
Per Åhgren928146f2019-08-20 09:19:21 +0200365 size_t channel,
366 const int16_t* const* split_band_data) {
367 for (size_t k = 0; k < num_bands(); ++k) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200368 float* band_data = split_bands(channel)[k];
Per Åhgren928146f2019-08-20 09:19:21 +0200369 RTC_DCHECK(split_band_data[k]);
370 RTC_DCHECK(band_data);
371 for (size_t i = 0; i < num_frames_per_band(); ++i) {
372 band_data[i] = split_band_data[k][i];
373 }
374 }
375}
376
niklase@google.com470e71d2011-07-07 08:21:25 +0000377} // namespace webrtc