blob: c4dff8a8d0d341350e439f4a1ea40a4c1a2741c9 [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.orga7384a12014-12-03 01:06:35 +0000247const float* const* AudioBuffer::channels_const_f() const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000248 return data_->fbuf_const()->channels();
claguna@google.combfacaab2014-09-25 20:52:08 +0000249}
250
251float* const* AudioBuffer::channels_f() {
252 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000253 return data_->fbuf()->channels();
claguna@google.combfacaab2014-09-25 20:52:08 +0000254}
255
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000256const float* const* AudioBuffer::split_bands_const_f(int channel) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000257 return split_data_.get() ?
258 split_data_->fbuf_const()->bands(channel) :
259 data_->fbuf_const()->bands(channel);
niklase@google.com470e71d2011-07-07 08:21:25 +0000260}
261
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000262float* const* AudioBuffer::split_bands_f(int channel) {
263 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000264 return split_data_.get() ?
265 split_data_->fbuf()->bands(channel) :
266 data_->fbuf()->bands(channel);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000267}
268
269const float* const* AudioBuffer::split_channels_const_f(Band band) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000270 if (split_data_.get()) {
271 return split_data_->fbuf_const()->channels(band);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000272 } else {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000273 return band == kBand0To8kHz ? data_->fbuf_const()->channels() : nullptr;
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000274 }
275}
276
277float* const* AudioBuffer::split_channels_f(Band band) {
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000278 mixed_low_pass_valid_ = false;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000279 if (split_data_.get()) {
280 return split_data_->fbuf()->channels(band);
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000281 } else {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000282 return band == kBand0To8kHz ? data_->fbuf()->channels() : nullptr;
aluebs@webrtc.orga7384a12014-12-03 01:06:35 +0000283 }
aluebs@webrtc.org087da132014-11-17 23:01:23 +0000284}
285
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000286const int16_t* AudioBuffer::mixed_low_pass_data() {
287 // Currently only mixing stereo to mono is supported.
288 assert(num_proc_channels_ == 1 || num_proc_channels_ == 2);
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000289
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000290 if (num_proc_channels_ == 1) {
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000291 return split_bands_const(0)[kBand0To8kHz];
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000292 }
293
294 if (!mixed_low_pass_valid_) {
295 if (!mixed_low_pass_channels_.get()) {
296 mixed_low_pass_channels_.reset(
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000297 new ChannelBuffer<int16_t>(num_split_frames_, 1));
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000298 }
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000299 StereoToMono(split_bands_const(0)[kBand0To8kHz],
300 split_bands_const(1)[kBand0To8kHz],
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000301 mixed_low_pass_channels_->channels()[0],
302 num_split_frames_);
aluebs@webrtc.org2561d522014-07-17 08:27:39 +0000303 mixed_low_pass_valid_ = true;
304 }
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000305 return mixed_low_pass_channels_->channels()[0];
niklase@google.com470e71d2011-07-07 08:21:25 +0000306}
307
andrew@webrtc.org65f93382014-04-30 16:44:13 +0000308const int16_t* AudioBuffer::low_pass_reference(int channel) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000309 if (!reference_copied_) {
310 return NULL;
311 }
312
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000313 return low_pass_reference_channels_->channels()[channel];
niklase@google.com470e71d2011-07-07 08:21:25 +0000314}
315
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000316const float* AudioBuffer::keyboard_data() const {
317 return keyboard_data_;
318}
319
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000320void AudioBuffer::set_activity(AudioFrame::VADActivity activity) {
321 activity_ = activity;
322}
323
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000324AudioFrame::VADActivity AudioBuffer::activity() const {
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000325 return activity_;
326}
327
328int AudioBuffer::num_channels() const {
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000329 return num_channels_;
330}
331
332void AudioBuffer::set_num_channels(int num_channels) {
333 num_channels_ = num_channels;
niklase@google.com470e71d2011-07-07 08:21:25 +0000334}
335
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000336int AudioBuffer::num_frames() const {
337 return proc_num_frames_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000338}
339
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000340int AudioBuffer::num_frames_per_band() const {
341 return num_split_frames_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000342}
343
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000344int AudioBuffer::num_keyboard_frames() const {
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000345 // We don't resample the keyboard channel.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000346 return input_num_frames_;
andrew@webrtc.org103657b2014-04-24 18:28:56 +0000347}
348
aluebs@webrtc.orgc5ebbd92014-12-10 19:30:57 +0000349int AudioBuffer::num_bands() const {
350 return num_bands_;
351}
352
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000353// TODO(andrew): Do deinterleaving and mixing in one step?
354void AudioBuffer::DeinterleaveFrom(AudioFrame* frame) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000355 assert(proc_num_frames_ == input_num_frames_);
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000356 assert(frame->num_channels_ == num_input_channels_);
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000357 assert(frame->samples_per_channel_ == proc_num_frames_);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000358 InitForNewData();
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000359 activity_ = frame->vad_activity_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000360
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000361 if (num_input_channels_ == 2 && num_proc_channels_ == 1) {
362 // Downmix directly; no explicit deinterleaving needed.
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000363 int16_t* downmixed = data_->ibuf()->channels()[0];
364 for (int i = 0; i < input_num_frames_; ++i) {
andrew@webrtc.org8328e7c2014-10-31 04:58:14 +0000365 downmixed[i] = (frame->data_[i * 2] + frame->data_[i * 2 + 1]) / 2;
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000366 }
367 } else {
368 assert(num_proc_channels_ == num_input_channels_);
369 int16_t* interleaved = frame->data_;
370 for (int i = 0; i < num_proc_channels_; ++i) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000371 int16_t* deinterleaved = data_->ibuf()->channels()[i];
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000372 int interleaved_idx = i;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000373 for (int j = 0; j < proc_num_frames_; ++j) {
andrew@webrtc.org30be8272014-09-24 20:06:23 +0000374 deinterleaved[j] = interleaved[interleaved_idx];
375 interleaved_idx += num_proc_channels_;
376 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000377 }
378 }
379}
380
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000381void AudioBuffer::InterleaveTo(AudioFrame* frame, bool data_changed) const {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000382 assert(proc_num_frames_ == output_num_frames_);
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000383 assert(num_channels_ == num_input_channels_);
384 assert(frame->num_channels_ == num_channels_);
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000385 assert(frame->samples_per_channel_ == proc_num_frames_);
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000386 frame->vad_activity_ = activity_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000387
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000388 if (!data_changed) {
389 return;
390 }
391
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000392 int16_t* interleaved = frame->data_;
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000393 for (int i = 0; i < num_channels_; i++) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000394 int16_t* deinterleaved = data_->ibuf()->channels()[i];
andrew@webrtc.orged083d42011-09-19 15:28:51 +0000395 int interleaved_idx = i;
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000396 for (int j = 0; j < proc_num_frames_; j++) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000397 interleaved[interleaved_idx] = deinterleaved[j];
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000398 interleaved_idx += num_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000399 }
400 }
401}
402
niklase@google.com470e71d2011-07-07 08:21:25 +0000403void AudioBuffer::CopyLowPassToReference() {
404 reference_copied_ = true;
aluebs@webrtc.org27d106b2014-12-11 17:09:21 +0000405 if (!low_pass_reference_channels_.get() ||
406 low_pass_reference_channels_->num_channels() != num_channels_) {
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000407 low_pass_reference_channels_.reset(
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000408 new ChannelBuffer<int16_t>(num_split_frames_,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000409 num_proc_channels_));
410 }
411 for (int i = 0; i < num_proc_channels_; i++) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000412 memcpy(low_pass_reference_channels_->channels()[i],
413 split_bands_const(i)[kBand0To8kHz],
414 low_pass_reference_channels_->num_frames_per_band() *
415 sizeof(split_bands_const(i)[kBand0To8kHz][0]));
niklase@google.com470e71d2011-07-07 08:21:25 +0000416 }
417}
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000418
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000419void AudioBuffer::SplitIntoFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000420 splitting_filter_->Analysis(data_.get(), split_data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000421}
422
423void AudioBuffer::MergeFrequencyBands() {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000424 splitting_filter_->Synthesis(split_data_.get(), data_.get());
aluebs@webrtc.orgbe05c742014-11-14 22:18:10 +0000425}
426
niklase@google.com470e71d2011-07-07 08:21:25 +0000427} // namespace webrtc