blob: 3dbe1fe072cafb4133ef534b82ad5ff71a5c4651 [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)
Lionel Koenig39ad2d82022-04-07 11:01:26 +020048 : input_num_frames_(static_cast<int>(input_rate) / 100),
Per Åhgrend47941e2019-08-22 11:51:13 +020049 input_num_channels_(input_num_channels),
Lionel Koenig39ad2d82022-04-07 11:01:26 +020050 buffer_num_frames_(static_cast<int>(buffer_rate) / 100),
Per Åhgrend47941e2019-08-22 11:51:13 +020051 buffer_num_channels_(buffer_num_channels),
Lionel Koenig39ad2d82022-04-07 11:01:26 +020052 output_num_frames_(static_cast<int>(output_rate) / 100),
Per Åhgrend47941e2019-08-22 11:51:13 +020053 output_num_channels_(0),
54 num_channels_(buffer_num_channels),
55 num_bands_(NumBandsFromFramesPerChannel(buffer_num_frames_)),
56 num_split_frames_(rtc::CheckedDivExact(buffer_num_frames_, num_bands_)),
Gustaf Ullberg422b9e02019-10-09 13:02:14 +020057 data_(
58 new ChannelBuffer<float>(buffer_num_frames_, buffer_num_channels_)) {
kwibergaf476c72016-11-28 15:21:39 -080059 RTC_DCHECK_GT(input_num_frames_, 0);
Per Åhgrend47941e2019-08-22 11:51:13 +020060 RTC_DCHECK_GT(buffer_num_frames_, 0);
kwibergaf476c72016-11-28 15:21:39 -080061 RTC_DCHECK_GT(output_num_frames_, 0);
Per Åhgrend47941e2019-08-22 11:51:13 +020062 RTC_DCHECK_GT(input_num_channels_, 0);
63 RTC_DCHECK_GT(buffer_num_channels_, 0);
64 RTC_DCHECK_LE(buffer_num_channels_, input_num_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +000065
Per Åhgrend47941e2019-08-22 11:51:13 +020066 const bool input_resampling_needed = input_num_frames_ != buffer_num_frames_;
67 const bool output_resampling_needed =
68 output_num_frames_ != buffer_num_frames_;
69 if (input_resampling_needed) {
70 for (size_t i = 0; i < buffer_num_channels_; ++i) {
71 input_resamplers_.push_back(std::unique_ptr<PushSincResampler>(
72 new PushSincResampler(input_num_frames_, buffer_num_frames_)));
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000073 }
Per Åhgrend47941e2019-08-22 11:51:13 +020074 }
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000075
Per Åhgrend47941e2019-08-22 11:51:13 +020076 if (output_resampling_needed) {
77 for (size_t i = 0; i < buffer_num_channels_; ++i) {
78 output_resamplers_.push_back(std::unique_ptr<PushSincResampler>(
79 new PushSincResampler(buffer_num_frames_, output_num_frames_)));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000080 }
81 }
82
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000083 if (num_bands_ > 1) {
Per Åhgrend47941e2019-08-22 11:51:13 +020084 split_data_.reset(new ChannelBuffer<float>(
85 buffer_num_frames_, buffer_num_channels_, num_bands_));
86 splitting_filter_.reset(new SplittingFilter(
87 buffer_num_channels_, num_bands_, buffer_num_frames_));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000088 }
89}
90
andrew@webrtc.org103657b2014-04-24 18:28:56 +000091AudioBuffer::~AudioBuffer() {}
92
Per Åhgrend47941e2019-08-22 11:51:13 +020093void AudioBuffer::set_downmixing_to_specific_channel(size_t channel) {
94 downmix_by_averaging_ = false;
95 RTC_DCHECK_GT(input_num_channels_, channel);
96 channel_for_downmixing_ = std::min(channel, input_num_channels_ - 1);
97}
98
99void AudioBuffer::set_downmixing_by_averaging() {
100 downmix_by_averaging_ = true;
101}
102
Per Åhgren645f24c2020-03-16 12:06:02 +0100103void AudioBuffer::CopyFrom(const float* const* stacked_data,
Michael Graczyk86c6d332015-07-23 11:41:39 -0700104 const StreamConfig& stream_config) {
kwiberg9e2be5f2016-09-14 05:23:22 -0700105 RTC_DCHECK_EQ(stream_config.num_frames(), input_num_frames_);
Per Åhgrend47941e2019-08-22 11:51:13 +0200106 RTC_DCHECK_EQ(stream_config.num_channels(), input_num_channels_);
107 RestoreNumChannels();
108 const bool downmix_needed = input_num_channels_ > 1 && num_channels_ == 1;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000109
Per Åhgrend47941e2019-08-22 11:51:13 +0200110 const bool resampling_needed = input_num_frames_ != buffer_num_frames_;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000111
Per Åhgrend47941e2019-08-22 11:51:13 +0200112 if (downmix_needed) {
Per Åhgren3e8bf282019-08-29 23:38:40 +0200113 RTC_DCHECK_GE(kMaxSamplesPerChannel, input_num_frames_);
Per Åhgrend47941e2019-08-22 11:51:13 +0200114
115 std::array<float, kMaxSamplesPerChannel> downmix;
116 if (downmix_by_averaging_) {
117 const float kOneByNumChannels = 1.f / input_num_channels_;
118 for (size_t i = 0; i < input_num_frames_; ++i) {
Per Åhgren645f24c2020-03-16 12:06:02 +0100119 float value = stacked_data[0][i];
Per Åhgrend47941e2019-08-22 11:51:13 +0200120 for (size_t j = 1; j < input_num_channels_; ++j) {
Per Åhgren645f24c2020-03-16 12:06:02 +0100121 value += stacked_data[j][i];
Per Åhgrend47941e2019-08-22 11:51:13 +0200122 }
123 downmix[i] = value * kOneByNumChannels;
124 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000125 }
Per Åhgren645f24c2020-03-16 12:06:02 +0100126 const float* downmixed_data = downmix_by_averaging_
127 ? downmix.data()
128 : stacked_data[channel_for_downmixing_];
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000129
Per Åhgrend47941e2019-08-22 11:51:13 +0200130 if (resampling_needed) {
131 input_resamplers_[0]->Resample(downmixed_data, input_num_frames_,
132 data_->channels()[0], buffer_num_frames_);
133 }
134 const float* data_to_convert =
135 resampling_needed ? data_->channels()[0] : downmixed_data;
136 FloatToFloatS16(data_to_convert, buffer_num_frames_, data_->channels()[0]);
137 } else {
138 if (resampling_needed) {
139 for (size_t i = 0; i < num_channels_; ++i) {
Per Åhgren645f24c2020-03-16 12:06:02 +0100140 input_resamplers_[i]->Resample(stacked_data[i], input_num_frames_,
Per Åhgrend47941e2019-08-22 11:51:13 +0200141 data_->channels()[i],
142 buffer_num_frames_);
143 FloatToFloatS16(data_->channels()[i], buffer_num_frames_,
144 data_->channels()[i]);
145 }
146 } else {
147 for (size_t i = 0; i < num_channels_; ++i) {
Per Åhgren645f24c2020-03-16 12:06:02 +0100148 FloatToFloatS16(stacked_data[i], buffer_num_frames_,
149 data_->channels()[i]);
Per Åhgrend47941e2019-08-22 11:51:13 +0200150 }
151 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000152 }
153}
154
Michael Graczyk86c6d332015-07-23 11:41:39 -0700155void AudioBuffer::CopyTo(const StreamConfig& stream_config,
Per Åhgren645f24c2020-03-16 12:06:02 +0100156 float* const* stacked_data) {
kwiberg9e2be5f2016-09-14 05:23:22 -0700157 RTC_DCHECK_EQ(stream_config.num_frames(), output_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000158
Per Åhgrend47941e2019-08-22 11:51:13 +0200159 const bool resampling_needed = output_num_frames_ != buffer_num_frames_;
160 if (resampling_needed) {
Peter Kasting69558702016-01-12 16:26:35 -0800161 for (size_t i = 0; i < num_channels_; ++i) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200162 FloatS16ToFloat(data_->channels()[i], buffer_num_frames_,
163 data_->channels()[i]);
164 output_resamplers_[i]->Resample(data_->channels()[i], buffer_num_frames_,
Per Åhgren645f24c2020-03-16 12:06:02 +0100165 stacked_data[i], output_num_frames_);
Per Åhgrend47941e2019-08-22 11:51:13 +0200166 }
167 } else {
168 for (size_t i = 0; i < num_channels_; ++i) {
Per Åhgren645f24c2020-03-16 12:06:02 +0100169 FloatS16ToFloat(data_->channels()[i], buffer_num_frames_,
170 stacked_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) {
Per Åhgren645f24c2020-03-16 12:06:02 +0100175 memcpy(stacked_data[i], stacked_data[0],
176 output_num_frames_ * sizeof(**stacked_data));
aluebsb2328d12016-01-11 20:32:29 -0800177 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000178}
179
Gustaf Ullberg422b9e02019-10-09 13:02:14 +0200180void AudioBuffer::CopyTo(AudioBuffer* buffer) const {
181 RTC_DCHECK_EQ(buffer->num_frames(), output_num_frames_);
182
183 const bool resampling_needed = output_num_frames_ != buffer_num_frames_;
184 if (resampling_needed) {
185 for (size_t i = 0; i < num_channels_; ++i) {
186 output_resamplers_[i]->Resample(data_->channels()[i], buffer_num_frames_,
187 buffer->channels()[i],
188 buffer->num_frames());
189 }
190 } else {
191 for (size_t i = 0; i < num_channels_; ++i) {
192 memcpy(buffer->channels()[i], data_->channels()[i],
193 buffer_num_frames_ * sizeof(**buffer->channels()));
194 }
195 }
196
197 for (size_t i = num_channels_; i < buffer->num_channels(); ++i) {
198 memcpy(buffer->channels()[i], buffer->channels()[0],
199 output_num_frames_ * sizeof(**buffer->channels()));
200 }
201}
202
Per Åhgrend47941e2019-08-22 11:51:13 +0200203void AudioBuffer::RestoreNumChannels() {
204 num_channels_ = buffer_num_channels_;
205 data_->set_num_channels(buffer_num_channels_);
Alejandro Luebsa181c9a2016-06-30 15:33:37 -0700206 if (split_data_.get()) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200207 split_data_->set_num_channels(buffer_num_channels_);
Alejandro Luebsa181c9a2016-06-30 15:33:37 -0700208 }
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000209}
210
Peter Kasting69558702016-01-12 16:26:35 -0800211void AudioBuffer::set_num_channels(size_t num_channels) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200212 RTC_DCHECK_GE(buffer_num_channels_, num_channels);
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000213 num_channels_ = num_channels;
Alejandro Luebsa181c9a2016-06-30 15:33:37 -0700214 data_->set_num_channels(num_channels);
215 if (split_data_.get()) {
216 split_data_->set_num_channels(num_channels);
217 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000218}
219
Alejandro Luebs05c76052015-05-20 14:39:39 -0700220// The resampler is only for supporting 48kHz to 16kHz in the reverse stream.
Per Åhgren645f24c2020-03-16 12:06:02 +0100221void AudioBuffer::CopyFrom(const int16_t* const interleaved_data,
222 const StreamConfig& stream_config) {
223 RTC_DCHECK_EQ(stream_config.num_channels(), input_num_channels_);
224 RTC_DCHECK_EQ(stream_config.num_frames(), input_num_frames_);
Per Åhgrend47941e2019-08-22 11:51:13 +0200225 RestoreNumChannels();
niklase@google.com470e71d2011-07-07 08:21:25 +0000226
Per Åhgrend47941e2019-08-22 11:51:13 +0200227 const bool resampling_required = input_num_frames_ != buffer_num_frames_;
Per Åhgren81c0cf22019-08-21 15:02:37 +0200228
Per Åhgren645f24c2020-03-16 12:06:02 +0100229 const int16_t* interleaved = interleaved_data;
Per Åhgrend47941e2019-08-22 11:51:13 +0200230 if (num_channels_ == 1) {
231 if (input_num_channels_ == 1) {
232 if (resampling_required) {
233 std::array<float, kMaxSamplesPerChannel> float_buffer;
234 S16ToFloatS16(interleaved, input_num_frames_, float_buffer.data());
235 input_resamplers_[0]->Resample(float_buffer.data(), input_num_frames_,
236 data_->channels()[0],
237 buffer_num_frames_);
238 } else {
239 S16ToFloatS16(interleaved, input_num_frames_, data_->channels()[0]);
240 }
241 } else {
242 std::array<float, kMaxSamplesPerChannel> float_buffer;
243 float* downmixed_data =
244 resampling_required ? float_buffer.data() : data_->channels()[0];
245 if (downmix_by_averaging_) {
246 for (size_t j = 0, k = 0; j < input_num_frames_; ++j) {
247 int32_t sum = 0;
248 for (size_t i = 0; i < input_num_channels_; ++i, ++k) {
249 sum += interleaved[k];
250 }
251 downmixed_data[j] = sum / static_cast<int16_t>(input_num_channels_);
252 }
253 } else {
254 for (size_t j = 0, k = channel_for_downmixing_; j < input_num_frames_;
255 ++j, k += input_num_channels_) {
256 downmixed_data[j] = interleaved[k];
257 }
258 }
259
260 if (resampling_required) {
261 input_resamplers_[0]->Resample(downmixed_data, input_num_frames_,
262 data_->channels()[0],
263 buffer_num_frames_);
264 }
265 }
266 } else {
267 auto deinterleave_channel = [](size_t channel, size_t num_channels,
268 size_t samples_per_channel, const int16_t* x,
269 float* y) {
270 for (size_t j = 0, k = channel; j < samples_per_channel;
271 ++j, k += num_channels) {
272 y[j] = x[k];
273 }
274 };
275
276 if (resampling_required) {
277 std::array<float, kMaxSamplesPerChannel> float_buffer;
278 for (size_t i = 0; i < num_channels_; ++i) {
279 deinterleave_channel(i, num_channels_, input_num_frames_, interleaved,
280 float_buffer.data());
281 input_resamplers_[i]->Resample(float_buffer.data(), input_num_frames_,
282 data_->channels()[i],
283 buffer_num_frames_);
284 }
285 } else {
286 for (size_t i = 0; i < num_channels_; ++i) {
287 deinterleave_channel(i, num_channels_, input_num_frames_, interleaved,
288 data_->channels()[i]);
289 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000290 }
291 }
292}
293
Per Åhgren645f24c2020-03-16 12:06:02 +0100294void AudioBuffer::CopyTo(const StreamConfig& stream_config,
295 int16_t* const interleaved_data) {
296 const size_t config_num_channels = stream_config.num_channels();
297
298 RTC_DCHECK(config_num_channels == num_channels_ || num_channels_ == 1);
299 RTC_DCHECK_EQ(stream_config.num_frames(), output_num_frames_);
ekmeyerson60d9b332015-08-14 10:35:55 -0700300
Per Åhgrend47941e2019-08-22 11:51:13 +0200301 const bool resampling_required = buffer_num_frames_ != output_num_frames_;
Per Åhgren81c0cf22019-08-21 15:02:37 +0200302
Per Åhgren645f24c2020-03-16 12:06:02 +0100303 int16_t* interleaved = interleaved_data;
Per Åhgrend47941e2019-08-22 11:51:13 +0200304 if (num_channels_ == 1) {
305 std::array<float, kMaxSamplesPerChannel> float_buffer;
306
307 if (resampling_required) {
308 output_resamplers_[0]->Resample(data_->channels()[0], buffer_num_frames_,
309 float_buffer.data(), output_num_frames_);
310 }
311 const float* deinterleaved =
312 resampling_required ? float_buffer.data() : data_->channels()[0];
313
Per Åhgren645f24c2020-03-16 12:06:02 +0100314 if (config_num_channels == 1) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200315 for (size_t j = 0; j < output_num_frames_; ++j) {
316 interleaved[j] = FloatS16ToS16(deinterleaved[j]);
317 }
318 } else {
319 for (size_t i = 0, k = 0; i < output_num_frames_; ++i) {
320 float tmp = FloatS16ToS16(deinterleaved[i]);
Per Åhgren645f24c2020-03-16 12:06:02 +0100321 for (size_t j = 0; j < config_num_channels; ++j, ++k) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200322 interleaved[k] = tmp;
323 }
324 }
325 }
ekmeyerson60d9b332015-08-14 10:35:55 -0700326 } else {
Per Åhgrend47941e2019-08-22 11:51:13 +0200327 auto interleave_channel = [](size_t channel, size_t num_channels,
328 size_t samples_per_channel, const float* x,
329 int16_t* y) {
330 for (size_t k = 0, j = channel; k < samples_per_channel;
331 ++k, j += num_channels) {
332 y[j] = FloatS16ToS16(x[k]);
333 }
334 };
335
336 if (resampling_required) {
337 for (size_t i = 0; i < num_channels_; ++i) {
338 std::array<float, kMaxSamplesPerChannel> float_buffer;
339 output_resamplers_[i]->Resample(data_->channels()[i],
340 buffer_num_frames_, float_buffer.data(),
341 output_num_frames_);
Per Åhgren645f24c2020-03-16 12:06:02 +0100342 interleave_channel(i, config_num_channels, output_num_frames_,
Per Åhgrend47941e2019-08-22 11:51:13 +0200343 float_buffer.data(), interleaved);
344 }
345 } else {
346 for (size_t i = 0; i < num_channels_; ++i) {
Per Åhgren645f24c2020-03-16 12:06:02 +0100347 interleave_channel(i, config_num_channels, output_num_frames_,
Per Åhgrend47941e2019-08-22 11:51:13 +0200348 data_->channels()[i], interleaved);
349 }
350 }
351
Per Åhgren645f24c2020-03-16 12:06:02 +0100352 for (size_t i = num_channels_; i < config_num_channels; ++i) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200353 for (size_t j = 0, k = i, n = num_channels_; j < output_num_frames_;
Per Åhgren645f24c2020-03-16 12:06:02 +0100354 ++j, k += config_num_channels, n += config_num_channels) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200355 interleaved[k] = interleaved[n];
356 }
357 }
ekmeyerson60d9b332015-08-14 10:35:55 -0700358 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000359}
360
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000361void AudioBuffer::SplitIntoFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000362 splitting_filter_->Analysis(data_.get(), split_data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000363}
364
365void AudioBuffer::MergeFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000366 splitting_filter_->Synthesis(split_data_.get(), data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000367}
368
Per Åhgrene35b32c2019-11-22 18:22:04 +0100369void AudioBuffer::ExportSplitChannelData(
370 size_t channel,
371 int16_t* const* split_band_data) const {
Per Åhgren928146f2019-08-20 09:19:21 +0200372 for (size_t k = 0; k < num_bands(); ++k) {
Per Åhgrene35b32c2019-11-22 18:22:04 +0100373 const float* band_data = split_bands_const(channel)[k];
Per Åhgrend47941e2019-08-22 11:51:13 +0200374
Per Åhgren928146f2019-08-20 09:19:21 +0200375 RTC_DCHECK(split_band_data[k]);
376 RTC_DCHECK(band_data);
377 for (size_t i = 0; i < num_frames_per_band(); ++i) {
378 split_band_data[k][i] = FloatS16ToS16(band_data[i]);
379 }
380 }
381}
382
Per Åhgrend47941e2019-08-22 11:51:13 +0200383void AudioBuffer::ImportSplitChannelData(
Per Åhgren928146f2019-08-20 09:19:21 +0200384 size_t channel,
385 const int16_t* const* split_band_data) {
386 for (size_t k = 0; k < num_bands(); ++k) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200387 float* band_data = split_bands(channel)[k];
Per Åhgren928146f2019-08-20 09:19:21 +0200388 RTC_DCHECK(split_band_data[k]);
389 RTC_DCHECK(band_data);
390 for (size_t i = 0; i < num_frames_per_band(); ++i) {
391 band_data[i] = split_band_data[k][i];
392 }
393 }
394}
395
niklase@google.com470e71d2011-07-07 08:21:25 +0000396} // namespace webrtc