blob: ec5e2279ceb668b7073f63fc71f0536232a5ce4f [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
Alejandro Luebs5a92aa82015-04-27 11:34:45 -070022enum {
23 kSamplesPer16kHzChannel = 160,
24 kSamplesPer32kHzChannel = 320,
25 kSamplesPer48kHzChannel = 480
26};
27
andrew@webrtc.org103657b2014-04-24 18:28:56 +000028bool HasKeyboardChannel(AudioProcessing::ChannelLayout layout) {
29 switch (layout) {
30 case AudioProcessing::kMono:
31 case AudioProcessing::kStereo:
32 return false;
33 case AudioProcessing::kMonoAndKeyboard:
34 case AudioProcessing::kStereoAndKeyboard:
35 return true;
36 }
37 assert(false);
38 return false;
39}
40
41int KeyboardChannelIndex(AudioProcessing::ChannelLayout layout) {
42 switch (layout) {
43 case AudioProcessing::kMono:
44 case AudioProcessing::kStereo:
45 assert(false);
46 return -1;
47 case AudioProcessing::kMonoAndKeyboard:
48 return 1;
49 case AudioProcessing::kStereoAndKeyboard:
50 return 2;
51 }
52 assert(false);
53 return -1;
54}
55
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +000056template <typename T>
57void StereoToMono(const T* left, const T* right, T* out,
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000058 int num_frames) {
59 for (int i = 0; i < num_frames; ++i)
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000060 out[i] = (left[i] + right[i]) / 2;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000061}
62
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000063int NumBandsFromSamplesPerChannel(int num_frames) {
64 int num_bands = 1;
65 if (num_frames == kSamplesPer32kHzChannel ||
66 num_frames == kSamplesPer48kHzChannel) {
67 num_bands = rtc::CheckedDivExact(num_frames,
68 static_cast<int>(kSamplesPer16kHzChannel));
69 }
70 return num_bands;
71}
72
niklase@google.com470e71d2011-07-07 08:21:25 +000073} // namespace
74
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000075AudioBuffer::AudioBuffer(int input_num_frames,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000076 int num_input_channels,
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000077 int process_num_frames,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000078 int num_process_channels,
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000079 int output_num_frames)
80 : input_num_frames_(input_num_frames),
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000081 num_input_channels_(num_input_channels),
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000082 proc_num_frames_(process_num_frames),
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000083 num_proc_channels_(num_process_channels),
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000084 output_num_frames_(output_num_frames),
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +000085 num_channels_(num_process_channels),
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000086 num_bands_(NumBandsFromSamplesPerChannel(proc_num_frames_)),
87 num_split_frames_(rtc::CheckedDivExact(
88 proc_num_frames_, num_bands_)),
aluebs@webrtc.org2561d522014-07-17 08:27:39 +000089 mixed_low_pass_valid_(false),
andrew@webrtc.orged083d42011-09-19 15:28:51 +000090 reference_copied_(false),
91 activity_(AudioFrame::kVadUnknown),
andrew@webrtc.org103657b2014-04-24 18:28:56 +000092 keyboard_data_(NULL),
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000093 data_(new IFChannelBuffer(proc_num_frames_, num_proc_channels_)) {
94 assert(input_num_frames_ > 0);
95 assert(proc_num_frames_ > 0);
96 assert(output_num_frames_ > 0);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000097 assert(num_input_channels_ > 0 && num_input_channels_ <= 2);
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000098 assert(num_proc_channels_ > 0 && num_proc_channels_ <= num_input_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +000099
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000100 if (input_num_frames_ != proc_num_frames_ ||
101 output_num_frames_ != proc_num_frames_) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000102 // Create an intermediate buffer for resampling.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000103 process_buffer_.reset(new ChannelBuffer<float>(proc_num_frames_,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000104 num_proc_channels_));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000105
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000106 if (input_num_frames_ != proc_num_frames_) {
107 for (int i = 0; i < num_proc_channels_; ++i) {
108 input_resamplers_.push_back(
109 new PushSincResampler(input_num_frames_,
110 proc_num_frames_));
111 }
112 }
113
114 if (output_num_frames_ != proc_num_frames_) {
115 for (int i = 0; i < num_proc_channels_; ++i) {
116 output_resamplers_.push_back(
117 new PushSincResampler(proc_num_frames_,
118 output_num_frames_));
119 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000120 }
121 }
122
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000123 if (num_bands_ > 1) {
124 split_data_.reset(new IFChannelBuffer(proc_num_frames_,
125 num_proc_channels_,
126 num_bands_));
Alejandro Luebs5a92aa82015-04-27 11:34:45 -0700127 splitting_filter_.reset(new SplittingFilter(num_proc_channels_,
128 num_bands_,
129 proc_num_frames_));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000130 }
131}
132
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000133AudioBuffer::~AudioBuffer() {}
134
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000135void AudioBuffer::CopyFrom(const float* const* data,
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000136 int num_frames,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000137 AudioProcessing::ChannelLayout layout) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000138 assert(num_frames == input_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000139 assert(ChannelsFromLayout(layout) == num_input_channels_);
140 InitForNewData();
Alejandro Luebs05c76052015-05-20 14:39:39 -0700141 // Initialized lazily because there's a different condition in
142 // DeinterleaveFrom.
143 if ((num_input_channels_ == 2 && num_proc_channels_ == 1) && !input_buffer_) {
144 input_buffer_.reset(
145 new IFChannelBuffer(input_num_frames_, num_proc_channels_));
146 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000147
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000148 if (HasKeyboardChannel(layout)) {
149 keyboard_data_ = data[KeyboardChannelIndex(layout)];
150 }
151
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000152 // Downmix.
153 const float* const* data_ptr = data;
154 if (num_input_channels_ == 2 && num_proc_channels_ == 1) {
155 StereoToMono(data[0],
156 data[1],
Alejandro Luebs05c76052015-05-20 14:39:39 -0700157 input_buffer_->fbuf()->channels()[0],
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000158 input_num_frames_);
Alejandro Luebs05c76052015-05-20 14:39:39 -0700159 data_ptr = input_buffer_->fbuf_const()->channels();
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000160 }
161
162 // Resample.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000163 if (input_num_frames_ != proc_num_frames_) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000164 for (int i = 0; i < num_proc_channels_; ++i) {
165 input_resamplers_[i]->Resample(data_ptr[i],
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000166 input_num_frames_,
167 process_buffer_->channels()[i],
168 proc_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000169 }
170 data_ptr = process_buffer_->channels();
171 }
172
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000173 // Convert to the S16 range.
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000174 for (int i = 0; i < num_proc_channels_; ++i) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000175 FloatToFloatS16(data_ptr[i],
176 proc_num_frames_,
177 data_->fbuf()->channels()[i]);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000178 }
179}
180
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000181void AudioBuffer::CopyTo(int num_frames,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000182 AudioProcessing::ChannelLayout layout,
183 float* const* data) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000184 assert(num_frames == output_num_frames_);
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000185 assert(ChannelsFromLayout(layout) == num_channels_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000186
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000187 // Convert to the float range.
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000188 float* const* data_ptr = data;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000189 if (output_num_frames_ != proc_num_frames_) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000190 // Convert to an intermediate buffer for subsequent resampling.
191 data_ptr = process_buffer_->channels();
192 }
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000193 for (int i = 0; i < num_channels_; ++i) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000194 FloatS16ToFloat(data_->fbuf()->channels()[i],
195 proc_num_frames_,
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000196 data_ptr[i]);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000197 }
198
199 // Resample.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000200 if (output_num_frames_ != proc_num_frames_) {
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000201 for (int i = 0; i < num_channels_; ++i) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000202 output_resamplers_[i]->Resample(data_ptr[i],
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000203 proc_num_frames_,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000204 data[i],
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000205 output_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000206 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000207 }
208}
209
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000210void AudioBuffer::InitForNewData() {
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000211 keyboard_data_ = NULL;
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000212 mixed_low_pass_valid_ = false;
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000213 reference_copied_ = false;
214 activity_ = AudioFrame::kVadUnknown;
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000215 num_channels_ = num_proc_channels_;
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000216}
217
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000218const int16_t* const* AudioBuffer::channels_const() const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000219 return data_->ibuf_const()->channels();
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000220}
221
222int16_t* const* AudioBuffer::channels() {
223 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000224 return data_->ibuf()->channels();
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000225}
226
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000227const int16_t* const* AudioBuffer::split_bands_const(int channel) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000228 return split_data_.get() ?
229 split_data_->ibuf_const()->bands(channel) :
230 data_->ibuf_const()->bands(channel);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000231}
232
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000233int16_t* const* AudioBuffer::split_bands(int channel) {
234 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000235 return split_data_.get() ?
236 split_data_->ibuf()->bands(channel) :
237 data_->ibuf()->bands(channel);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000238}
239
240const int16_t* const* AudioBuffer::split_channels_const(Band band) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000241 if (split_data_.get()) {
242 return split_data_->ibuf_const()->channels(band);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000243 } else {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000244 return band == kBand0To8kHz ? data_->ibuf_const()->channels() : nullptr;
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000245 }
246}
247
248int16_t* const* AudioBuffer::split_channels(Band band) {
249 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000250 if (split_data_.get()) {
251 return split_data_->ibuf()->channels(band);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000252 } else {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000253 return band == kBand0To8kHz ? data_->ibuf()->channels() : nullptr;
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000254 }
255}
256
aluebs@webrtc.org3aca0b02015-02-26 21:52:20 +0000257ChannelBuffer<int16_t>* AudioBuffer::data() {
258 mixed_low_pass_valid_ = false;
259 return data_->ibuf();
260}
261
262const ChannelBuffer<int16_t>* AudioBuffer::data() const {
263 return data_->ibuf_const();
264}
265
266ChannelBuffer<int16_t>* AudioBuffer::split_data() {
267 mixed_low_pass_valid_ = false;
268 return split_data_.get() ? split_data_->ibuf() : data_->ibuf();
269}
270
271const ChannelBuffer<int16_t>* AudioBuffer::split_data() const {
272 return split_data_.get() ? split_data_->ibuf_const() : data_->ibuf_const();
273}
274
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000275const float* const* AudioBuffer::channels_const_f() const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000276 return data_->fbuf_const()->channels();
claguna@google.combfacaab2014-09-25 20:52:08 +0000277}
278
279float* const* AudioBuffer::channels_f() {
280 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000281 return data_->fbuf()->channels();
claguna@google.combfacaab2014-09-25 20:52:08 +0000282}
283
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000284const float* const* AudioBuffer::split_bands_const_f(int channel) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000285 return split_data_.get() ?
286 split_data_->fbuf_const()->bands(channel) :
287 data_->fbuf_const()->bands(channel);
niklase@google.com470e71d2011-07-07 08:21:25 +0000288}
289
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000290float* const* AudioBuffer::split_bands_f(int channel) {
291 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000292 return split_data_.get() ?
293 split_data_->fbuf()->bands(channel) :
294 data_->fbuf()->bands(channel);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000295}
296
297const float* const* AudioBuffer::split_channels_const_f(Band band) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000298 if (split_data_.get()) {
299 return split_data_->fbuf_const()->channels(band);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000300 } else {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000301 return band == kBand0To8kHz ? data_->fbuf_const()->channels() : nullptr;
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000302 }
303}
304
305float* const* AudioBuffer::split_channels_f(Band band) {
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000306 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000307 if (split_data_.get()) {
308 return split_data_->fbuf()->channels(band);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000309 } else {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000310 return band == kBand0To8kHz ? data_->fbuf()->channels() : nullptr;
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000311 }
aluebs@webrtc.org087da132014-11-17 23:01:23 +0000312}
313
aluebs@webrtc.org3aca0b02015-02-26 21:52:20 +0000314ChannelBuffer<float>* AudioBuffer::data_f() {
315 mixed_low_pass_valid_ = false;
316 return data_->fbuf();
317}
318
319const ChannelBuffer<float>* AudioBuffer::data_f() const {
320 return data_->fbuf_const();
321}
322
323ChannelBuffer<float>* AudioBuffer::split_data_f() {
324 mixed_low_pass_valid_ = false;
325 return split_data_.get() ? split_data_->fbuf() : data_->fbuf();
326}
327
328const ChannelBuffer<float>* AudioBuffer::split_data_f() const {
329 return split_data_.get() ? split_data_->fbuf_const() : data_->fbuf_const();
330}
331
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000332const int16_t* AudioBuffer::mixed_low_pass_data() {
333 // Currently only mixing stereo to mono is supported.
334 assert(num_proc_channels_ == 1 || num_proc_channels_ == 2);
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000335
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000336 if (num_proc_channels_ == 1) {
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000337 return split_bands_const(0)[kBand0To8kHz];
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000338 }
339
340 if (!mixed_low_pass_valid_) {
341 if (!mixed_low_pass_channels_.get()) {
342 mixed_low_pass_channels_.reset(
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000343 new ChannelBuffer<int16_t>(num_split_frames_, 1));
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000344 }
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000345 StereoToMono(split_bands_const(0)[kBand0To8kHz],
346 split_bands_const(1)[kBand0To8kHz],
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000347 mixed_low_pass_channels_->channels()[0],
348 num_split_frames_);
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000349 mixed_low_pass_valid_ = true;
350 }
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000351 return mixed_low_pass_channels_->channels()[0];
niklase@google.com470e71d2011-07-07 08:21:25 +0000352}
353
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000354const int16_t* AudioBuffer::low_pass_reference(int channel) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000355 if (!reference_copied_) {
356 return NULL;
357 }
358
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000359 return low_pass_reference_channels_->channels()[channel];
niklase@google.com470e71d2011-07-07 08:21:25 +0000360}
361
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000362const float* AudioBuffer::keyboard_data() const {
363 return keyboard_data_;
364}
365
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000366void AudioBuffer::set_activity(AudioFrame::VADActivity activity) {
367 activity_ = activity;
368}
369
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000370AudioFrame::VADActivity AudioBuffer::activity() const {
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000371 return activity_;
372}
373
374int AudioBuffer::num_channels() const {
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000375 return num_channels_;
376}
377
378void AudioBuffer::set_num_channels(int num_channels) {
379 num_channels_ = num_channels;
niklase@google.com470e71d2011-07-07 08:21:25 +0000380}
381
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000382int AudioBuffer::num_frames() const {
383 return proc_num_frames_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000384}
385
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000386int AudioBuffer::num_frames_per_band() const {
387 return num_split_frames_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000388}
389
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000390int AudioBuffer::num_keyboard_frames() const {
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000391 // We don't resample the keyboard channel.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000392 return input_num_frames_;
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000393}
394
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000395int AudioBuffer::num_bands() const {
396 return num_bands_;
397}
398
Alejandro Luebs05c76052015-05-20 14:39:39 -0700399// The resampler is only for supporting 48kHz to 16kHz in the reverse stream.
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000400void AudioBuffer::DeinterleaveFrom(AudioFrame* frame) {
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000401 assert(frame->num_channels_ == num_input_channels_);
Alejandro Luebs05c76052015-05-20 14:39:39 -0700402 assert(frame->samples_per_channel_ == input_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000403 InitForNewData();
Alejandro Luebs05c76052015-05-20 14:39:39 -0700404 // Initialized lazily because there's a different condition in CopyFrom.
405 if ((input_num_frames_ != proc_num_frames_) && !input_buffer_) {
406 input_buffer_.reset(
407 new IFChannelBuffer(input_num_frames_, num_proc_channels_));
408 }
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000409 activity_ = frame->vad_activity_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000410
Alejandro Luebs05c76052015-05-20 14:39:39 -0700411 int16_t* const* deinterleaved;
412 if (input_num_frames_ == proc_num_frames_) {
413 deinterleaved = data_->ibuf()->channels();
414 } else {
415 deinterleaved = input_buffer_->ibuf()->channels();
416 }
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000417 if (num_input_channels_ == 2 && num_proc_channels_ == 1) {
418 // Downmix directly; no explicit deinterleaving needed.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000419 for (int i = 0; i < input_num_frames_; ++i) {
Alejandro Luebs05c76052015-05-20 14:39:39 -0700420 deinterleaved[0][i] = (frame->data_[i * 2] + frame->data_[i * 2 + 1]) / 2;
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000421 }
422 } else {
423 assert(num_proc_channels_ == num_input_channels_);
Alejandro Luebs05c76052015-05-20 14:39:39 -0700424 Deinterleave(frame->data_,
425 input_num_frames_,
426 num_proc_channels_,
427 deinterleaved);
428 }
429
430 // Resample.
431 if (input_num_frames_ != proc_num_frames_) {
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000432 for (int i = 0; i < num_proc_channels_; ++i) {
Alejandro Luebs05c76052015-05-20 14:39:39 -0700433 input_resamplers_[i]->Resample(input_buffer_->fbuf_const()->channels()[i],
434 input_num_frames_,
435 data_->fbuf()->channels()[i],
436 proc_num_frames_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000437 }
438 }
439}
440
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000441void AudioBuffer::InterleaveTo(AudioFrame* frame, bool data_changed) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000442 assert(proc_num_frames_ == output_num_frames_);
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000443 assert(num_channels_ == num_input_channels_);
444 assert(frame->num_channels_ == num_channels_);
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000445 assert(frame->samples_per_channel_ == proc_num_frames_);
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000446 frame->vad_activity_ = activity_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000447
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000448 if (!data_changed) {
449 return;
450 }
451
Alejandro Luebs05c76052015-05-20 14:39:39 -0700452 Interleave(data_->ibuf()->channels(),
453 proc_num_frames_,
454 num_channels_,
455 frame->data_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000456}
457
niklase@google.com470e71d2011-07-07 08:21:25 +0000458void AudioBuffer::CopyLowPassToReference() {
459 reference_copied_ = true;
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000460 if (!low_pass_reference_channels_.get() ||
461 low_pass_reference_channels_->num_channels() != num_channels_) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000462 low_pass_reference_channels_.reset(
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000463 new ChannelBuffer<int16_t>(num_split_frames_,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000464 num_proc_channels_));
465 }
466 for (int i = 0; i < num_proc_channels_; i++) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000467 memcpy(low_pass_reference_channels_->channels()[i],
468 split_bands_const(i)[kBand0To8kHz],
469 low_pass_reference_channels_->num_frames_per_band() *
470 sizeof(split_bands_const(i)[kBand0To8kHz][0]));
niklase@google.com470e71d2011-07-07 08:21:25 +0000471 }
472}
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000473
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000474void AudioBuffer::SplitIntoFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000475 splitting_filter_->Analysis(data_.get(), split_data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000476}
477
478void AudioBuffer::MergeFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000479 splitting_filter_->Synthesis(split_data_.get(), data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000480}
481
niklase@google.com470e71d2011-07-07 08:21:25 +0000482} // namespace webrtc