blob: 1ceba383bd38e90510448a40970922b5ea4857a1 [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
pbos@webrtc.org7fad4b82013-05-28 08:11:59 +000011#include "webrtc/modules/audio_processing/audio_buffer.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
andrew@webrtc.org17e40642014-03-04 20:58:13 +000013#include "webrtc/common_audio/include/audio_util.h"
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000014#include "webrtc/common_audio/resampler/push_sinc_resampler.h"
pbos@webrtc.org7fad4b82013-05-28 08:11:59 +000015#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
andrew@webrtc.org755b04a2011-11-15 16:57:56 +000016
niklase@google.com470e71d2011-07-07 08:21:25 +000017namespace webrtc {
18namespace {
19
20enum {
21 kSamplesPer8kHzChannel = 80,
22 kSamplesPer16kHzChannel = 160,
23 kSamplesPer32kHzChannel = 320
24};
25
andrew@webrtc.org103657b2014-04-24 18:28:56 +000026bool HasKeyboardChannel(AudioProcessing::ChannelLayout layout) {
27 switch (layout) {
28 case AudioProcessing::kMono:
29 case AudioProcessing::kStereo:
30 return false;
31 case AudioProcessing::kMonoAndKeyboard:
32 case AudioProcessing::kStereoAndKeyboard:
33 return true;
34 }
35 assert(false);
36 return false;
37}
38
39int KeyboardChannelIndex(AudioProcessing::ChannelLayout layout) {
40 switch (layout) {
41 case AudioProcessing::kMono:
42 case AudioProcessing::kStereo:
43 assert(false);
44 return -1;
45 case AudioProcessing::kMonoAndKeyboard:
46 return 1;
47 case AudioProcessing::kStereoAndKeyboard:
48 return 2;
49 }
50 assert(false);
51 return -1;
52}
53
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000054void StereoToMono(const float* left, const float* right, float* out,
55 int samples_per_channel) {
56 for (int i = 0; i < samples_per_channel; ++i) {
57 out[i] = (left[i] + right[i]) / 2;
58 }
niklase@google.com470e71d2011-07-07 08:21:25 +000059}
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000060
61void StereoToMono(const int16_t* left, const int16_t* right, int16_t* out,
62 int samples_per_channel) {
andrew@webrtc.org103657b2014-04-24 18:28:56 +000063 for (int i = 0; i < samples_per_channel; ++i) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000064 out[i] = (left[i] + right[i]) >> 1;
andrew@webrtc.org103657b2014-04-24 18:28:56 +000065 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000066}
67
niklase@google.com470e71d2011-07-07 08:21:25 +000068} // namespace
69
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +000070// One int16_t and one float ChannelBuffer that are kept in sync. The sync is
71// broken when someone requests write access to either ChannelBuffer, and
72// reestablished when someone requests the outdated ChannelBuffer. It is
73// therefore safe to use the return value of ibuf() and fbuf() until the next
74// call to the other method.
75class IFChannelBuffer {
76 public:
77 IFChannelBuffer(int samples_per_channel, int num_channels)
78 : ivalid_(true),
79 ibuf_(samples_per_channel, num_channels),
80 fvalid_(true),
81 fbuf_(samples_per_channel, num_channels) {}
82
83 ChannelBuffer<int16_t>* ibuf() {
84 RefreshI();
85 fvalid_ = false;
86 return &ibuf_;
87 }
88
89 ChannelBuffer<float>* fbuf() {
90 RefreshF();
91 ivalid_ = false;
92 return &fbuf_;
93 }
94
95 private:
96 void RefreshF() {
97 if (!fvalid_) {
98 assert(ivalid_);
99 const int16_t* const int_data = ibuf_.data();
100 float* const float_data = fbuf_.data();
101 const int length = fbuf_.length();
102 for (int i = 0; i < length; ++i)
103 float_data[i] = int_data[i];
104 fvalid_ = true;
105 }
106 }
107
108 void RefreshI() {
109 if (!ivalid_) {
110 assert(fvalid_);
111 const float* const float_data = fbuf_.data();
112 int16_t* const int_data = ibuf_.data();
113 const int length = ibuf_.length();
114 for (int i = 0; i < length; ++i)
115 int_data[i] = WEBRTC_SPL_SAT(std::numeric_limits<int16_t>::max(),
116 float_data[i],
117 std::numeric_limits<int16_t>::min());
118 ivalid_ = true;
119 }
120 }
121
122 bool ivalid_;
123 ChannelBuffer<int16_t> ibuf_;
124 bool fvalid_;
125 ChannelBuffer<float> fbuf_;
126};
127
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000128AudioBuffer::AudioBuffer(int input_samples_per_channel,
129 int num_input_channels,
130 int process_samples_per_channel,
131 int num_process_channels,
132 int output_samples_per_channel)
133 : input_samples_per_channel_(input_samples_per_channel),
134 num_input_channels_(num_input_channels),
135 proc_samples_per_channel_(process_samples_per_channel),
136 num_proc_channels_(num_process_channels),
137 output_samples_per_channel_(output_samples_per_channel),
138 samples_per_split_channel_(proc_samples_per_channel_),
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000139 mixed_low_pass_valid_(false),
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000140 reference_copied_(false),
141 activity_(AudioFrame::kVadUnknown),
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000142 keyboard_data_(NULL),
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +0000143 channels_(new IFChannelBuffer(proc_samples_per_channel_,
144 num_proc_channels_)) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000145 assert(input_samples_per_channel_ > 0);
146 assert(proc_samples_per_channel_ > 0);
147 assert(output_samples_per_channel_ > 0);
148 assert(num_input_channels_ > 0 && num_input_channels_ <= 2);
149 assert(num_proc_channels_ <= num_input_channels);
niklase@google.com470e71d2011-07-07 08:21:25 +0000150
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000151 if (num_input_channels_ == 2 && num_proc_channels_ == 1) {
152 input_buffer_.reset(new ChannelBuffer<float>(input_samples_per_channel_,
153 num_proc_channels_));
154 }
155
156 if (input_samples_per_channel_ != proc_samples_per_channel_ ||
157 output_samples_per_channel_ != proc_samples_per_channel_) {
158 // Create an intermediate buffer for resampling.
159 process_buffer_.reset(new ChannelBuffer<float>(proc_samples_per_channel_,
160 num_proc_channels_));
161 }
162
163 if (input_samples_per_channel_ != proc_samples_per_channel_) {
164 input_resamplers_.reserve(num_proc_channels_);
165 for (int i = 0; i < num_proc_channels_; ++i) {
166 input_resamplers_.push_back(
167 new PushSincResampler(input_samples_per_channel_,
168 proc_samples_per_channel_));
169 }
170 }
171
172 if (output_samples_per_channel_ != proc_samples_per_channel_) {
173 output_resamplers_.reserve(num_proc_channels_);
174 for (int i = 0; i < num_proc_channels_; ++i) {
175 output_resamplers_.push_back(
176 new PushSincResampler(proc_samples_per_channel_,
177 output_samples_per_channel_));
178 }
179 }
180
181 if (proc_samples_per_channel_ == kSamplesPer32kHzChannel) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000182 samples_per_split_channel_ = kSamplesPer16kHzChannel;
kwiberg@webrtc.org2b6bc8d2014-07-17 09:46:37 +0000183 split_channels_low_.reset(new IFChannelBuffer(samples_per_split_channel_,
184 num_proc_channels_));
185 split_channels_high_.reset(new IFChannelBuffer(samples_per_split_channel_,
186 num_proc_channels_));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000187 filter_states_.reset(new SplitFilterStates[num_proc_channels_]);
188 }
189}
190
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000191AudioBuffer::~AudioBuffer() {}
192
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000193void AudioBuffer::CopyFrom(const float* const* data,
194 int samples_per_channel,
195 AudioProcessing::ChannelLayout layout) {
196 assert(samples_per_channel == input_samples_per_channel_);
197 assert(ChannelsFromLayout(layout) == num_input_channels_);
198 InitForNewData();
199
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000200 if (HasKeyboardChannel(layout)) {
201 keyboard_data_ = data[KeyboardChannelIndex(layout)];
202 }
203
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000204 // Downmix.
205 const float* const* data_ptr = data;
206 if (num_input_channels_ == 2 && num_proc_channels_ == 1) {
207 StereoToMono(data[0],
208 data[1],
209 input_buffer_->channel(0),
210 input_samples_per_channel_);
211 data_ptr = input_buffer_->channels();
212 }
213
214 // Resample.
215 if (input_samples_per_channel_ != proc_samples_per_channel_) {
216 for (int i = 0; i < num_proc_channels_; ++i) {
217 input_resamplers_[i]->Resample(data_ptr[i],
218 input_samples_per_channel_,
219 process_buffer_->channel(i),
220 proc_samples_per_channel_);
221 }
222 data_ptr = process_buffer_->channels();
223 }
224
225 // Convert to int16.
226 for (int i = 0; i < num_proc_channels_; ++i) {
227 ScaleAndRoundToInt16(data_ptr[i], proc_samples_per_channel_,
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +0000228 channels_->ibuf()->channel(i));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000229 }
230}
231
232void AudioBuffer::CopyTo(int samples_per_channel,
233 AudioProcessing::ChannelLayout layout,
234 float* const* data) {
235 assert(samples_per_channel == output_samples_per_channel_);
236 assert(ChannelsFromLayout(layout) == num_proc_channels_);
237
238 // Convert to float.
239 float* const* data_ptr = data;
240 if (output_samples_per_channel_ != proc_samples_per_channel_) {
241 // Convert to an intermediate buffer for subsequent resampling.
242 data_ptr = process_buffer_->channels();
243 }
244 for (int i = 0; i < num_proc_channels_; ++i) {
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +0000245 ScaleToFloat(channels_->ibuf()->channel(i),
246 proc_samples_per_channel_,
247 data_ptr[i]);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000248 }
249
250 // Resample.
251 if (output_samples_per_channel_ != proc_samples_per_channel_) {
252 for (int i = 0; i < num_proc_channels_; ++i) {
253 output_resamplers_[i]->Resample(data_ptr[i],
254 proc_samples_per_channel_,
255 data[i],
256 output_samples_per_channel_);
257 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000258 }
259}
260
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000261void AudioBuffer::InitForNewData() {
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000262 keyboard_data_ = NULL;
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000263 mixed_low_pass_valid_ = false;
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000264 reference_copied_ = false;
265 activity_ = AudioFrame::kVadUnknown;
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000266}
267
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000268const int16_t* AudioBuffer::data(int channel) const {
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +0000269 return channels_->ibuf()->channel(channel);
niklase@google.com470e71d2011-07-07 08:21:25 +0000270}
271
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000272int16_t* AudioBuffer::data(int channel) {
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000273 mixed_low_pass_valid_ = false;
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000274 const AudioBuffer* t = this;
275 return const_cast<int16_t*>(t->data(channel));
276}
277
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +0000278const float* AudioBuffer::data_f(int channel) const {
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +0000279 return channels_->fbuf()->channel(channel);
280}
281
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +0000282float* AudioBuffer::data_f(int channel) {
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000283 mixed_low_pass_valid_ = false;
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +0000284 const AudioBuffer* t = this;
285 return const_cast<float*>(t->data_f(channel));
286}
287
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000288const int16_t* AudioBuffer::low_pass_split_data(int channel) const {
kwiberg@webrtc.org2b6bc8d2014-07-17 09:46:37 +0000289 return split_channels_low_.get()
290 ? split_channels_low_->ibuf()->channel(channel)
291 : data(channel);
niklase@google.com470e71d2011-07-07 08:21:25 +0000292}
293
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000294int16_t* AudioBuffer::low_pass_split_data(int channel) {
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000295 mixed_low_pass_valid_ = false;
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000296 const AudioBuffer* t = this;
297 return const_cast<int16_t*>(t->low_pass_split_data(channel));
298}
299
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +0000300const float* AudioBuffer::low_pass_split_data_f(int channel) const {
kwiberg@webrtc.org2b6bc8d2014-07-17 09:46:37 +0000301 return split_channels_low_.get()
302 ? split_channels_low_->fbuf()->channel(channel)
303 : data_f(channel);
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +0000304}
305
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +0000306float* AudioBuffer::low_pass_split_data_f(int channel) {
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000307 mixed_low_pass_valid_ = false;
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +0000308 const AudioBuffer* t = this;
309 return const_cast<float*>(t->low_pass_split_data_f(channel));
310}
311
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000312const int16_t* AudioBuffer::high_pass_split_data(int channel) const {
kwiberg@webrtc.org2b6bc8d2014-07-17 09:46:37 +0000313 return split_channels_high_.get()
314 ? split_channels_high_->ibuf()->channel(channel)
315 : NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000316}
317
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000318int16_t* AudioBuffer::high_pass_split_data(int channel) {
319 const AudioBuffer* t = this;
320 return const_cast<int16_t*>(t->high_pass_split_data(channel));
321}
322
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +0000323const float* AudioBuffer::high_pass_split_data_f(int channel) const {
kwiberg@webrtc.org2b6bc8d2014-07-17 09:46:37 +0000324 return split_channels_high_.get()
325 ? split_channels_high_->fbuf()->channel(channel)
326 : NULL;
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +0000327}
328
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +0000329float* AudioBuffer::high_pass_split_data_f(int channel) {
330 const AudioBuffer* t = this;
331 return const_cast<float*>(t->high_pass_split_data_f(channel));
332}
333
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000334const int16_t* AudioBuffer::mixed_low_pass_data() {
335 // Currently only mixing stereo to mono is supported.
336 assert(num_proc_channels_ == 1 || num_proc_channels_ == 2);
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000337
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000338 if (num_proc_channels_ == 1) {
339 return low_pass_split_data(0);
340 }
341
342 if (!mixed_low_pass_valid_) {
343 if (!mixed_low_pass_channels_.get()) {
344 mixed_low_pass_channels_.reset(
345 new ChannelBuffer<int16_t>(samples_per_split_channel_, 1));
346 }
347 StereoToMono(low_pass_split_data(0),
348 low_pass_split_data(1),
349 mixed_low_pass_channels_->data(),
350 samples_per_split_channel_);
351 mixed_low_pass_valid_ = true;
352 }
353 return mixed_low_pass_channels_->data();
niklase@google.com470e71d2011-07-07 08:21:25 +0000354}
355
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000356const int16_t* AudioBuffer::low_pass_reference(int channel) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000357 if (!reference_copied_) {
358 return NULL;
359 }
360
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000361 return low_pass_reference_channels_->channel(channel);
niklase@google.com470e71d2011-07-07 08:21:25 +0000362}
363
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000364const float* AudioBuffer::keyboard_data() const {
365 return keyboard_data_;
366}
367
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000368SplitFilterStates* AudioBuffer::filter_states(int channel) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000369 assert(channel >= 0 && channel < num_proc_channels_);
370 return &filter_states_[channel];
niklase@google.com470e71d2011-07-07 08:21:25 +0000371}
372
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000373void AudioBuffer::set_activity(AudioFrame::VADActivity activity) {
374 activity_ = activity;
375}
376
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000377AudioFrame::VADActivity AudioBuffer::activity() const {
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000378 return activity_;
379}
380
381int AudioBuffer::num_channels() const {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000382 return num_proc_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000383}
384
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000385int AudioBuffer::samples_per_channel() const {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000386 return proc_samples_per_channel_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000387}
388
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000389int AudioBuffer::samples_per_split_channel() const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000390 return samples_per_split_channel_;
391}
392
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000393int AudioBuffer::samples_per_keyboard_channel() const {
394 // We don't resample the keyboard channel.
395 return input_samples_per_channel_;
396}
397
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000398// TODO(andrew): Do deinterleaving and mixing in one step?
399void AudioBuffer::DeinterleaveFrom(AudioFrame* frame) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000400 assert(proc_samples_per_channel_ == input_samples_per_channel_);
401 assert(num_proc_channels_ == num_input_channels_);
402 assert(frame->num_channels_ == num_proc_channels_);
403 assert(frame->samples_per_channel_ == proc_samples_per_channel_);
404 InitForNewData();
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000405 activity_ = frame->vad_activity_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000406
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000407 int16_t* interleaved = frame->data_;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000408 for (int i = 0; i < num_proc_channels_; i++) {
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +0000409 int16_t* deinterleaved = channels_->ibuf()->channel(i);
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000410 int interleaved_idx = i;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000411 for (int j = 0; j < proc_samples_per_channel_; j++) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000412 deinterleaved[j] = interleaved[interleaved_idx];
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000413 interleaved_idx += num_proc_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000414 }
415 }
416}
417
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000418void AudioBuffer::InterleaveTo(AudioFrame* frame, bool data_changed) const {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000419 assert(proc_samples_per_channel_ == output_samples_per_channel_);
420 assert(num_proc_channels_ == num_input_channels_);
421 assert(frame->num_channels_ == num_proc_channels_);
422 assert(frame->samples_per_channel_ == proc_samples_per_channel_);
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000423 frame->vad_activity_ = activity_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000424
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000425 if (!data_changed) {
426 return;
427 }
428
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000429 int16_t* interleaved = frame->data_;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000430 for (int i = 0; i < num_proc_channels_; i++) {
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +0000431 int16_t* deinterleaved = channels_->ibuf()->channel(i);
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000432 int interleaved_idx = i;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000433 for (int j = 0; j < proc_samples_per_channel_; j++) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000434 interleaved[interleaved_idx] = deinterleaved[j];
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000435 interleaved_idx += num_proc_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000436 }
437 }
438}
439
niklase@google.com470e71d2011-07-07 08:21:25 +0000440void AudioBuffer::CopyLowPassToReference() {
441 reference_copied_ = true;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000442 if (!low_pass_reference_channels_.get()) {
443 low_pass_reference_channels_.reset(
444 new ChannelBuffer<int16_t>(samples_per_split_channel_,
445 num_proc_channels_));
446 }
447 for (int i = 0; i < num_proc_channels_; i++) {
448 low_pass_reference_channels_->CopyFrom(low_pass_split_data(i), i);
niklase@google.com470e71d2011-07-07 08:21:25 +0000449 }
450}
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000451
niklase@google.com470e71d2011-07-07 08:21:25 +0000452} // namespace webrtc