blob: 5d542d038f556ba376f57b4f47462a90b10ff8ef [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.orgddbb8a22014-04-22 21:00:04 +000013#include "webrtc/common_audio/resampler/push_sinc_resampler.h"
pbos@webrtc.org7fad4b82013-05-28 08:11:59 +000014#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +000015#include "webrtc/modules/audio_processing/channel_buffer.h"
andrew@webrtc.org755b04a2011-11-15 16:57:56 +000016
niklase@google.com470e71d2011-07-07 08:21:25 +000017namespace webrtc {
18namespace {
19
andrew@webrtc.org103657b2014-04-24 18:28:56 +000020bool HasKeyboardChannel(AudioProcessing::ChannelLayout layout) {
21 switch (layout) {
22 case AudioProcessing::kMono:
23 case AudioProcessing::kStereo:
24 return false;
25 case AudioProcessing::kMonoAndKeyboard:
26 case AudioProcessing::kStereoAndKeyboard:
27 return true;
28 }
29 assert(false);
30 return false;
31}
32
33int KeyboardChannelIndex(AudioProcessing::ChannelLayout layout) {
34 switch (layout) {
35 case AudioProcessing::kMono:
36 case AudioProcessing::kStereo:
37 assert(false);
38 return -1;
39 case AudioProcessing::kMonoAndKeyboard:
40 return 1;
41 case AudioProcessing::kStereoAndKeyboard:
42 return 2;
43 }
44 assert(false);
45 return -1;
46}
47
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +000048template <typename T>
49void StereoToMono(const T* left, const T* right, T* out,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000050 int samples_per_channel) {
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +000051 for (int i = 0; i < samples_per_channel; ++i)
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000052 out[i] = (left[i] + right[i]) / 2;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000053}
54
niklase@google.com470e71d2011-07-07 08:21:25 +000055} // namespace
56
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000057AudioBuffer::AudioBuffer(int input_samples_per_channel,
58 int num_input_channels,
59 int process_samples_per_channel,
60 int num_process_channels,
61 int output_samples_per_channel)
62 : input_samples_per_channel_(input_samples_per_channel),
63 num_input_channels_(num_input_channels),
64 proc_samples_per_channel_(process_samples_per_channel),
65 num_proc_channels_(num_process_channels),
66 output_samples_per_channel_(output_samples_per_channel),
67 samples_per_split_channel_(proc_samples_per_channel_),
aluebs@webrtc.org2561d522014-07-17 08:27:39 +000068 mixed_low_pass_valid_(false),
andrew@webrtc.orged083d42011-09-19 15:28:51 +000069 reference_copied_(false),
70 activity_(AudioFrame::kVadUnknown),
andrew@webrtc.org103657b2014-04-24 18:28:56 +000071 keyboard_data_(NULL),
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +000072 channels_(new IFChannelBuffer(proc_samples_per_channel_,
73 num_proc_channels_)) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000074 assert(input_samples_per_channel_ > 0);
75 assert(proc_samples_per_channel_ > 0);
76 assert(output_samples_per_channel_ > 0);
77 assert(num_input_channels_ > 0 && num_input_channels_ <= 2);
78 assert(num_proc_channels_ <= num_input_channels);
niklase@google.com470e71d2011-07-07 08:21:25 +000079
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000080 if (num_input_channels_ == 2 && num_proc_channels_ == 1) {
81 input_buffer_.reset(new ChannelBuffer<float>(input_samples_per_channel_,
82 num_proc_channels_));
83 }
84
85 if (input_samples_per_channel_ != proc_samples_per_channel_ ||
86 output_samples_per_channel_ != proc_samples_per_channel_) {
87 // Create an intermediate buffer for resampling.
88 process_buffer_.reset(new ChannelBuffer<float>(proc_samples_per_channel_,
89 num_proc_channels_));
90 }
91
92 if (input_samples_per_channel_ != proc_samples_per_channel_) {
93 input_resamplers_.reserve(num_proc_channels_);
94 for (int i = 0; i < num_proc_channels_; ++i) {
95 input_resamplers_.push_back(
96 new PushSincResampler(input_samples_per_channel_,
97 proc_samples_per_channel_));
98 }
99 }
100
101 if (output_samples_per_channel_ != proc_samples_per_channel_) {
102 output_resamplers_.reserve(num_proc_channels_);
103 for (int i = 0; i < num_proc_channels_; ++i) {
104 output_resamplers_.push_back(
105 new PushSincResampler(proc_samples_per_channel_,
106 output_samples_per_channel_));
107 }
108 }
109
aluebs@webrtc.org087da132014-11-17 23:01:23 +0000110 if (proc_samples_per_channel_ == kSamplesPer32kHzChannel ||
111 proc_samples_per_channel_ == kSamplesPer48kHzChannel) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000112 samples_per_split_channel_ = kSamplesPer16kHzChannel;
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000113 split_channels_.push_back(new IFChannelBuffer(samples_per_split_channel_,
kwiberg@webrtc.org2b6bc8d2014-07-17 09:46:37 +0000114 num_proc_channels_));
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000115 split_channels_.push_back(new IFChannelBuffer(samples_per_split_channel_,
116 num_proc_channels_));
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000117 splitting_filter_.reset(new SplittingFilter(num_proc_channels_));
aluebs@webrtc.org087da132014-11-17 23:01:23 +0000118 if (proc_samples_per_channel_ == kSamplesPer48kHzChannel) {
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000119 split_channels_.push_back(new IFChannelBuffer(samples_per_split_channel_,
120 num_proc_channels_));
aluebs@webrtc.org087da132014-11-17 23:01:23 +0000121 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000122 }
123}
124
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000125AudioBuffer::~AudioBuffer() {}
126
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000127void AudioBuffer::CopyFrom(const float* const* data,
128 int samples_per_channel,
129 AudioProcessing::ChannelLayout layout) {
130 assert(samples_per_channel == input_samples_per_channel_);
131 assert(ChannelsFromLayout(layout) == num_input_channels_);
132 InitForNewData();
133
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000134 if (HasKeyboardChannel(layout)) {
135 keyboard_data_ = data[KeyboardChannelIndex(layout)];
136 }
137
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000138 // Downmix.
139 const float* const* data_ptr = data;
140 if (num_input_channels_ == 2 && num_proc_channels_ == 1) {
141 StereoToMono(data[0],
142 data[1],
143 input_buffer_->channel(0),
144 input_samples_per_channel_);
145 data_ptr = input_buffer_->channels();
146 }
147
148 // Resample.
149 if (input_samples_per_channel_ != proc_samples_per_channel_) {
150 for (int i = 0; i < num_proc_channels_; ++i) {
151 input_resamplers_[i]->Resample(data_ptr[i],
152 input_samples_per_channel_,
153 process_buffer_->channel(i),
154 proc_samples_per_channel_);
155 }
156 data_ptr = process_buffer_->channels();
157 }
158
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000159 // Convert to the S16 range.
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000160 for (int i = 0; i < num_proc_channels_; ++i) {
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000161 FloatToFloatS16(data_ptr[i], proc_samples_per_channel_,
162 channels_->fbuf()->channel(i));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000163 }
164}
165
166void AudioBuffer::CopyTo(int samples_per_channel,
167 AudioProcessing::ChannelLayout layout,
168 float* const* data) {
169 assert(samples_per_channel == output_samples_per_channel_);
170 assert(ChannelsFromLayout(layout) == num_proc_channels_);
171
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000172 // Convert to the float range.
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000173 float* const* data_ptr = data;
174 if (output_samples_per_channel_ != proc_samples_per_channel_) {
175 // Convert to an intermediate buffer for subsequent resampling.
176 data_ptr = process_buffer_->channels();
177 }
178 for (int i = 0; i < num_proc_channels_; ++i) {
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000179 FloatS16ToFloat(channels_->fbuf()->channel(i), proc_samples_per_channel_,
180 data_ptr[i]);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000181 }
182
183 // Resample.
184 if (output_samples_per_channel_ != proc_samples_per_channel_) {
185 for (int i = 0; i < num_proc_channels_; ++i) {
186 output_resamplers_[i]->Resample(data_ptr[i],
187 proc_samples_per_channel_,
188 data[i],
189 output_samples_per_channel_);
190 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000191 }
192}
193
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000194void AudioBuffer::InitForNewData() {
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000195 keyboard_data_ = NULL;
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000196 mixed_low_pass_valid_ = false;
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000197 reference_copied_ = false;
198 activity_ = AudioFrame::kVadUnknown;
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000199}
200
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000201const int16_t* AudioBuffer::data(int channel) const {
kwiberg@webrtc.orge364ac92014-07-18 07:50:29 +0000202 return channels_->ibuf_const()->channel(channel);
niklase@google.com470e71d2011-07-07 08:21:25 +0000203}
204
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000205int16_t* AudioBuffer::data(int channel) {
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000206 mixed_low_pass_valid_ = false;
kwiberg@webrtc.orge364ac92014-07-18 07:50:29 +0000207 return channels_->ibuf()->channel(channel);
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000208}
209
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000210const int16_t* const* AudioBuffer::channels() const {
211 return channels_->ibuf_const()->channels();
212}
213
214int16_t* const* AudioBuffer::channels() {
215 mixed_low_pass_valid_ = false;
216 return channels_->ibuf()->channels();
217}
218
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +0000219const float* AudioBuffer::data_f(int channel) const {
kwiberg@webrtc.orge364ac92014-07-18 07:50:29 +0000220 return channels_->fbuf_const()->channel(channel);
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +0000221}
222
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +0000223float* AudioBuffer::data_f(int channel) {
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000224 mixed_low_pass_valid_ = false;
kwiberg@webrtc.orge364ac92014-07-18 07:50:29 +0000225 return channels_->fbuf()->channel(channel);
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +0000226}
227
claguna@google.combfacaab2014-09-25 20:52:08 +0000228const float* const* AudioBuffer::channels_f() const {
229 return channels_->fbuf_const()->channels();
230}
231
232float* const* AudioBuffer::channels_f() {
233 mixed_low_pass_valid_ = false;
234 return channels_->fbuf()->channels();
235}
236
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000237const int16_t* AudioBuffer::low_pass_split_data(int channel) const {
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000238 return split_channels_.size() > 0
239 ? split_channels_[0]->ibuf_const()->channel(channel)
kwiberg@webrtc.org2b6bc8d2014-07-17 09:46:37 +0000240 : data(channel);
niklase@google.com470e71d2011-07-07 08:21:25 +0000241}
242
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000243int16_t* AudioBuffer::low_pass_split_data(int channel) {
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000244 mixed_low_pass_valid_ = false;
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000245 return split_channels_.size() > 0
246 ? split_channels_[0]->ibuf()->channel(channel)
kwiberg@webrtc.orge364ac92014-07-18 07:50:29 +0000247 : data(channel);
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000248}
249
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000250const int16_t* const* AudioBuffer::low_pass_split_channels() const {
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000251 return split_channels_.size() > 0
252 ? split_channels_[0]->ibuf_const()->channels()
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000253 : channels();
254}
255
256int16_t* const* AudioBuffer::low_pass_split_channels() {
257 mixed_low_pass_valid_ = false;
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000258 return split_channels_.size() > 0 ? split_channels_[0]->ibuf()->channels()
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000259 : channels();
260}
261
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +0000262const float* AudioBuffer::low_pass_split_data_f(int channel) const {
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000263 return split_channels_.size() > 0
264 ? split_channels_[0]->fbuf_const()->channel(channel)
kwiberg@webrtc.org2b6bc8d2014-07-17 09:46:37 +0000265 : data_f(channel);
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +0000266}
267
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +0000268float* AudioBuffer::low_pass_split_data_f(int channel) {
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000269 mixed_low_pass_valid_ = false;
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000270 return split_channels_.size() > 0
271 ? split_channels_[0]->fbuf()->channel(channel)
kwiberg@webrtc.orge364ac92014-07-18 07:50:29 +0000272 : data_f(channel);
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +0000273}
274
claguna@google.combfacaab2014-09-25 20:52:08 +0000275const float* const* AudioBuffer::low_pass_split_channels_f() const {
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000276 return split_channels_.size() > 0
277 ? split_channels_[0]->fbuf_const()->channels()
claguna@google.combfacaab2014-09-25 20:52:08 +0000278 : channels_f();
279}
280
281float* const* AudioBuffer::low_pass_split_channels_f() {
282 mixed_low_pass_valid_ = false;
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000283 return split_channels_.size() > 0
284 ? split_channels_[0]->fbuf()->channels()
claguna@google.combfacaab2014-09-25 20:52:08 +0000285 : channels_f();
286}
287
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000288const int16_t* AudioBuffer::high_pass_split_data(int channel) const {
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000289 return split_channels_.size() > 1
290 ? split_channels_[1]->ibuf_const()->channel(channel)
kwiberg@webrtc.orge364ac92014-07-18 07:50:29 +0000291 : NULL;
292}
293
294int16_t* AudioBuffer::high_pass_split_data(int channel) {
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000295 return split_channels_.size() > 1
296 ? split_channels_[1]->ibuf()->channel(channel)
kwiberg@webrtc.org2b6bc8d2014-07-17 09:46:37 +0000297 : NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000298}
299
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000300const int16_t* const* AudioBuffer::high_pass_split_channels() const {
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000301 return split_channels_.size() > 1
302 ? split_channels_[1]->ibuf_const()->channels()
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000303 : NULL;
304}
305
306int16_t* const* AudioBuffer::high_pass_split_channels() {
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000307 return split_channels_.size() > 1 ? split_channels_[1]->ibuf()->channels()
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000308 : NULL;
309}
310
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +0000311const float* AudioBuffer::high_pass_split_data_f(int channel) const {
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000312 return split_channels_.size() > 1
313 ? split_channels_[1]->fbuf_const()->channel(channel)
kwiberg@webrtc.org2b6bc8d2014-07-17 09:46:37 +0000314 : NULL;
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +0000315}
316
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +0000317float* AudioBuffer::high_pass_split_data_f(int channel) {
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000318 return split_channels_.size() > 1
319 ? split_channels_[1]->fbuf()->channel(channel)
kwiberg@webrtc.orge364ac92014-07-18 07:50:29 +0000320 : NULL;
kwiberg@webrtc.org38214d52014-07-03 09:47:33 +0000321}
322
claguna@google.combfacaab2014-09-25 20:52:08 +0000323const float* const* AudioBuffer::high_pass_split_channels_f() const {
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000324 return split_channels_.size() > 1
325 ? split_channels_[1]->fbuf_const()->channels()
claguna@google.combfacaab2014-09-25 20:52:08 +0000326 : NULL;
327}
328
329float* const* AudioBuffer::high_pass_split_channels_f() {
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000330 return split_channels_.size() > 1
331 ? split_channels_[1]->fbuf()->channels()
claguna@google.combfacaab2014-09-25 20:52:08 +0000332 : NULL;
333}
334
aluebs@webrtc.org087da132014-11-17 23:01:23 +0000335const float* const* AudioBuffer::super_high_pass_split_channels_f() const {
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000336 return split_channels_.size() > 2
337 ? split_channels_[2]->fbuf_const()->channels()
aluebs@webrtc.org087da132014-11-17 23:01:23 +0000338 : NULL;
339}
340
341float* const* AudioBuffer::super_high_pass_split_channels_f() {
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000342 return split_channels_.size() > 2
343 ? split_channels_[2]->fbuf()->channels()
aluebs@webrtc.org087da132014-11-17 23:01:23 +0000344 : NULL;
345}
346
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000347const int16_t* AudioBuffer::mixed_low_pass_data() {
348 // Currently only mixing stereo to mono is supported.
349 assert(num_proc_channels_ == 1 || num_proc_channels_ == 2);
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000350
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000351 if (num_proc_channels_ == 1) {
352 return low_pass_split_data(0);
353 }
354
355 if (!mixed_low_pass_valid_) {
356 if (!mixed_low_pass_channels_.get()) {
357 mixed_low_pass_channels_.reset(
358 new ChannelBuffer<int16_t>(samples_per_split_channel_, 1));
359 }
360 StereoToMono(low_pass_split_data(0),
361 low_pass_split_data(1),
362 mixed_low_pass_channels_->data(),
363 samples_per_split_channel_);
364 mixed_low_pass_valid_ = true;
365 }
366 return mixed_low_pass_channels_->data();
niklase@google.com470e71d2011-07-07 08:21:25 +0000367}
368
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000369const int16_t* AudioBuffer::low_pass_reference(int channel) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000370 if (!reference_copied_) {
371 return NULL;
372 }
373
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000374 return low_pass_reference_channels_->channel(channel);
niklase@google.com470e71d2011-07-07 08:21:25 +0000375}
376
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000377const float* AudioBuffer::keyboard_data() const {
378 return keyboard_data_;
379}
380
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000381void AudioBuffer::set_activity(AudioFrame::VADActivity activity) {
382 activity_ = activity;
383}
384
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000385AudioFrame::VADActivity AudioBuffer::activity() const {
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000386 return activity_;
387}
388
389int AudioBuffer::num_channels() const {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000390 return num_proc_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000391}
392
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000393int AudioBuffer::samples_per_channel() const {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000394 return proc_samples_per_channel_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000395}
396
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000397int AudioBuffer::samples_per_split_channel() const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000398 return samples_per_split_channel_;
399}
400
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000401int AudioBuffer::samples_per_keyboard_channel() const {
402 // We don't resample the keyboard channel.
403 return input_samples_per_channel_;
404}
405
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000406// TODO(andrew): Do deinterleaving and mixing in one step?
407void AudioBuffer::DeinterleaveFrom(AudioFrame* frame) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000408 assert(proc_samples_per_channel_ == input_samples_per_channel_);
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000409 assert(frame->num_channels_ == num_input_channels_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000410 assert(frame->samples_per_channel_ == proc_samples_per_channel_);
411 InitForNewData();
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000412 activity_ = frame->vad_activity_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000413
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000414 if (num_input_channels_ == 2 && num_proc_channels_ == 1) {
415 // Downmix directly; no explicit deinterleaving needed.
416 int16_t* downmixed = channels_->ibuf()->channel(0);
417 for (int i = 0; i < input_samples_per_channel_; ++i) {
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000418 downmixed[i] = (frame->data_[i * 2] + frame->data_[i * 2 + 1]) / 2;
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000419 }
420 } else {
421 assert(num_proc_channels_ == num_input_channels_);
422 int16_t* interleaved = frame->data_;
423 for (int i = 0; i < num_proc_channels_; ++i) {
424 int16_t* deinterleaved = channels_->ibuf()->channel(i);
425 int interleaved_idx = i;
426 for (int j = 0; j < proc_samples_per_channel_; ++j) {
427 deinterleaved[j] = interleaved[interleaved_idx];
428 interleaved_idx += num_proc_channels_;
429 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000430 }
431 }
432}
433
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000434void AudioBuffer::InterleaveTo(AudioFrame* frame, bool data_changed) const {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000435 assert(proc_samples_per_channel_ == output_samples_per_channel_);
436 assert(num_proc_channels_ == num_input_channels_);
437 assert(frame->num_channels_ == num_proc_channels_);
438 assert(frame->samples_per_channel_ == proc_samples_per_channel_);
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000439 frame->vad_activity_ = activity_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000440
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000441 if (!data_changed) {
442 return;
443 }
444
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000445 int16_t* interleaved = frame->data_;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000446 for (int i = 0; i < num_proc_channels_; i++) {
mflodman@webrtc.orgd5da2502014-05-15 11:17:21 +0000447 int16_t* deinterleaved = channels_->ibuf()->channel(i);
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000448 int interleaved_idx = i;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000449 for (int j = 0; j < proc_samples_per_channel_; j++) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000450 interleaved[interleaved_idx] = deinterleaved[j];
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000451 interleaved_idx += num_proc_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000452 }
453 }
454}
455
niklase@google.com470e71d2011-07-07 08:21:25 +0000456void AudioBuffer::CopyLowPassToReference() {
457 reference_copied_ = true;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000458 if (!low_pass_reference_channels_.get()) {
459 low_pass_reference_channels_.reset(
460 new ChannelBuffer<int16_t>(samples_per_split_channel_,
461 num_proc_channels_));
462 }
463 for (int i = 0; i < num_proc_channels_; i++) {
464 low_pass_reference_channels_->CopyFrom(low_pass_split_data(i), i);
niklase@google.com470e71d2011-07-07 08:21:25 +0000465 }
466}
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000467
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000468void AudioBuffer::SplitIntoFrequencyBands() {
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000469 splitting_filter_->Analysis(channels_.get(),
470 split_channels_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000471}
472
473void AudioBuffer::MergeFrequencyBands() {
aluebs@webrtc.org79b9eba2014-11-26 20:21:38 +0000474 splitting_filter_->Synthesis(split_channels_.get(),
475 channels_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000476}
477
niklase@google.com470e71d2011-07-07 08:21:25 +0000478} // namespace webrtc