OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/audio_processing/audio_buffer.h" | 11 #include "webrtc/modules/audio_processing/audio_buffer.h" |
12 | 12 |
13 #include "webrtc/common_audio/include/audio_util.h" | 13 #include "webrtc/common_audio/include/audio_util.h" |
14 #include "webrtc/common_audio/resampler/push_sinc_resampler.h" | 14 #include "webrtc/common_audio/resampler/push_sinc_resampler.h" |
15 #include "webrtc/common_audio/signal_processing/include/signal_processing_librar
y.h" | 15 #include "webrtc/common_audio/signal_processing/include/signal_processing_librar
y.h" |
16 #include "webrtc/common_audio/channel_buffer.h" | 16 #include "webrtc/common_audio/channel_buffer.h" |
17 #include "webrtc/modules/audio_processing/common.h" | 17 #include "webrtc/modules/audio_processing/common.h" |
18 | 18 |
19 namespace webrtc { | 19 namespace webrtc { |
20 namespace { | 20 namespace { |
21 | 21 |
22 const int kSamplesPer16kHzChannel = 160; | 22 const int kSamplesPer16kHzChannel = 160; |
23 const int kSamplesPer32kHzChannel = 320; | 23 const int kSamplesPer32kHzChannel = 320; |
24 const int kSamplesPer48kHzChannel = 480; | 24 const int kSamplesPer48kHzChannel = 480; |
25 | 25 |
26 int KeyboardChannelIndex(const StreamConfig& stream_config) { | 26 bool HasKeyboardChannel(AudioProcessing::ChannelLayout layout) { |
27 if (!stream_config.has_keyboard()) { | 27 switch (layout) { |
28 assert(false); | 28 case AudioProcessing::kMono: |
29 return -1; | 29 case AudioProcessing::kStereo: |
| 30 return false; |
| 31 case AudioProcessing::kMonoAndKeyboard: |
| 32 case AudioProcessing::kStereoAndKeyboard: |
| 33 return true; |
30 } | 34 } |
| 35 assert(false); |
| 36 return false; |
| 37 } |
31 | 38 |
32 return stream_config.num_channels(); | 39 int KeyboardChannelIndex(AudioProcessing::ChannelLayout layout) { |
| 40 switch (layout) { |
| 41 case AudioProcessing::kMono: |
| 42 case AudioProcessing::kStereo: |
| 43 assert(false); |
| 44 return -1; |
| 45 case AudioProcessing::kMonoAndKeyboard: |
| 46 return 1; |
| 47 case AudioProcessing::kStereoAndKeyboard: |
| 48 return 2; |
| 49 } |
| 50 assert(false); |
| 51 return -1; |
| 52 } |
| 53 |
| 54 template <typename T> |
| 55 void StereoToMono(const T* left, const T* right, T* out, |
| 56 int num_frames) { |
| 57 for (int i = 0; i < num_frames; ++i) |
| 58 out[i] = (left[i] + right[i]) / 2; |
33 } | 59 } |
34 | 60 |
35 int NumBandsFromSamplesPerChannel(int num_frames) { | 61 int NumBandsFromSamplesPerChannel(int num_frames) { |
36 int num_bands = 1; | 62 int num_bands = 1; |
37 if (num_frames == kSamplesPer32kHzChannel || | 63 if (num_frames == kSamplesPer32kHzChannel || |
38 num_frames == kSamplesPer48kHzChannel) { | 64 num_frames == kSamplesPer48kHzChannel) { |
39 num_bands = rtc::CheckedDivExact(num_frames, | 65 num_bands = rtc::CheckedDivExact(num_frames, |
40 static_cast<int>(kSamplesPer16kHzChannel)); | 66 static_cast<int>(kSamplesPer16kHzChannel)); |
41 } | 67 } |
42 return num_bands; | 68 return num_bands; |
(...skipping 15 matching lines...) Expand all Loading... |
58 num_bands_(NumBandsFromSamplesPerChannel(proc_num_frames_)), | 84 num_bands_(NumBandsFromSamplesPerChannel(proc_num_frames_)), |
59 num_split_frames_(rtc::CheckedDivExact(proc_num_frames_, num_bands_)), | 85 num_split_frames_(rtc::CheckedDivExact(proc_num_frames_, num_bands_)), |
60 mixed_low_pass_valid_(false), | 86 mixed_low_pass_valid_(false), |
61 reference_copied_(false), | 87 reference_copied_(false), |
62 activity_(AudioFrame::kVadUnknown), | 88 activity_(AudioFrame::kVadUnknown), |
63 keyboard_data_(NULL), | 89 keyboard_data_(NULL), |
64 data_(new IFChannelBuffer(proc_num_frames_, num_proc_channels_)) { | 90 data_(new IFChannelBuffer(proc_num_frames_, num_proc_channels_)) { |
65 assert(input_num_frames_ > 0); | 91 assert(input_num_frames_ > 0); |
66 assert(proc_num_frames_ > 0); | 92 assert(proc_num_frames_ > 0); |
67 assert(output_num_frames_ > 0); | 93 assert(output_num_frames_ > 0); |
68 assert(num_input_channels_ > 0); | 94 assert(num_input_channels_ > 0 && num_input_channels_ <= 2); |
69 assert(num_proc_channels_ > 0 && num_proc_channels_ <= num_input_channels_); | 95 assert(num_proc_channels_ > 0 && num_proc_channels_ <= num_input_channels_); |
70 | 96 |
71 if (input_num_frames_ != proc_num_frames_ || | 97 if (input_num_frames_ != proc_num_frames_ || |
72 output_num_frames_ != proc_num_frames_) { | 98 output_num_frames_ != proc_num_frames_) { |
73 // Create an intermediate buffer for resampling. | 99 // Create an intermediate buffer for resampling. |
74 process_buffer_.reset(new ChannelBuffer<float>(proc_num_frames_, | 100 process_buffer_.reset(new ChannelBuffer<float>(proc_num_frames_, |
75 num_proc_channels_)); | 101 num_proc_channels_)); |
76 | 102 |
77 if (input_num_frames_ != proc_num_frames_) { | 103 if (input_num_frames_ != proc_num_frames_) { |
78 for (int i = 0; i < num_proc_channels_; ++i) { | 104 for (int i = 0; i < num_proc_channels_; ++i) { |
(...skipping 18 matching lines...) Expand all Loading... |
97 num_bands_)); | 123 num_bands_)); |
98 splitting_filter_.reset(new SplittingFilter(num_proc_channels_, | 124 splitting_filter_.reset(new SplittingFilter(num_proc_channels_, |
99 num_bands_, | 125 num_bands_, |
100 proc_num_frames_)); | 126 proc_num_frames_)); |
101 } | 127 } |
102 } | 128 } |
103 | 129 |
104 AudioBuffer::~AudioBuffer() {} | 130 AudioBuffer::~AudioBuffer() {} |
105 | 131 |
106 void AudioBuffer::CopyFrom(const float* const* data, | 132 void AudioBuffer::CopyFrom(const float* const* data, |
107 const StreamConfig& stream_config) { | 133 int num_frames, |
108 assert(stream_config.num_frames() == input_num_frames_); | 134 AudioProcessing::ChannelLayout layout) { |
109 assert(stream_config.num_channels() == num_input_channels_); | 135 assert(num_frames == input_num_frames_); |
| 136 assert(ChannelsFromLayout(layout) == num_input_channels_); |
110 InitForNewData(); | 137 InitForNewData(); |
111 // Initialized lazily because there's a different condition in | 138 // Initialized lazily because there's a different condition in |
112 // DeinterleaveFrom. | 139 // DeinterleaveFrom. |
113 const bool need_to_downmix = | 140 if ((num_input_channels_ == 2 && num_proc_channels_ == 1) && !input_buffer_) { |
114 num_input_channels_ > 1 && num_proc_channels_ == 1; | |
115 if (need_to_downmix && !input_buffer_) { | |
116 input_buffer_.reset( | 141 input_buffer_.reset( |
117 new IFChannelBuffer(input_num_frames_, num_proc_channels_)); | 142 new IFChannelBuffer(input_num_frames_, num_proc_channels_)); |
118 } | 143 } |
119 | 144 |
120 if (stream_config.has_keyboard()) { | 145 if (HasKeyboardChannel(layout)) { |
121 keyboard_data_ = data[KeyboardChannelIndex(stream_config)]; | 146 keyboard_data_ = data[KeyboardChannelIndex(layout)]; |
122 } | 147 } |
123 | 148 |
124 // Downmix. | 149 // Downmix. |
125 const float* const* data_ptr = data; | 150 const float* const* data_ptr = data; |
126 if (need_to_downmix) { | 151 if (num_input_channels_ == 2 && num_proc_channels_ == 1) { |
127 DownmixToMono<float, float>(data, input_num_frames_, num_input_channels_, | 152 StereoToMono(data[0], |
128 input_buffer_->fbuf()->channels()[0]); | 153 data[1], |
| 154 input_buffer_->fbuf()->channels()[0], |
| 155 input_num_frames_); |
129 data_ptr = input_buffer_->fbuf_const()->channels(); | 156 data_ptr = input_buffer_->fbuf_const()->channels(); |
130 } | 157 } |
131 | 158 |
132 // Resample. | 159 // Resample. |
133 if (input_num_frames_ != proc_num_frames_) { | 160 if (input_num_frames_ != proc_num_frames_) { |
134 for (int i = 0; i < num_proc_channels_; ++i) { | 161 for (int i = 0; i < num_proc_channels_; ++i) { |
135 input_resamplers_[i]->Resample(data_ptr[i], | 162 input_resamplers_[i]->Resample(data_ptr[i], |
136 input_num_frames_, | 163 input_num_frames_, |
137 process_buffer_->channels()[i], | 164 process_buffer_->channels()[i], |
138 proc_num_frames_); | 165 proc_num_frames_); |
139 } | 166 } |
140 data_ptr = process_buffer_->channels(); | 167 data_ptr = process_buffer_->channels(); |
141 } | 168 } |
142 | 169 |
143 // Convert to the S16 range. | 170 // Convert to the S16 range. |
144 for (int i = 0; i < num_proc_channels_; ++i) { | 171 for (int i = 0; i < num_proc_channels_; ++i) { |
145 FloatToFloatS16(data_ptr[i], | 172 FloatToFloatS16(data_ptr[i], |
146 proc_num_frames_, | 173 proc_num_frames_, |
147 data_->fbuf()->channels()[i]); | 174 data_->fbuf()->channels()[i]); |
148 } | 175 } |
149 } | 176 } |
150 | 177 |
151 void AudioBuffer::CopyTo(const StreamConfig& stream_config, | 178 void AudioBuffer::CopyTo(int num_frames, |
| 179 AudioProcessing::ChannelLayout layout, |
152 float* const* data) { | 180 float* const* data) { |
153 assert(stream_config.num_frames() == output_num_frames_); | 181 assert(num_frames == output_num_frames_); |
154 assert(stream_config.num_channels() == num_channels_); | 182 assert(ChannelsFromLayout(layout) == num_channels_); |
155 | 183 |
156 // Convert to the float range. | 184 // Convert to the float range. |
157 float* const* data_ptr = data; | 185 float* const* data_ptr = data; |
158 if (output_num_frames_ != proc_num_frames_) { | 186 if (output_num_frames_ != proc_num_frames_) { |
159 // Convert to an intermediate buffer for subsequent resampling. | 187 // Convert to an intermediate buffer for subsequent resampling. |
160 data_ptr = process_buffer_->channels(); | 188 data_ptr = process_buffer_->channels(); |
161 } | 189 } |
162 for (int i = 0; i < num_channels_; ++i) { | 190 for (int i = 0; i < num_channels_; ++i) { |
163 FloatS16ToFloat(data_->fbuf()->channels()[i], | 191 FloatS16ToFloat(data_->fbuf()->channels()[i], |
164 proc_num_frames_, | 192 proc_num_frames_, |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 ChannelBuffer<float>* AudioBuffer::split_data_f() { | 320 ChannelBuffer<float>* AudioBuffer::split_data_f() { |
293 mixed_low_pass_valid_ = false; | 321 mixed_low_pass_valid_ = false; |
294 return split_data_.get() ? split_data_->fbuf() : data_->fbuf(); | 322 return split_data_.get() ? split_data_->fbuf() : data_->fbuf(); |
295 } | 323 } |
296 | 324 |
297 const ChannelBuffer<float>* AudioBuffer::split_data_f() const { | 325 const ChannelBuffer<float>* AudioBuffer::split_data_f() const { |
298 return split_data_.get() ? split_data_->fbuf_const() : data_->fbuf_const(); | 326 return split_data_.get() ? split_data_->fbuf_const() : data_->fbuf_const(); |
299 } | 327 } |
300 | 328 |
301 const int16_t* AudioBuffer::mixed_low_pass_data() { | 329 const int16_t* AudioBuffer::mixed_low_pass_data() { |
| 330 // Currently only mixing stereo to mono is supported. |
| 331 assert(num_proc_channels_ == 1 || num_proc_channels_ == 2); |
| 332 |
302 if (num_proc_channels_ == 1) { | 333 if (num_proc_channels_ == 1) { |
303 return split_bands_const(0)[kBand0To8kHz]; | 334 return split_bands_const(0)[kBand0To8kHz]; |
304 } | 335 } |
305 | 336 |
306 if (!mixed_low_pass_valid_) { | 337 if (!mixed_low_pass_valid_) { |
307 if (!mixed_low_pass_channels_.get()) { | 338 if (!mixed_low_pass_channels_.get()) { |
308 mixed_low_pass_channels_.reset( | 339 mixed_low_pass_channels_.reset( |
309 new ChannelBuffer<int16_t>(num_split_frames_, 1)); | 340 new ChannelBuffer<int16_t>(num_split_frames_, 1)); |
310 } | 341 } |
311 | 342 StereoToMono(split_bands_const(0)[kBand0To8kHz], |
312 DownmixToMono<int16_t, int32_t>(split_channels_const(kBand0To8kHz), | 343 split_bands_const(1)[kBand0To8kHz], |
313 num_split_frames_, num_channels_, | 344 mixed_low_pass_channels_->channels()[0], |
314 mixed_low_pass_channels_->channels()[0]); | 345 num_split_frames_); |
315 mixed_low_pass_valid_ = true; | 346 mixed_low_pass_valid_ = true; |
316 } | 347 } |
317 return mixed_low_pass_channels_->channels()[0]; | 348 return mixed_low_pass_channels_->channels()[0]; |
318 } | 349 } |
319 | 350 |
320 const int16_t* AudioBuffer::low_pass_reference(int channel) const { | 351 const int16_t* AudioBuffer::low_pass_reference(int channel) const { |
321 if (!reference_copied_) { | 352 if (!reference_copied_) { |
322 return NULL; | 353 return NULL; |
323 } | 354 } |
324 | 355 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
373 new IFChannelBuffer(input_num_frames_, num_proc_channels_)); | 404 new IFChannelBuffer(input_num_frames_, num_proc_channels_)); |
374 } | 405 } |
375 activity_ = frame->vad_activity_; | 406 activity_ = frame->vad_activity_; |
376 | 407 |
377 int16_t* const* deinterleaved; | 408 int16_t* const* deinterleaved; |
378 if (input_num_frames_ == proc_num_frames_) { | 409 if (input_num_frames_ == proc_num_frames_) { |
379 deinterleaved = data_->ibuf()->channels(); | 410 deinterleaved = data_->ibuf()->channels(); |
380 } else { | 411 } else { |
381 deinterleaved = input_buffer_->ibuf()->channels(); | 412 deinterleaved = input_buffer_->ibuf()->channels(); |
382 } | 413 } |
383 if (num_proc_channels_ == 1) { | 414 if (num_input_channels_ == 2 && num_proc_channels_ == 1) { |
384 // Downmix and deinterleave simultaneously. | 415 // Downmix directly; no explicit deinterleaving needed. |
385 DownmixInterleavedToMono(frame->data_, input_num_frames_, | 416 for (int i = 0; i < input_num_frames_; ++i) { |
386 num_input_channels_, deinterleaved[0]); | 417 deinterleaved[0][i] = (frame->data_[i * 2] + frame->data_[i * 2 + 1]) / 2; |
| 418 } |
387 } else { | 419 } else { |
388 assert(num_proc_channels_ == num_input_channels_); | 420 assert(num_proc_channels_ == num_input_channels_); |
389 Deinterleave(frame->data_, | 421 Deinterleave(frame->data_, |
390 input_num_frames_, | 422 input_num_frames_, |
391 num_proc_channels_, | 423 num_proc_channels_, |
392 deinterleaved); | 424 deinterleaved); |
393 } | 425 } |
394 | 426 |
395 // Resample. | 427 // Resample. |
396 if (input_num_frames_ != proc_num_frames_) { | 428 if (input_num_frames_ != proc_num_frames_) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 | 470 |
439 void AudioBuffer::SplitIntoFrequencyBands() { | 471 void AudioBuffer::SplitIntoFrequencyBands() { |
440 splitting_filter_->Analysis(data_.get(), split_data_.get()); | 472 splitting_filter_->Analysis(data_.get(), split_data_.get()); |
441 } | 473 } |
442 | 474 |
443 void AudioBuffer::MergeFrequencyBands() { | 475 void AudioBuffer::MergeFrequencyBands() { |
444 splitting_filter_->Synthesis(split_data_.get(), data_.get()); | 476 splitting_filter_->Synthesis(split_data_.get(), data_.get()); |
445 } | 477 } |
446 | 478 |
447 } // namespace webrtc | 479 } // namespace webrtc |
OLD | NEW |