blob: 04dcaea799d60af6bbc48d899e9ded8134d6ce03 [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
Alejandro Luebs05c76052015-05-20 14:39:39 -070013#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"
kjellander@webrtc.org035e9122015-01-28 19:57:00 +000016#include "webrtc/common_audio/channel_buffer.h"
aluebs@webrtc.org87893762014-11-27 23:40:25 +000017#include "webrtc/modules/audio_processing/common.h"
andrew@webrtc.org755b04a2011-11-15 16:57:56 +000018
niklase@google.com470e71d2011-07-07 08:21:25 +000019namespace webrtc {
20namespace {
21
Peter Kasting728d9032015-06-11 14:31:38 -070022const int kSamplesPer16kHzChannel = 160;
23const int kSamplesPer32kHzChannel = 320;
24const int kSamplesPer48kHzChannel = 480;
Alejandro Luebs5a92aa82015-04-27 11:34:45 -070025
magjed64e753c2015-07-23 04:30:06 -070026bool 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;
andrew@webrtc.org103657b2014-04-24 18:28:56 +000034 }
magjed64e753c2015-07-23 04:30:06 -070035 assert(false);
36 return false;
37}
andrew@webrtc.org103657b2014-04-24 18:28:56 +000038
magjed64e753c2015-07-23 04:30:06 -070039int 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
54template <typename T>
55void StereoToMono(const T* left, const T* right, T* out,
56 int num_frames) {
57 for (int i = 0; i < num_frames; ++i)
58 out[i] = (left[i] + right[i]) / 2;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000059}
60
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000061int NumBandsFromSamplesPerChannel(int num_frames) {
62 int num_bands = 1;
63 if (num_frames == kSamplesPer32kHzChannel ||
64 num_frames == kSamplesPer48kHzChannel) {
65 num_bands = rtc::CheckedDivExact(num_frames,
66 static_cast<int>(kSamplesPer16kHzChannel));
67 }
68 return num_bands;
69}
70
niklase@google.com470e71d2011-07-07 08:21:25 +000071} // namespace
72
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000073AudioBuffer::AudioBuffer(int input_num_frames,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000074 int num_input_channels,
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000075 int process_num_frames,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000076 int num_process_channels,
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000077 int output_num_frames)
78 : input_num_frames_(input_num_frames),
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000079 num_input_channels_(num_input_channels),
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000080 proc_num_frames_(process_num_frames),
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000081 num_proc_channels_(num_process_channels),
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000082 output_num_frames_(output_num_frames),
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +000083 num_channels_(num_process_channels),
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000084 num_bands_(NumBandsFromSamplesPerChannel(proc_num_frames_)),
Peter Kasting728d9032015-06-11 14:31:38 -070085 num_split_frames_(rtc::CheckedDivExact(proc_num_frames_, num_bands_)),
aluebs@webrtc.org2561d522014-07-17 08:27:39 +000086 mixed_low_pass_valid_(false),
andrew@webrtc.orged083d42011-09-19 15:28:51 +000087 reference_copied_(false),
88 activity_(AudioFrame::kVadUnknown),
andrew@webrtc.org103657b2014-04-24 18:28:56 +000089 keyboard_data_(NULL),
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000090 data_(new IFChannelBuffer(proc_num_frames_, num_proc_channels_)) {
91 assert(input_num_frames_ > 0);
92 assert(proc_num_frames_ > 0);
93 assert(output_num_frames_ > 0);
magjed64e753c2015-07-23 04:30:06 -070094 assert(num_input_channels_ > 0 && num_input_channels_ <= 2);
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000095 assert(num_proc_channels_ > 0 && num_proc_channels_ <= num_input_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +000096
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000097 if (input_num_frames_ != proc_num_frames_ ||
98 output_num_frames_ != proc_num_frames_) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000099 // Create an intermediate buffer for resampling.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000100 process_buffer_.reset(new ChannelBuffer<float>(proc_num_frames_,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000101 num_proc_channels_));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000102
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000103 if (input_num_frames_ != proc_num_frames_) {
104 for (int i = 0; i < num_proc_channels_; ++i) {
105 input_resamplers_.push_back(
106 new PushSincResampler(input_num_frames_,
107 proc_num_frames_));
108 }
109 }
110
111 if (output_num_frames_ != proc_num_frames_) {
112 for (int i = 0; i < num_proc_channels_; ++i) {
113 output_resamplers_.push_back(
114 new PushSincResampler(proc_num_frames_,
115 output_num_frames_));
116 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000117 }
118 }
119
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000120 if (num_bands_ > 1) {
121 split_data_.reset(new IFChannelBuffer(proc_num_frames_,
122 num_proc_channels_,
123 num_bands_));
Alejandro Luebs5a92aa82015-04-27 11:34:45 -0700124 splitting_filter_.reset(new SplittingFilter(num_proc_channels_,
125 num_bands_,
126 proc_num_frames_));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000127 }
128}
129
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000130AudioBuffer::~AudioBuffer() {}
131
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000132void AudioBuffer::CopyFrom(const float* const* data,
magjed64e753c2015-07-23 04:30:06 -0700133 int num_frames,
134 AudioProcessing::ChannelLayout layout) {
135 assert(num_frames == input_num_frames_);
136 assert(ChannelsFromLayout(layout) == num_input_channels_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000137 InitForNewData();
Alejandro Luebs05c76052015-05-20 14:39:39 -0700138 // Initialized lazily because there's a different condition in
139 // DeinterleaveFrom.
magjed64e753c2015-07-23 04:30:06 -0700140 if ((num_input_channels_ == 2 && num_proc_channels_ == 1) && !input_buffer_) {
Alejandro Luebs05c76052015-05-20 14:39:39 -0700141 input_buffer_.reset(
142 new IFChannelBuffer(input_num_frames_, num_proc_channels_));
143 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000144
magjed64e753c2015-07-23 04:30:06 -0700145 if (HasKeyboardChannel(layout)) {
146 keyboard_data_ = data[KeyboardChannelIndex(layout)];
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000147 }
148
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000149 // Downmix.
150 const float* const* data_ptr = data;
magjed64e753c2015-07-23 04:30:06 -0700151 if (num_input_channels_ == 2 && num_proc_channels_ == 1) {
152 StereoToMono(data[0],
153 data[1],
154 input_buffer_->fbuf()->channels()[0],
155 input_num_frames_);
Alejandro Luebs05c76052015-05-20 14:39:39 -0700156 data_ptr = input_buffer_->fbuf_const()->channels();
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000157 }
158
159 // Resample.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000160 if (input_num_frames_ != proc_num_frames_) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000161 for (int i = 0; i < num_proc_channels_; ++i) {
162 input_resamplers_[i]->Resample(data_ptr[i],
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000163 input_num_frames_,
164 process_buffer_->channels()[i],
165 proc_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000166 }
167 data_ptr = process_buffer_->channels();
168 }
169
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000170 // Convert to the S16 range.
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000171 for (int i = 0; i < num_proc_channels_; ++i) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000172 FloatToFloatS16(data_ptr[i],
173 proc_num_frames_,
174 data_->fbuf()->channels()[i]);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000175 }
176}
177
magjed64e753c2015-07-23 04:30:06 -0700178void AudioBuffer::CopyTo(int num_frames,
179 AudioProcessing::ChannelLayout layout,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000180 float* const* data) {
magjed64e753c2015-07-23 04:30:06 -0700181 assert(num_frames == output_num_frames_);
182 assert(ChannelsFromLayout(layout) == num_channels_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000183
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000184 // Convert to the float range.
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000185 float* const* data_ptr = data;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000186 if (output_num_frames_ != proc_num_frames_) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000187 // Convert to an intermediate buffer for subsequent resampling.
188 data_ptr = process_buffer_->channels();
189 }
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000190 for (int i = 0; i < num_channels_; ++i) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000191 FloatS16ToFloat(data_->fbuf()->channels()[i],
192 proc_num_frames_,
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000193 data_ptr[i]);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000194 }
195
196 // Resample.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000197 if (output_num_frames_ != proc_num_frames_) {
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000198 for (int i = 0; i < num_channels_; ++i) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000199 output_resamplers_[i]->Resample(data_ptr[i],
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000200 proc_num_frames_,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000201 data[i],
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000202 output_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000203 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000204 }
205}
206
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000207void AudioBuffer::InitForNewData() {
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000208 keyboard_data_ = NULL;
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000209 mixed_low_pass_valid_ = false;
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000210 reference_copied_ = false;
211 activity_ = AudioFrame::kVadUnknown;
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000212 num_channels_ = num_proc_channels_;
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000213}
214
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000215const int16_t* const* AudioBuffer::channels_const() const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000216 return data_->ibuf_const()->channels();
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000217}
218
219int16_t* const* AudioBuffer::channels() {
220 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000221 return data_->ibuf()->channels();
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000222}
223
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000224const int16_t* const* AudioBuffer::split_bands_const(int channel) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000225 return split_data_.get() ?
226 split_data_->ibuf_const()->bands(channel) :
227 data_->ibuf_const()->bands(channel);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000228}
229
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000230int16_t* const* AudioBuffer::split_bands(int channel) {
231 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000232 return split_data_.get() ?
233 split_data_->ibuf()->bands(channel) :
234 data_->ibuf()->bands(channel);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000235}
236
237const int16_t* const* AudioBuffer::split_channels_const(Band band) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000238 if (split_data_.get()) {
239 return split_data_->ibuf_const()->channels(band);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000240 } else {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000241 return band == kBand0To8kHz ? data_->ibuf_const()->channels() : nullptr;
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000242 }
243}
244
245int16_t* const* AudioBuffer::split_channels(Band band) {
246 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000247 if (split_data_.get()) {
248 return split_data_->ibuf()->channels(band);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000249 } else {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000250 return band == kBand0To8kHz ? data_->ibuf()->channels() : nullptr;
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000251 }
252}
253
aluebs@webrtc.org3aca0b02015-02-26 21:52:20 +0000254ChannelBuffer<int16_t>* AudioBuffer::data() {
255 mixed_low_pass_valid_ = false;
256 return data_->ibuf();
257}
258
259const ChannelBuffer<int16_t>* AudioBuffer::data() const {
260 return data_->ibuf_const();
261}
262
263ChannelBuffer<int16_t>* AudioBuffer::split_data() {
264 mixed_low_pass_valid_ = false;
265 return split_data_.get() ? split_data_->ibuf() : data_->ibuf();
266}
267
268const ChannelBuffer<int16_t>* AudioBuffer::split_data() const {
269 return split_data_.get() ? split_data_->ibuf_const() : data_->ibuf_const();
270}
271
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000272const float* const* AudioBuffer::channels_const_f() const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000273 return data_->fbuf_const()->channels();
claguna@google.combfacaab2014-09-25 20:52:08 +0000274}
275
276float* const* AudioBuffer::channels_f() {
277 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000278 return data_->fbuf()->channels();
claguna@google.combfacaab2014-09-25 20:52:08 +0000279}
280
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000281const float* const* AudioBuffer::split_bands_const_f(int channel) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000282 return split_data_.get() ?
283 split_data_->fbuf_const()->bands(channel) :
284 data_->fbuf_const()->bands(channel);
niklase@google.com470e71d2011-07-07 08:21:25 +0000285}
286
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000287float* const* AudioBuffer::split_bands_f(int channel) {
288 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000289 return split_data_.get() ?
290 split_data_->fbuf()->bands(channel) :
291 data_->fbuf()->bands(channel);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000292}
293
294const float* const* AudioBuffer::split_channels_const_f(Band band) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000295 if (split_data_.get()) {
296 return split_data_->fbuf_const()->channels(band);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000297 } else {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000298 return band == kBand0To8kHz ? data_->fbuf_const()->channels() : nullptr;
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000299 }
300}
301
302float* const* AudioBuffer::split_channels_f(Band band) {
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000303 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000304 if (split_data_.get()) {
305 return split_data_->fbuf()->channels(band);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000306 } else {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000307 return band == kBand0To8kHz ? data_->fbuf()->channels() : nullptr;
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000308 }
aluebs@webrtc.org087da132014-11-17 23:01:23 +0000309}
310
aluebs@webrtc.org3aca0b02015-02-26 21:52:20 +0000311ChannelBuffer<float>* AudioBuffer::data_f() {
312 mixed_low_pass_valid_ = false;
313 return data_->fbuf();
314}
315
316const ChannelBuffer<float>* AudioBuffer::data_f() const {
317 return data_->fbuf_const();
318}
319
320ChannelBuffer<float>* AudioBuffer::split_data_f() {
321 mixed_low_pass_valid_ = false;
322 return split_data_.get() ? split_data_->fbuf() : data_->fbuf();
323}
324
325const ChannelBuffer<float>* AudioBuffer::split_data_f() const {
326 return split_data_.get() ? split_data_->fbuf_const() : data_->fbuf_const();
327}
328
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000329const int16_t* AudioBuffer::mixed_low_pass_data() {
magjed64e753c2015-07-23 04:30:06 -0700330 // Currently only mixing stereo to mono is supported.
331 assert(num_proc_channels_ == 1 || num_proc_channels_ == 2);
332
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000333 if (num_proc_channels_ == 1) {
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000334 return split_bands_const(0)[kBand0To8kHz];
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000335 }
336
337 if (!mixed_low_pass_valid_) {
338 if (!mixed_low_pass_channels_.get()) {
339 mixed_low_pass_channels_.reset(
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000340 new ChannelBuffer<int16_t>(num_split_frames_, 1));
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000341 }
magjed64e753c2015-07-23 04:30:06 -0700342 StereoToMono(split_bands_const(0)[kBand0To8kHz],
343 split_bands_const(1)[kBand0To8kHz],
344 mixed_low_pass_channels_->channels()[0],
345 num_split_frames_);
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000346 mixed_low_pass_valid_ = true;
347 }
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000348 return mixed_low_pass_channels_->channels()[0];
niklase@google.com470e71d2011-07-07 08:21:25 +0000349}
350
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000351const int16_t* AudioBuffer::low_pass_reference(int channel) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000352 if (!reference_copied_) {
353 return NULL;
354 }
355
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000356 return low_pass_reference_channels_->channels()[channel];
niklase@google.com470e71d2011-07-07 08:21:25 +0000357}
358
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000359const float* AudioBuffer::keyboard_data() const {
360 return keyboard_data_;
361}
362
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000363void AudioBuffer::set_activity(AudioFrame::VADActivity activity) {
364 activity_ = activity;
365}
366
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000367AudioFrame::VADActivity AudioBuffer::activity() const {
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000368 return activity_;
369}
370
371int AudioBuffer::num_channels() const {
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000372 return num_channels_;
373}
374
375void AudioBuffer::set_num_channels(int num_channels) {
376 num_channels_ = num_channels;
niklase@google.com470e71d2011-07-07 08:21:25 +0000377}
378
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000379int AudioBuffer::num_frames() const {
380 return proc_num_frames_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000381}
382
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000383int AudioBuffer::num_frames_per_band() const {
384 return num_split_frames_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000385}
386
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000387int AudioBuffer::num_keyboard_frames() const {
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000388 // We don't resample the keyboard channel.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000389 return input_num_frames_;
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000390}
391
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000392int AudioBuffer::num_bands() const {
393 return num_bands_;
394}
395
Alejandro Luebs05c76052015-05-20 14:39:39 -0700396// The resampler is only for supporting 48kHz to 16kHz in the reverse stream.
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000397void AudioBuffer::DeinterleaveFrom(AudioFrame* frame) {
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000398 assert(frame->num_channels_ == num_input_channels_);
Peter Kasting728d9032015-06-11 14:31:38 -0700399 assert(frame->samples_per_channel_ == input_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000400 InitForNewData();
Alejandro Luebs05c76052015-05-20 14:39:39 -0700401 // Initialized lazily because there's a different condition in CopyFrom.
402 if ((input_num_frames_ != proc_num_frames_) && !input_buffer_) {
403 input_buffer_.reset(
404 new IFChannelBuffer(input_num_frames_, num_proc_channels_));
405 }
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000406 activity_ = frame->vad_activity_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000407
Alejandro Luebs05c76052015-05-20 14:39:39 -0700408 int16_t* const* deinterleaved;
409 if (input_num_frames_ == proc_num_frames_) {
410 deinterleaved = data_->ibuf()->channels();
411 } else {
412 deinterleaved = input_buffer_->ibuf()->channels();
413 }
magjed64e753c2015-07-23 04:30:06 -0700414 if (num_input_channels_ == 2 && num_proc_channels_ == 1) {
415 // Downmix directly; no explicit deinterleaving needed.
416 for (int i = 0; i < input_num_frames_; ++i) {
417 deinterleaved[0][i] = (frame->data_[i * 2] + frame->data_[i * 2 + 1]) / 2;
418 }
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000419 } else {
420 assert(num_proc_channels_ == num_input_channels_);
Alejandro Luebs05c76052015-05-20 14:39:39 -0700421 Deinterleave(frame->data_,
422 input_num_frames_,
423 num_proc_channels_,
424 deinterleaved);
425 }
426
427 // Resample.
428 if (input_num_frames_ != proc_num_frames_) {
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000429 for (int i = 0; i < num_proc_channels_; ++i) {
Alejandro Luebs05c76052015-05-20 14:39:39 -0700430 input_resamplers_[i]->Resample(input_buffer_->fbuf_const()->channels()[i],
431 input_num_frames_,
432 data_->fbuf()->channels()[i],
433 proc_num_frames_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000434 }
435 }
436}
437
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000438void AudioBuffer::InterleaveTo(AudioFrame* frame, bool data_changed) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000439 assert(proc_num_frames_ == output_num_frames_);
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000440 assert(num_channels_ == num_input_channels_);
441 assert(frame->num_channels_ == num_channels_);
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000442 assert(frame->samples_per_channel_ == proc_num_frames_);
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000443 frame->vad_activity_ = activity_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000444
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000445 if (!data_changed) {
446 return;
447 }
448
Alejandro Luebs05c76052015-05-20 14:39:39 -0700449 Interleave(data_->ibuf()->channels(),
450 proc_num_frames_,
451 num_channels_,
452 frame->data_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000453}
454
niklase@google.com470e71d2011-07-07 08:21:25 +0000455void AudioBuffer::CopyLowPassToReference() {
456 reference_copied_ = true;
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000457 if (!low_pass_reference_channels_.get() ||
458 low_pass_reference_channels_->num_channels() != num_channels_) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000459 low_pass_reference_channels_.reset(
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000460 new ChannelBuffer<int16_t>(num_split_frames_,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000461 num_proc_channels_));
462 }
463 for (int i = 0; i < num_proc_channels_; i++) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000464 memcpy(low_pass_reference_channels_->channels()[i],
465 split_bands_const(i)[kBand0To8kHz],
466 low_pass_reference_channels_->num_frames_per_band() *
467 sizeof(split_bands_const(i)[kBand0To8kHz][0]));
niklase@google.com470e71d2011-07-07 08:21:25 +0000468 }
469}
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000470
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000471void AudioBuffer::SplitIntoFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000472 splitting_filter_->Analysis(data_.get(), split_data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000473}
474
475void AudioBuffer::MergeFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000476 splitting_filter_->Synthesis(split_data_.get(), data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000477}
478
niklase@google.com470e71d2011-07-07 08:21:25 +0000479} // namespace webrtc