blob: e7419440e7afac0e5967800458f898ff1b0cd30a [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
andrew@webrtc.org103657b2014-04-24 18:28:56 +000021bool HasKeyboardChannel(AudioProcessing::ChannelLayout layout) {
22 switch (layout) {
23 case AudioProcessing::kMono:
24 case AudioProcessing::kStereo:
25 return false;
26 case AudioProcessing::kMonoAndKeyboard:
27 case AudioProcessing::kStereoAndKeyboard:
28 return true;
29 }
30 assert(false);
31 return false;
32}
33
34int KeyboardChannelIndex(AudioProcessing::ChannelLayout layout) {
35 switch (layout) {
36 case AudioProcessing::kMono:
37 case AudioProcessing::kStereo:
38 assert(false);
39 return -1;
40 case AudioProcessing::kMonoAndKeyboard:
41 return 1;
42 case AudioProcessing::kStereoAndKeyboard:
43 return 2;
44 }
45 assert(false);
46 return -1;
47}
48
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +000049template <typename T>
50void StereoToMono(const T* left, const T* right, T* out,
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000051 int num_frames) {
52 for (int i = 0; i < num_frames; ++i)
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000053 out[i] = (left[i] + right[i]) / 2;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000054}
55
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000056int NumBandsFromSamplesPerChannel(int num_frames) {
57 int num_bands = 1;
58 if (num_frames == kSamplesPer32kHzChannel ||
59 num_frames == kSamplesPer48kHzChannel) {
60 num_bands = rtc::CheckedDivExact(num_frames,
61 static_cast<int>(kSamplesPer16kHzChannel));
62 }
63 return num_bands;
64}
65
niklase@google.com470e71d2011-07-07 08:21:25 +000066} // namespace
67
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000068AudioBuffer::AudioBuffer(int input_num_frames,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000069 int num_input_channels,
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000070 int process_num_frames,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000071 int num_process_channels,
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000072 int output_num_frames)
73 : input_num_frames_(input_num_frames),
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000074 num_input_channels_(num_input_channels),
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000075 proc_num_frames_(process_num_frames),
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000076 num_proc_channels_(num_process_channels),
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000077 output_num_frames_(output_num_frames),
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +000078 num_channels_(num_process_channels),
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000079 num_bands_(NumBandsFromSamplesPerChannel(proc_num_frames_)),
80 num_split_frames_(rtc::CheckedDivExact(
81 proc_num_frames_, num_bands_)),
aluebs@webrtc.org2561d522014-07-17 08:27:39 +000082 mixed_low_pass_valid_(false),
andrew@webrtc.orged083d42011-09-19 15:28:51 +000083 reference_copied_(false),
84 activity_(AudioFrame::kVadUnknown),
andrew@webrtc.org103657b2014-04-24 18:28:56 +000085 keyboard_data_(NULL),
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000086 data_(new IFChannelBuffer(proc_num_frames_, num_proc_channels_)) {
87 assert(input_num_frames_ > 0);
88 assert(proc_num_frames_ > 0);
89 assert(output_num_frames_ > 0);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000090 assert(num_input_channels_ > 0 && num_input_channels_ <= 2);
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000091 assert(num_proc_channels_ > 0 && num_proc_channels_ <= num_input_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +000092
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000093 if (num_input_channels_ == 2 && num_proc_channels_ == 1) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000094 input_buffer_.reset(new ChannelBuffer<float>(input_num_frames_,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +000095 num_proc_channels_));
96 }
97
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +000098 if (input_num_frames_ != proc_num_frames_ ||
99 output_num_frames_ != proc_num_frames_) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000100 // Create an intermediate buffer for resampling.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000101 process_buffer_.reset(new ChannelBuffer<float>(proc_num_frames_,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000102 num_proc_channels_));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000103
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000104 if (input_num_frames_ != proc_num_frames_) {
105 for (int i = 0; i < num_proc_channels_; ++i) {
106 input_resamplers_.push_back(
107 new PushSincResampler(input_num_frames_,
108 proc_num_frames_));
109 }
110 }
111
112 if (output_num_frames_ != proc_num_frames_) {
113 for (int i = 0; i < num_proc_channels_; ++i) {
114 output_resamplers_.push_back(
115 new PushSincResampler(proc_num_frames_,
116 output_num_frames_));
117 }
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000118 }
119 }
120
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000121 if (num_bands_ > 1) {
122 split_data_.reset(new IFChannelBuffer(proc_num_frames_,
123 num_proc_channels_,
124 num_bands_));
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000125 splitting_filter_.reset(new SplittingFilter(num_proc_channels_));
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000126 }
127}
128
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000129AudioBuffer::~AudioBuffer() {}
130
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000131void AudioBuffer::CopyFrom(const float* const* data,
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000132 int num_frames,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000133 AudioProcessing::ChannelLayout layout) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000134 assert(num_frames == input_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000135 assert(ChannelsFromLayout(layout) == num_input_channels_);
136 InitForNewData();
137
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000138 if (HasKeyboardChannel(layout)) {
139 keyboard_data_ = data[KeyboardChannelIndex(layout)];
140 }
141
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000142 // Downmix.
143 const float* const* data_ptr = data;
144 if (num_input_channels_ == 2 && num_proc_channels_ == 1) {
145 StereoToMono(data[0],
146 data[1],
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000147 input_buffer_->channels()[0],
148 input_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000149 data_ptr = input_buffer_->channels();
150 }
151
152 // Resample.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000153 if (input_num_frames_ != proc_num_frames_) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000154 for (int i = 0; i < num_proc_channels_; ++i) {
155 input_resamplers_[i]->Resample(data_ptr[i],
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000156 input_num_frames_,
157 process_buffer_->channels()[i],
158 proc_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000159 }
160 data_ptr = process_buffer_->channels();
161 }
162
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000163 // Convert to the S16 range.
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000164 for (int i = 0; i < num_proc_channels_; ++i) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000165 FloatToFloatS16(data_ptr[i],
166 proc_num_frames_,
167 data_->fbuf()->channels()[i]);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000168 }
169}
170
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000171void AudioBuffer::CopyTo(int num_frames,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000172 AudioProcessing::ChannelLayout layout,
173 float* const* data) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000174 assert(num_frames == output_num_frames_);
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000175 assert(ChannelsFromLayout(layout) == num_channels_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000176
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000177 // Convert to the float range.
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000178 float* const* data_ptr = data;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000179 if (output_num_frames_ != proc_num_frames_) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000180 // Convert to an intermediate buffer for subsequent resampling.
181 data_ptr = process_buffer_->channels();
182 }
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000183 for (int i = 0; i < num_channels_; ++i) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000184 FloatS16ToFloat(data_->fbuf()->channels()[i],
185 proc_num_frames_,
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000186 data_ptr[i]);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000187 }
188
189 // Resample.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000190 if (output_num_frames_ != proc_num_frames_) {
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000191 for (int i = 0; i < num_channels_; ++i) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000192 output_resamplers_[i]->Resample(data_ptr[i],
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000193 proc_num_frames_,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000194 data[i],
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000195 output_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000196 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000197 }
198}
199
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000200void AudioBuffer::InitForNewData() {
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000201 keyboard_data_ = NULL;
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000202 mixed_low_pass_valid_ = false;
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000203 reference_copied_ = false;
204 activity_ = AudioFrame::kVadUnknown;
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000205 num_channels_ = num_proc_channels_;
andrew@webrtc.org17e40642014-03-04 20:58:13 +0000206}
207
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000208const int16_t* const* AudioBuffer::channels_const() const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000209 return data_->ibuf_const()->channels();
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000210}
211
212int16_t* const* AudioBuffer::channels() {
213 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000214 return data_->ibuf()->channels();
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000215}
216
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000217const int16_t* const* AudioBuffer::split_bands_const(int channel) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000218 return split_data_.get() ?
219 split_data_->ibuf_const()->bands(channel) :
220 data_->ibuf_const()->bands(channel);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000221}
222
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000223int16_t* const* AudioBuffer::split_bands(int channel) {
224 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000225 return split_data_.get() ?
226 split_data_->ibuf()->bands(channel) :
227 data_->ibuf()->bands(channel);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000228}
229
230const int16_t* const* AudioBuffer::split_channels_const(Band band) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000231 if (split_data_.get()) {
232 return split_data_->ibuf_const()->channels(band);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000233 } else {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000234 return band == kBand0To8kHz ? data_->ibuf_const()->channels() : nullptr;
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000235 }
236}
237
238int16_t* const* AudioBuffer::split_channels(Band band) {
239 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000240 if (split_data_.get()) {
241 return split_data_->ibuf()->channels(band);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000242 } else {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000243 return band == kBand0To8kHz ? data_->ibuf()->channels() : nullptr;
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000244 }
245}
246
aluebs@webrtc.org3aca0b02015-02-26 21:52:20 +0000247ChannelBuffer<int16_t>* AudioBuffer::data() {
248 mixed_low_pass_valid_ = false;
249 return data_->ibuf();
250}
251
252const ChannelBuffer<int16_t>* AudioBuffer::data() const {
253 return data_->ibuf_const();
254}
255
256ChannelBuffer<int16_t>* AudioBuffer::split_data() {
257 mixed_low_pass_valid_ = false;
258 return split_data_.get() ? split_data_->ibuf() : data_->ibuf();
259}
260
261const ChannelBuffer<int16_t>* AudioBuffer::split_data() const {
262 return split_data_.get() ? split_data_->ibuf_const() : data_->ibuf_const();
263}
264
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000265const float* const* AudioBuffer::channels_const_f() const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000266 return data_->fbuf_const()->channels();
claguna@google.combfacaab2014-09-25 20:52:08 +0000267}
268
269float* const* AudioBuffer::channels_f() {
270 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000271 return data_->fbuf()->channels();
claguna@google.combfacaab2014-09-25 20:52:08 +0000272}
273
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000274const float* const* AudioBuffer::split_bands_const_f(int channel) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000275 return split_data_.get() ?
276 split_data_->fbuf_const()->bands(channel) :
277 data_->fbuf_const()->bands(channel);
niklase@google.com470e71d2011-07-07 08:21:25 +0000278}
279
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000280float* const* AudioBuffer::split_bands_f(int channel) {
281 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000282 return split_data_.get() ?
283 split_data_->fbuf()->bands(channel) :
284 data_->fbuf()->bands(channel);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000285}
286
287const float* const* AudioBuffer::split_channels_const_f(Band band) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000288 if (split_data_.get()) {
289 return split_data_->fbuf_const()->channels(band);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000290 } else {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000291 return band == kBand0To8kHz ? data_->fbuf_const()->channels() : nullptr;
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000292 }
293}
294
295float* const* AudioBuffer::split_channels_f(Band band) {
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000296 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000297 if (split_data_.get()) {
298 return split_data_->fbuf()->channels(band);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000299 } else {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000300 return band == kBand0To8kHz ? data_->fbuf()->channels() : nullptr;
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000301 }
aluebs@webrtc.org087da132014-11-17 23:01:23 +0000302}
303
aluebs@webrtc.org3aca0b02015-02-26 21:52:20 +0000304ChannelBuffer<float>* AudioBuffer::data_f() {
305 mixed_low_pass_valid_ = false;
306 return data_->fbuf();
307}
308
309const ChannelBuffer<float>* AudioBuffer::data_f() const {
310 return data_->fbuf_const();
311}
312
313ChannelBuffer<float>* AudioBuffer::split_data_f() {
314 mixed_low_pass_valid_ = false;
315 return split_data_.get() ? split_data_->fbuf() : data_->fbuf();
316}
317
318const ChannelBuffer<float>* AudioBuffer::split_data_f() const {
319 return split_data_.get() ? split_data_->fbuf_const() : data_->fbuf_const();
320}
321
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000322const int16_t* AudioBuffer::mixed_low_pass_data() {
323 // Currently only mixing stereo to mono is supported.
324 assert(num_proc_channels_ == 1 || num_proc_channels_ == 2);
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000325
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000326 if (num_proc_channels_ == 1) {
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000327 return split_bands_const(0)[kBand0To8kHz];
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000328 }
329
330 if (!mixed_low_pass_valid_) {
331 if (!mixed_low_pass_channels_.get()) {
332 mixed_low_pass_channels_.reset(
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000333 new ChannelBuffer<int16_t>(num_split_frames_, 1));
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000334 }
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000335 StereoToMono(split_bands_const(0)[kBand0To8kHz],
336 split_bands_const(1)[kBand0To8kHz],
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000337 mixed_low_pass_channels_->channels()[0],
338 num_split_frames_);
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000339 mixed_low_pass_valid_ = true;
340 }
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000341 return mixed_low_pass_channels_->channels()[0];
niklase@google.com470e71d2011-07-07 08:21:25 +0000342}
343
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000344const int16_t* AudioBuffer::low_pass_reference(int channel) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000345 if (!reference_copied_) {
346 return NULL;
347 }
348
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000349 return low_pass_reference_channels_->channels()[channel];
niklase@google.com470e71d2011-07-07 08:21:25 +0000350}
351
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000352const float* AudioBuffer::keyboard_data() const {
353 return keyboard_data_;
354}
355
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000356void AudioBuffer::set_activity(AudioFrame::VADActivity activity) {
357 activity_ = activity;
358}
359
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000360AudioFrame::VADActivity AudioBuffer::activity() const {
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000361 return activity_;
362}
363
364int AudioBuffer::num_channels() const {
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000365 return num_channels_;
366}
367
368void AudioBuffer::set_num_channels(int num_channels) {
369 num_channels_ = num_channels;
niklase@google.com470e71d2011-07-07 08:21:25 +0000370}
371
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000372int AudioBuffer::num_frames() const {
373 return proc_num_frames_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000374}
375
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000376int AudioBuffer::num_frames_per_band() const {
377 return num_split_frames_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000378}
379
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000380int AudioBuffer::num_keyboard_frames() const {
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000381 // We don't resample the keyboard channel.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000382 return input_num_frames_;
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000383}
384
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000385int AudioBuffer::num_bands() const {
386 return num_bands_;
387}
388
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000389// TODO(andrew): Do deinterleaving and mixing in one step?
390void AudioBuffer::DeinterleaveFrom(AudioFrame* frame) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000391 assert(proc_num_frames_ == input_num_frames_);
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000392 assert(frame->num_channels_ == num_input_channels_);
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000393 assert(frame->samples_per_channel_ == proc_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000394 InitForNewData();
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000395 activity_ = frame->vad_activity_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000396
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000397 if (num_input_channels_ == 2 && num_proc_channels_ == 1) {
398 // Downmix directly; no explicit deinterleaving needed.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000399 int16_t* downmixed = data_->ibuf()->channels()[0];
400 for (int i = 0; i < input_num_frames_; ++i) {
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000401 downmixed[i] = (frame->data_[i * 2] + frame->data_[i * 2 + 1]) / 2;
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000402 }
403 } else {
404 assert(num_proc_channels_ == num_input_channels_);
405 int16_t* interleaved = frame->data_;
406 for (int i = 0; i < num_proc_channels_; ++i) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000407 int16_t* deinterleaved = data_->ibuf()->channels()[i];
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000408 int interleaved_idx = i;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000409 for (int j = 0; j < proc_num_frames_; ++j) {
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000410 deinterleaved[j] = interleaved[interleaved_idx];
411 interleaved_idx += num_proc_channels_;
412 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000413 }
414 }
415}
416
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000417void AudioBuffer::InterleaveTo(AudioFrame* frame, bool data_changed) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000418 assert(proc_num_frames_ == output_num_frames_);
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000419 assert(num_channels_ == num_input_channels_);
420 assert(frame->num_channels_ == num_channels_);
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000421 assert(frame->samples_per_channel_ == proc_num_frames_);
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000422 frame->vad_activity_ = activity_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000423
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000424 if (!data_changed) {
425 return;
426 }
427
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000428 int16_t* interleaved = frame->data_;
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000429 for (int i = 0; i < num_channels_; i++) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000430 int16_t* deinterleaved = data_->ibuf()->channels()[i];
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000431 int interleaved_idx = i;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000432 for (int j = 0; j < proc_num_frames_; j++) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000433 interleaved[interleaved_idx] = deinterleaved[j];
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000434 interleaved_idx += num_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000435 }
436 }
437}
438
niklase@google.com470e71d2011-07-07 08:21:25 +0000439void AudioBuffer::CopyLowPassToReference() {
440 reference_copied_ = true;
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000441 if (!low_pass_reference_channels_.get() ||
442 low_pass_reference_channels_->num_channels() != num_channels_) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000443 low_pass_reference_channels_.reset(
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000444 new ChannelBuffer<int16_t>(num_split_frames_,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000445 num_proc_channels_));
446 }
447 for (int i = 0; i < num_proc_channels_; i++) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000448 memcpy(low_pass_reference_channels_->channels()[i],
449 split_bands_const(i)[kBand0To8kHz],
450 low_pass_reference_channels_->num_frames_per_band() *
451 sizeof(split_bands_const(i)[kBand0To8kHz][0]));
niklase@google.com470e71d2011-07-07 08:21:25 +0000452 }
453}
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000454
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000455void AudioBuffer::SplitIntoFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000456 splitting_filter_->Analysis(data_.get(), split_data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000457}
458
459void AudioBuffer::MergeFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000460 splitting_filter_->Synthesis(split_data_.get(), data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000461}
462
niklase@google.com470e71d2011-07-07 08:21:25 +0000463} // namespace webrtc