blob: ff6636df8790829c1b9ec0fee7a52f2bda0a4677 [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_)),
Gustaf Ullberg422b9e02019-10-09 13:02:14 +020068 data_(
69 new ChannelBuffer<float>(buffer_num_frames_, buffer_num_channels_)) {
kwibergaf476c72016-11-28 15:21:39 -080070 RTC_DCHECK_GT(input_num_frames_, 0);
Per Åhgrend47941e2019-08-22 11:51:13 +020071 RTC_DCHECK_GT(buffer_num_frames_, 0);
kwibergaf476c72016-11-28 15:21:39 -080072 RTC_DCHECK_GT(output_num_frames_, 0);
Per Åhgrend47941e2019-08-22 11:51:13 +020073 RTC_DCHECK_GT(input_num_channels_, 0);
74 RTC_DCHECK_GT(buffer_num_channels_, 0);
75 RTC_DCHECK_LE(buffer_num_channels_, input_num_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +000076
Per Åhgrend47941e2019-08-22 11:51:13 +020077 const bool input_resampling_needed = input_num_frames_ != buffer_num_frames_;
78 const bool output_resampling_needed =
79 output_num_frames_ != buffer_num_frames_;
80 if (input_resampling_needed) {
81 for (size_t i = 0; i < buffer_num_channels_; ++i) {
82 input_resamplers_.push_back(std::unique_ptr<PushSincResampler>(
83 new PushSincResampler(input_num_frames_, buffer_num_frames_)));
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000084 }
Per Åhgrend47941e2019-08-22 11:51:13 +020085 }
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000086
Per Åhgrend47941e2019-08-22 11:51:13 +020087 if (output_resampling_needed) {
88 for (size_t i = 0; i < buffer_num_channels_; ++i) {
89 output_resamplers_.push_back(std::unique_ptr<PushSincResampler>(
90 new PushSincResampler(buffer_num_frames_, output_num_frames_)));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000091 }
92 }
93
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000094 if (num_bands_ > 1) {
Per Åhgrend47941e2019-08-22 11:51:13 +020095 split_data_.reset(new ChannelBuffer<float>(
96 buffer_num_frames_, buffer_num_channels_, num_bands_));
97 splitting_filter_.reset(new SplittingFilter(
98 buffer_num_channels_, num_bands_, buffer_num_frames_));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000099 }
100}
101
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000102AudioBuffer::~AudioBuffer() {}
103
Per Åhgrend47941e2019-08-22 11:51:13 +0200104void AudioBuffer::set_downmixing_to_specific_channel(size_t channel) {
105 downmix_by_averaging_ = false;
106 RTC_DCHECK_GT(input_num_channels_, channel);
107 channel_for_downmixing_ = std::min(channel, input_num_channels_ - 1);
108}
109
110void AudioBuffer::set_downmixing_by_averaging() {
111 downmix_by_averaging_ = true;
112}
113
Per Åhgren645f24c2020-03-16 12:06:02 +0100114void AudioBuffer::CopyFrom(const float* const* stacked_data,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700115 const StreamConfig& stream_config) {
kwiberg9e2be5f2016-09-14 05:23:22 -0700116 RTC_DCHECK_EQ(stream_config.num_frames(), input_num_frames_);
Per Åhgrend47941e2019-08-22 11:51:13 +0200117 RTC_DCHECK_EQ(stream_config.num_channels(), input_num_channels_);
118 RestoreNumChannels();
119 const bool downmix_needed = input_num_channels_ > 1 && num_channels_ == 1;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000120
Per Åhgrend47941e2019-08-22 11:51:13 +0200121 const bool resampling_needed = input_num_frames_ != buffer_num_frames_;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000122
Per Åhgrend47941e2019-08-22 11:51:13 +0200123 if (downmix_needed) {
Per Åhgren3e8bf282019-08-29 23:38:40 +0200124 RTC_DCHECK_GE(kMaxSamplesPerChannel, input_num_frames_);
Per Åhgrend47941e2019-08-22 11:51:13 +0200125
126 std::array<float, kMaxSamplesPerChannel> downmix;
127 if (downmix_by_averaging_) {
128 const float kOneByNumChannels = 1.f / input_num_channels_;
129 for (size_t i = 0; i < input_num_frames_; ++i) {
Per Åhgren645f24c2020-03-16 12:06:02 +0100130 float value = stacked_data[0][i];
Per Åhgrend47941e2019-08-22 11:51:13 +0200131 for (size_t j = 1; j < input_num_channels_; ++j) {
Per Åhgren645f24c2020-03-16 12:06:02 +0100132 value += stacked_data[j][i];
Per Åhgrend47941e2019-08-22 11:51:13 +0200133 }
134 downmix[i] = value * kOneByNumChannels;
135 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000136 }
Per Åhgren645f24c2020-03-16 12:06:02 +0100137 const float* downmixed_data = downmix_by_averaging_
138 ? downmix.data()
139 : stacked_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) {
Per Åhgren645f24c2020-03-16 12:06:02 +0100151 input_resamplers_[i]->Resample(stacked_data[i], input_num_frames_,
Per Åhgrend47941e2019-08-22 11:51:13 +0200152 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) {
Per Åhgren645f24c2020-03-16 12:06:02 +0100159 FloatToFloatS16(stacked_data[i], buffer_num_frames_,
160 data_->channels()[i]);
Per Åhgrend47941e2019-08-22 11:51:13 +0200161 }
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,
Per Åhgren645f24c2020-03-16 12:06:02 +0100167 float* const* stacked_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_,
Per Åhgren645f24c2020-03-16 12:06:02 +0100176 stacked_data[i], output_num_frames_);
Per Åhgrend47941e2019-08-22 11:51:13 +0200177 }
178 } else {
179 for (size_t i = 0; i < num_channels_; ++i) {
Per Åhgren645f24c2020-03-16 12:06:02 +0100180 FloatS16ToFloat(data_->channels()[i], buffer_num_frames_,
181 stacked_data[i]);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000182 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000183 }
aluebsb2328d12016-01-11 20:32:29 -0800184
Peter Kasting69558702016-01-12 16:26:35 -0800185 for (size_t i = num_channels_; i < stream_config.num_channels(); ++i) {
Per Åhgren645f24c2020-03-16 12:06:02 +0100186 memcpy(stacked_data[i], stacked_data[0],
187 output_num_frames_ * sizeof(**stacked_data));
aluebsb2328d12016-01-11 20:32:29 -0800188 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000189}
190
Gustaf Ullberg422b9e02019-10-09 13:02:14 +0200191void AudioBuffer::CopyTo(AudioBuffer* buffer) const {
192 RTC_DCHECK_EQ(buffer->num_frames(), output_num_frames_);
193
194 const bool resampling_needed = output_num_frames_ != buffer_num_frames_;
195 if (resampling_needed) {
196 for (size_t i = 0; i < num_channels_; ++i) {
197 output_resamplers_[i]->Resample(data_->channels()[i], buffer_num_frames_,
198 buffer->channels()[i],
199 buffer->num_frames());
200 }
201 } else {
202 for (size_t i = 0; i < num_channels_; ++i) {
203 memcpy(buffer->channels()[i], data_->channels()[i],
204 buffer_num_frames_ * sizeof(**buffer->channels()));
205 }
206 }
207
208 for (size_t i = num_channels_; i < buffer->num_channels(); ++i) {
209 memcpy(buffer->channels()[i], buffer->channels()[0],
210 output_num_frames_ * sizeof(**buffer->channels()));
211 }
212}
213
Per Åhgrend47941e2019-08-22 11:51:13 +0200214void AudioBuffer::RestoreNumChannels() {
215 num_channels_ = buffer_num_channels_;
216 data_->set_num_channels(buffer_num_channels_);
Alejandro Luebsa181c9a2016-06-30 15:33:37 -0700217 if (split_data_.get()) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200218 split_data_->set_num_channels(buffer_num_channels_);
Alejandro Luebsa181c9a2016-06-30 15:33:37 -0700219 }
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000220}
221
Peter Kasting69558702016-01-12 16:26:35 -0800222void AudioBuffer::set_num_channels(size_t num_channels) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200223 RTC_DCHECK_GE(buffer_num_channels_, num_channels);
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000224 num_channels_ = num_channels;
Alejandro Luebsa181c9a2016-06-30 15:33:37 -0700225 data_->set_num_channels(num_channels);
226 if (split_data_.get()) {
227 split_data_->set_num_channels(num_channels);
228 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000229}
230
Alejandro Luebs05c76052015-05-20 14:39:39 -0700231// The resampler is only for supporting 48kHz to 16kHz in the reverse stream.
Per Åhgren645f24c2020-03-16 12:06:02 +0100232void AudioBuffer::CopyFrom(const int16_t* const interleaved_data,
233 const StreamConfig& stream_config) {
234 RTC_DCHECK_EQ(stream_config.num_channels(), input_num_channels_);
235 RTC_DCHECK_EQ(stream_config.num_frames(), input_num_frames_);
Per Åhgrend47941e2019-08-22 11:51:13 +0200236 RestoreNumChannels();
niklase@google.com470e71d2011-07-07 08:21:25 +0000237
Per Åhgrend47941e2019-08-22 11:51:13 +0200238 const bool resampling_required = input_num_frames_ != buffer_num_frames_;
Per Åhgren81c0cf22019-08-21 15:02:37 +0200239
Per Åhgren645f24c2020-03-16 12:06:02 +0100240 const int16_t* interleaved = interleaved_data;
Per Åhgrend47941e2019-08-22 11:51:13 +0200241 if (num_channels_ == 1) {
242 if (input_num_channels_ == 1) {
243 if (resampling_required) {
244 std::array<float, kMaxSamplesPerChannel> float_buffer;
245 S16ToFloatS16(interleaved, input_num_frames_, float_buffer.data());
246 input_resamplers_[0]->Resample(float_buffer.data(), input_num_frames_,
247 data_->channels()[0],
248 buffer_num_frames_);
249 } else {
250 S16ToFloatS16(interleaved, input_num_frames_, data_->channels()[0]);
251 }
252 } else {
253 std::array<float, kMaxSamplesPerChannel> float_buffer;
254 float* downmixed_data =
255 resampling_required ? float_buffer.data() : data_->channels()[0];
256 if (downmix_by_averaging_) {
257 for (size_t j = 0, k = 0; j < input_num_frames_; ++j) {
258 int32_t sum = 0;
259 for (size_t i = 0; i < input_num_channels_; ++i, ++k) {
260 sum += interleaved[k];
261 }
262 downmixed_data[j] = sum / static_cast<int16_t>(input_num_channels_);
263 }
264 } else {
265 for (size_t j = 0, k = channel_for_downmixing_; j < input_num_frames_;
266 ++j, k += input_num_channels_) {
267 downmixed_data[j] = interleaved[k];
268 }
269 }
270
271 if (resampling_required) {
272 input_resamplers_[0]->Resample(downmixed_data, input_num_frames_,
273 data_->channels()[0],
274 buffer_num_frames_);
275 }
276 }
277 } else {
278 auto deinterleave_channel = [](size_t channel, size_t num_channels,
279 size_t samples_per_channel, const int16_t* x,
280 float* y) {
281 for (size_t j = 0, k = channel; j < samples_per_channel;
282 ++j, k += num_channels) {
283 y[j] = x[k];
284 }
285 };
286
287 if (resampling_required) {
288 std::array<float, kMaxSamplesPerChannel> float_buffer;
289 for (size_t i = 0; i < num_channels_; ++i) {
290 deinterleave_channel(i, num_channels_, input_num_frames_, interleaved,
291 float_buffer.data());
292 input_resamplers_[i]->Resample(float_buffer.data(), input_num_frames_,
293 data_->channels()[i],
294 buffer_num_frames_);
295 }
296 } else {
297 for (size_t i = 0; i < num_channels_; ++i) {
298 deinterleave_channel(i, num_channels_, input_num_frames_, interleaved,
299 data_->channels()[i]);
300 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000301 }
302 }
303}
304
Per Åhgren645f24c2020-03-16 12:06:02 +0100305void AudioBuffer::CopyTo(const StreamConfig& stream_config,
306 int16_t* const interleaved_data) {
307 const size_t config_num_channels = stream_config.num_channels();
308
309 RTC_DCHECK(config_num_channels == num_channels_ || num_channels_ == 1);
310 RTC_DCHECK_EQ(stream_config.num_frames(), output_num_frames_);
ekmeyerson60d9b332015-08-14 10:35:55 -0700311
Per Åhgrend47941e2019-08-22 11:51:13 +0200312 const bool resampling_required = buffer_num_frames_ != output_num_frames_;
Per Åhgren81c0cf22019-08-21 15:02:37 +0200313
Per Åhgren645f24c2020-03-16 12:06:02 +0100314 int16_t* interleaved = interleaved_data;
Per Åhgrend47941e2019-08-22 11:51:13 +0200315 if (num_channels_ == 1) {
316 std::array<float, kMaxSamplesPerChannel> float_buffer;
317
318 if (resampling_required) {
319 output_resamplers_[0]->Resample(data_->channels()[0], buffer_num_frames_,
320 float_buffer.data(), output_num_frames_);
321 }
322 const float* deinterleaved =
323 resampling_required ? float_buffer.data() : data_->channels()[0];
324
Per Åhgren645f24c2020-03-16 12:06:02 +0100325 if (config_num_channels == 1) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200326 for (size_t j = 0; j < output_num_frames_; ++j) {
327 interleaved[j] = FloatS16ToS16(deinterleaved[j]);
328 }
329 } else {
330 for (size_t i = 0, k = 0; i < output_num_frames_; ++i) {
331 float tmp = FloatS16ToS16(deinterleaved[i]);
Per Åhgren645f24c2020-03-16 12:06:02 +0100332 for (size_t j = 0; j < config_num_channels; ++j, ++k) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200333 interleaved[k] = tmp;
334 }
335 }
336 }
ekmeyerson60d9b332015-08-14 10:35:55 -0700337 } else {
Per Åhgrend47941e2019-08-22 11:51:13 +0200338 auto interleave_channel = [](size_t channel, size_t num_channels,
339 size_t samples_per_channel, const float* x,
340 int16_t* y) {
341 for (size_t k = 0, j = channel; k < samples_per_channel;
342 ++k, j += num_channels) {
343 y[j] = FloatS16ToS16(x[k]);
344 }
345 };
346
347 if (resampling_required) {
348 for (size_t i = 0; i < num_channels_; ++i) {
349 std::array<float, kMaxSamplesPerChannel> float_buffer;
350 output_resamplers_[i]->Resample(data_->channels()[i],
351 buffer_num_frames_, float_buffer.data(),
352 output_num_frames_);
Per Åhgren645f24c2020-03-16 12:06:02 +0100353 interleave_channel(i, config_num_channels, output_num_frames_,
Per Åhgrend47941e2019-08-22 11:51:13 +0200354 float_buffer.data(), interleaved);
355 }
356 } else {
357 for (size_t i = 0; i < num_channels_; ++i) {
Per Åhgren645f24c2020-03-16 12:06:02 +0100358 interleave_channel(i, config_num_channels, output_num_frames_,
Per Åhgrend47941e2019-08-22 11:51:13 +0200359 data_->channels()[i], interleaved);
360 }
361 }
362
Per Åhgren645f24c2020-03-16 12:06:02 +0100363 for (size_t i = num_channels_; i < config_num_channels; ++i) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200364 for (size_t j = 0, k = i, n = num_channels_; j < output_num_frames_;
Per Åhgren645f24c2020-03-16 12:06:02 +0100365 ++j, k += config_num_channels, n += config_num_channels) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200366 interleaved[k] = interleaved[n];
367 }
368 }
ekmeyerson60d9b332015-08-14 10:35:55 -0700369 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000370}
371
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000372void AudioBuffer::SplitIntoFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000373 splitting_filter_->Analysis(data_.get(), split_data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000374}
375
376void AudioBuffer::MergeFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000377 splitting_filter_->Synthesis(split_data_.get(), data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000378}
379
Per Åhgrene35b32c2019-11-22 18:22:04 +0100380void AudioBuffer::ExportSplitChannelData(
381 size_t channel,
382 int16_t* const* split_band_data) const {
Per Åhgren928146f2019-08-20 09:19:21 +0200383 for (size_t k = 0; k < num_bands(); ++k) {
Per Åhgrene35b32c2019-11-22 18:22:04 +0100384 const float* band_data = split_bands_const(channel)[k];
Per Åhgrend47941e2019-08-22 11:51:13 +0200385
Per Åhgren928146f2019-08-20 09:19:21 +0200386 RTC_DCHECK(split_band_data[k]);
387 RTC_DCHECK(band_data);
388 for (size_t i = 0; i < num_frames_per_band(); ++i) {
389 split_band_data[k][i] = FloatS16ToS16(band_data[i]);
390 }
391 }
392}
393
Per Åhgrend47941e2019-08-22 11:51:13 +0200394void AudioBuffer::ImportSplitChannelData(
Per Åhgren928146f2019-08-20 09:19:21 +0200395 size_t channel,
396 const int16_t* const* split_band_data) {
397 for (size_t k = 0; k < num_bands(); ++k) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200398 float* band_data = split_bands(channel)[k];
Per Åhgren928146f2019-08-20 09:19:21 +0200399 RTC_DCHECK(split_band_data[k]);
400 RTC_DCHECK(band_data);
401 for (size_t i = 0; i < num_frames_per_band(); ++i) {
402 band_data[i] = split_band_data[k][i];
403 }
404 }
405}
406
niklase@google.com470e71d2011-07-07 08:21:25 +0000407} // namespace webrtc