blob: 794eb97015240a09b3c0c239cebc6ea6a5a1373a [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"
kjellander@webrtc.org035e9122015-01-28 19:57:00 +000015#include "webrtc/common_audio/channel_buffer.h"
aluebs@webrtc.org87893762014-11-27 23:40:25 +000016#include "webrtc/modules/audio_processing/common.h"
andrew@webrtc.org755b04a2011-11-15 16:57:56 +000017
niklase@google.com470e71d2011-07-07 08:21:25 +000018namespace webrtc {
19namespace {
20
Alejandro Luebs5a92aa82015-04-27 11:34:45 -070021enum {
22 kSamplesPer16kHzChannel = 160,
23 kSamplesPer32kHzChannel = 320,
24 kSamplesPer48kHzChannel = 480
25};
26
andrew@webrtc.org103657b2014-04-24 18:28:56 +000027bool HasKeyboardChannel(AudioProcessing::ChannelLayout layout) {
28 switch (layout) {
29 case AudioProcessing::kMono:
30 case AudioProcessing::kStereo:
31 return false;
32 case AudioProcessing::kMonoAndKeyboard:
33 case AudioProcessing::kStereoAndKeyboard:
34 return true;
35 }
36 assert(false);
37 return false;
38}
39
40int KeyboardChannelIndex(AudioProcessing::ChannelLayout layout) {
41 switch (layout) {
42 case AudioProcessing::kMono:
43 case AudioProcessing::kStereo:
44 assert(false);
45 return -1;
46 case AudioProcessing::kMonoAndKeyboard:
47 return 1;
48 case AudioProcessing::kStereoAndKeyboard:
49 return 2;
50 }
51 assert(false);
52 return -1;
53}
54
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +000055template <typename T>
56void StereoToMono(const T* left, const T* right, T* out,
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000057 int num_frames) {
58 for (int i = 0; i < num_frames; ++i)
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000059 out[i] = (left[i] + right[i]) / 2;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000060}
61
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000062int NumBandsFromSamplesPerChannel(int num_frames) {
63 int num_bands = 1;
64 if (num_frames == kSamplesPer32kHzChannel ||
65 num_frames == kSamplesPer48kHzChannel) {
66 num_bands = rtc::CheckedDivExact(num_frames,
67 static_cast<int>(kSamplesPer16kHzChannel));
68 }
69 return num_bands;
70}
71
niklase@google.com470e71d2011-07-07 08:21:25 +000072} // namespace
73
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000074AudioBuffer::AudioBuffer(int input_num_frames,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000075 int num_input_channels,
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000076 int process_num_frames,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000077 int num_process_channels,
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000078 int output_num_frames)
79 : input_num_frames_(input_num_frames),
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000080 num_input_channels_(num_input_channels),
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000081 proc_num_frames_(process_num_frames),
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000082 num_proc_channels_(num_process_channels),
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000083 output_num_frames_(output_num_frames),
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +000084 num_channels_(num_process_channels),
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000085 num_bands_(NumBandsFromSamplesPerChannel(proc_num_frames_)),
86 num_split_frames_(rtc::CheckedDivExact(
87 proc_num_frames_, num_bands_)),
aluebs@webrtc.org2561d522014-07-17 08:27:39 +000088 mixed_low_pass_valid_(false),
andrew@webrtc.orged083d42011-09-19 15:28:51 +000089 reference_copied_(false),
90 activity_(AudioFrame::kVadUnknown),
andrew@webrtc.org103657b2014-04-24 18:28:56 +000091 keyboard_data_(NULL),
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000092 data_(new IFChannelBuffer(proc_num_frames_, num_proc_channels_)) {
93 assert(input_num_frames_ > 0);
94 assert(proc_num_frames_ > 0);
95 assert(output_num_frames_ > 0);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000096 assert(num_input_channels_ > 0 && num_input_channels_ <= 2);
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000097 assert(num_proc_channels_ > 0 && num_proc_channels_ <= num_input_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +000098
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000099 if (num_input_channels_ == 2 && num_proc_channels_ == 1) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000100 input_buffer_.reset(new ChannelBuffer<float>(input_num_frames_,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000101 num_proc_channels_));
102 }
103
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000104 if (input_num_frames_ != proc_num_frames_ ||
105 output_num_frames_ != proc_num_frames_) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000106 // Create an intermediate buffer for resampling.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000107 process_buffer_.reset(new ChannelBuffer<float>(proc_num_frames_,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000108 num_proc_channels_));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000109
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000110 if (input_num_frames_ != proc_num_frames_) {
111 for (int i = 0; i < num_proc_channels_; ++i) {
112 input_resamplers_.push_back(
113 new PushSincResampler(input_num_frames_,
114 proc_num_frames_));
115 }
116 }
117
118 if (output_num_frames_ != proc_num_frames_) {
119 for (int i = 0; i < num_proc_channels_; ++i) {
120 output_resamplers_.push_back(
121 new PushSincResampler(proc_num_frames_,
122 output_num_frames_));
123 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000124 }
125 }
126
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000127 if (num_bands_ > 1) {
128 split_data_.reset(new IFChannelBuffer(proc_num_frames_,
129 num_proc_channels_,
130 num_bands_));
Alejandro Luebs5a92aa82015-04-27 11:34:45 -0700131 splitting_filter_.reset(new SplittingFilter(num_proc_channels_,
132 num_bands_,
133 proc_num_frames_));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000134 }
135}
136
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000137AudioBuffer::~AudioBuffer() {}
138
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000139void AudioBuffer::CopyFrom(const float* const* data,
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000140 int num_frames,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000141 AudioProcessing::ChannelLayout layout) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000142 assert(num_frames == input_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000143 assert(ChannelsFromLayout(layout) == num_input_channels_);
144 InitForNewData();
145
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000146 if (HasKeyboardChannel(layout)) {
147 keyboard_data_ = data[KeyboardChannelIndex(layout)];
148 }
149
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000150 // Downmix.
151 const float* const* data_ptr = data;
152 if (num_input_channels_ == 2 && num_proc_channels_ == 1) {
153 StereoToMono(data[0],
154 data[1],
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000155 input_buffer_->channels()[0],
156 input_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000157 data_ptr = input_buffer_->channels();
158 }
159
160 // Resample.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000161 if (input_num_frames_ != proc_num_frames_) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000162 for (int i = 0; i < num_proc_channels_; ++i) {
163 input_resamplers_[i]->Resample(data_ptr[i],
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000164 input_num_frames_,
165 process_buffer_->channels()[i],
166 proc_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000167 }
168 data_ptr = process_buffer_->channels();
169 }
170
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000171 // Convert to the S16 range.
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000172 for (int i = 0; i < num_proc_channels_; ++i) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000173 FloatToFloatS16(data_ptr[i],
174 proc_num_frames_,
175 data_->fbuf()->channels()[i]);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000176 }
177}
178
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000179void AudioBuffer::CopyTo(int num_frames,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000180 AudioProcessing::ChannelLayout layout,
181 float* const* data) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000182 assert(num_frames == output_num_frames_);
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000183 assert(ChannelsFromLayout(layout) == num_channels_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000184
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000185 // Convert to the float range.
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000186 float* const* data_ptr = data;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000187 if (output_num_frames_ != proc_num_frames_) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000188 // Convert to an intermediate buffer for subsequent resampling.
189 data_ptr = process_buffer_->channels();
190 }
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000191 for (int i = 0; i < num_channels_; ++i) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000192 FloatS16ToFloat(data_->fbuf()->channels()[i],
193 proc_num_frames_,
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000194 data_ptr[i]);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000195 }
196
197 // Resample.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000198 if (output_num_frames_ != proc_num_frames_) {
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000199 for (int i = 0; i < num_channels_; ++i) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000200 output_resamplers_[i]->Resample(data_ptr[i],
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000201 proc_num_frames_,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000202 data[i],
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000203 output_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000204 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000205 }
206}
207
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000208void AudioBuffer::InitForNewData() {
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000209 keyboard_data_ = NULL;
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000210 mixed_low_pass_valid_ = false;
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000211 reference_copied_ = false;
212 activity_ = AudioFrame::kVadUnknown;
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000213 num_channels_ = num_proc_channels_;
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000214}
215
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000216const int16_t* const* AudioBuffer::channels_const() const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000217 return data_->ibuf_const()->channels();
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000218}
219
220int16_t* const* AudioBuffer::channels() {
221 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000222 return data_->ibuf()->channels();
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000223}
224
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000225const int16_t* const* AudioBuffer::split_bands_const(int channel) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000226 return split_data_.get() ?
227 split_data_->ibuf_const()->bands(channel) :
228 data_->ibuf_const()->bands(channel);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000229}
230
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000231int16_t* const* AudioBuffer::split_bands(int channel) {
232 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000233 return split_data_.get() ?
234 split_data_->ibuf()->bands(channel) :
235 data_->ibuf()->bands(channel);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000236}
237
238const int16_t* const* AudioBuffer::split_channels_const(Band band) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000239 if (split_data_.get()) {
240 return split_data_->ibuf_const()->channels(band);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000241 } else {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000242 return band == kBand0To8kHz ? data_->ibuf_const()->channels() : nullptr;
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000243 }
244}
245
246int16_t* const* AudioBuffer::split_channels(Band band) {
247 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000248 if (split_data_.get()) {
249 return split_data_->ibuf()->channels(band);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000250 } else {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000251 return band == kBand0To8kHz ? data_->ibuf()->channels() : nullptr;
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000252 }
253}
254
aluebs@webrtc.org3aca0b02015-02-26 21:52:20 +0000255ChannelBuffer<int16_t>* AudioBuffer::data() {
256 mixed_low_pass_valid_ = false;
257 return data_->ibuf();
258}
259
260const ChannelBuffer<int16_t>* AudioBuffer::data() const {
261 return data_->ibuf_const();
262}
263
264ChannelBuffer<int16_t>* AudioBuffer::split_data() {
265 mixed_low_pass_valid_ = false;
266 return split_data_.get() ? split_data_->ibuf() : data_->ibuf();
267}
268
269const ChannelBuffer<int16_t>* AudioBuffer::split_data() const {
270 return split_data_.get() ? split_data_->ibuf_const() : data_->ibuf_const();
271}
272
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000273const float* const* AudioBuffer::channels_const_f() const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000274 return data_->fbuf_const()->channels();
claguna@google.combfacaab2014-09-25 20:52:08 +0000275}
276
277float* const* AudioBuffer::channels_f() {
278 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000279 return data_->fbuf()->channels();
claguna@google.combfacaab2014-09-25 20:52:08 +0000280}
281
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000282const float* const* AudioBuffer::split_bands_const_f(int channel) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000283 return split_data_.get() ?
284 split_data_->fbuf_const()->bands(channel) :
285 data_->fbuf_const()->bands(channel);
niklase@google.com470e71d2011-07-07 08:21:25 +0000286}
287
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000288float* const* AudioBuffer::split_bands_f(int channel) {
289 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000290 return split_data_.get() ?
291 split_data_->fbuf()->bands(channel) :
292 data_->fbuf()->bands(channel);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000293}
294
295const float* const* AudioBuffer::split_channels_const_f(Band band) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000296 if (split_data_.get()) {
297 return split_data_->fbuf_const()->channels(band);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000298 } else {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000299 return band == kBand0To8kHz ? data_->fbuf_const()->channels() : nullptr;
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000300 }
301}
302
303float* const* AudioBuffer::split_channels_f(Band band) {
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000304 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000305 if (split_data_.get()) {
306 return split_data_->fbuf()->channels(band);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000307 } else {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000308 return band == kBand0To8kHz ? data_->fbuf()->channels() : nullptr;
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000309 }
aluebs@webrtc.org087da132014-11-17 23:01:23 +0000310}
311
aluebs@webrtc.org3aca0b02015-02-26 21:52:20 +0000312ChannelBuffer<float>* AudioBuffer::data_f() {
313 mixed_low_pass_valid_ = false;
314 return data_->fbuf();
315}
316
317const ChannelBuffer<float>* AudioBuffer::data_f() const {
318 return data_->fbuf_const();
319}
320
321ChannelBuffer<float>* AudioBuffer::split_data_f() {
322 mixed_low_pass_valid_ = false;
323 return split_data_.get() ? split_data_->fbuf() : data_->fbuf();
324}
325
326const ChannelBuffer<float>* AudioBuffer::split_data_f() const {
327 return split_data_.get() ? split_data_->fbuf_const() : data_->fbuf_const();
328}
329
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000330const int16_t* AudioBuffer::mixed_low_pass_data() {
331 // Currently only mixing stereo to mono is supported.
332 assert(num_proc_channels_ == 1 || num_proc_channels_ == 2);
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000333
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000334 if (num_proc_channels_ == 1) {
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000335 return split_bands_const(0)[kBand0To8kHz];
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000336 }
337
338 if (!mixed_low_pass_valid_) {
339 if (!mixed_low_pass_channels_.get()) {
340 mixed_low_pass_channels_.reset(
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000341 new ChannelBuffer<int16_t>(num_split_frames_, 1));
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000342 }
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000343 StereoToMono(split_bands_const(0)[kBand0To8kHz],
344 split_bands_const(1)[kBand0To8kHz],
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000345 mixed_low_pass_channels_->channels()[0],
346 num_split_frames_);
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000347 mixed_low_pass_valid_ = true;
348 }
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000349 return mixed_low_pass_channels_->channels()[0];
niklase@google.com470e71d2011-07-07 08:21:25 +0000350}
351
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000352const int16_t* AudioBuffer::low_pass_reference(int channel) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000353 if (!reference_copied_) {
354 return NULL;
355 }
356
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000357 return low_pass_reference_channels_->channels()[channel];
niklase@google.com470e71d2011-07-07 08:21:25 +0000358}
359
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000360const float* AudioBuffer::keyboard_data() const {
361 return keyboard_data_;
362}
363
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000364void AudioBuffer::set_activity(AudioFrame::VADActivity activity) {
365 activity_ = activity;
366}
367
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000368AudioFrame::VADActivity AudioBuffer::activity() const {
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000369 return activity_;
370}
371
372int AudioBuffer::num_channels() const {
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000373 return num_channels_;
374}
375
376void AudioBuffer::set_num_channels(int num_channels) {
377 num_channels_ = num_channels;
niklase@google.com470e71d2011-07-07 08:21:25 +0000378}
379
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000380int AudioBuffer::num_frames() const {
381 return proc_num_frames_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000382}
383
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000384int AudioBuffer::num_frames_per_band() const {
385 return num_split_frames_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000386}
387
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000388int AudioBuffer::num_keyboard_frames() const {
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000389 // We don't resample the keyboard channel.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000390 return input_num_frames_;
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000391}
392
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000393int AudioBuffer::num_bands() const {
394 return num_bands_;
395}
396
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000397// TODO(andrew): Do deinterleaving and mixing in one step?
398void AudioBuffer::DeinterleaveFrom(AudioFrame* frame) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000399 assert(proc_num_frames_ == input_num_frames_);
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000400 assert(frame->num_channels_ == num_input_channels_);
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000401 assert(frame->samples_per_channel_ == proc_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000402 InitForNewData();
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000403 activity_ = frame->vad_activity_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000404
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000405 if (num_input_channels_ == 2 && num_proc_channels_ == 1) {
406 // Downmix directly; no explicit deinterleaving needed.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000407 int16_t* downmixed = data_->ibuf()->channels()[0];
408 for (int i = 0; i < input_num_frames_; ++i) {
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000409 downmixed[i] = (frame->data_[i * 2] + frame->data_[i * 2 + 1]) / 2;
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000410 }
411 } else {
412 assert(num_proc_channels_ == num_input_channels_);
413 int16_t* interleaved = frame->data_;
414 for (int i = 0; i < num_proc_channels_; ++i) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000415 int16_t* deinterleaved = data_->ibuf()->channels()[i];
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000416 int interleaved_idx = i;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000417 for (int j = 0; j < proc_num_frames_; ++j) {
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000418 deinterleaved[j] = interleaved[interleaved_idx];
419 interleaved_idx += num_proc_channels_;
420 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000421 }
422 }
423}
424
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000425void AudioBuffer::InterleaveTo(AudioFrame* frame, bool data_changed) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000426 assert(proc_num_frames_ == output_num_frames_);
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000427 assert(num_channels_ == num_input_channels_);
428 assert(frame->num_channels_ == num_channels_);
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000429 assert(frame->samples_per_channel_ == proc_num_frames_);
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000430 frame->vad_activity_ = activity_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000431
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000432 if (!data_changed) {
433 return;
434 }
435
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000436 int16_t* interleaved = frame->data_;
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000437 for (int i = 0; i < num_channels_; i++) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000438 int16_t* deinterleaved = data_->ibuf()->channels()[i];
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000439 int interleaved_idx = i;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000440 for (int j = 0; j < proc_num_frames_; j++) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000441 interleaved[interleaved_idx] = deinterleaved[j];
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000442 interleaved_idx += num_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000443 }
444 }
445}
446
niklase@google.com470e71d2011-07-07 08:21:25 +0000447void AudioBuffer::CopyLowPassToReference() {
448 reference_copied_ = true;
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000449 if (!low_pass_reference_channels_.get() ||
450 low_pass_reference_channels_->num_channels() != num_channels_) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000451 low_pass_reference_channels_.reset(
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000452 new ChannelBuffer<int16_t>(num_split_frames_,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000453 num_proc_channels_));
454 }
455 for (int i = 0; i < num_proc_channels_; i++) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000456 memcpy(low_pass_reference_channels_->channels()[i],
457 split_bands_const(i)[kBand0To8kHz],
458 low_pass_reference_channels_->num_frames_per_band() *
459 sizeof(split_bands_const(i)[kBand0To8kHz][0]));
niklase@google.com470e71d2011-07-07 08:21:25 +0000460 }
461}
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000462
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000463void AudioBuffer::SplitIntoFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000464 splitting_filter_->Analysis(data_.get(), split_data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000465}
466
467void AudioBuffer::MergeFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000468 splitting_filter_->Synthesis(split_data_.get(), data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000469}
470
niklase@google.com470e71d2011-07-07 08:21:25 +0000471} // namespace webrtc