1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 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 11 #include "webrtc/modules/audio_processing/audio_processing_impl.h" 12 13 #include <assert.h> 14 15 #include "webrtc/base/platform_file.h" 16 #include "webrtc/common_audio/include/audio_util.h" 17 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" 18 #include "webrtc/modules/audio_processing/audio_buffer.h" 19 #include "webrtc/modules/audio_processing/common.h" 20 #include "webrtc/modules/audio_processing/echo_cancellation_impl.h" 21 #include "webrtc/modules/audio_processing/echo_control_mobile_impl.h" 22 #include "webrtc/modules/audio_processing/gain_control_impl.h" 23 #include "webrtc/modules/audio_processing/high_pass_filter_impl.h" 24 #include "webrtc/modules/audio_processing/level_estimator_impl.h" 25 #include "webrtc/modules/audio_processing/noise_suppression_impl.h" 26 #include "webrtc/modules/audio_processing/processing_component.h" 27 #include "webrtc/modules/audio_processing/voice_detection_impl.h" 28 #include "webrtc/modules/interface/module_common_types.h" 29 #include "webrtc/system_wrappers/interface/compile_assert.h" 30 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 31 #include "webrtc/system_wrappers/interface/file_wrapper.h" 32 #include "webrtc/system_wrappers/interface/logging.h" 33 34 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP 35 // Files generated at build-time by the protobuf compiler. 36 #ifdef WEBRTC_ANDROID_PLATFORM_BUILD 37 #include "external/webrtc/webrtc/modules/audio_processing/debug.pb.h" 38 #else 39 #include "webrtc/audio_processing/debug.pb.h" 40 #endif 41 #endif // WEBRTC_AUDIOPROC_DEBUG_DUMP 42 43 #define RETURN_ON_ERR(expr) \ 44 do { \ 45 int err = expr; \ 46 if (err != kNoError) { \ 47 return err; \ 48 } \ 49 } while (0) 50 51 namespace webrtc { 52 53 // Throughout webrtc, it's assumed that success is represented by zero. 54 COMPILE_ASSERT(AudioProcessing::kNoError == 0, no_error_must_be_zero); 55 56 AudioProcessing* AudioProcessing::Create(int id) { 57 return Create(); 58 } 59 60 AudioProcessing* AudioProcessing::Create() { 61 Config config; 62 return Create(config); 63 } 64 65 AudioProcessing* AudioProcessing::Create(const Config& config) { 66 AudioProcessingImpl* apm = new AudioProcessingImpl(config); 67 if (apm->Initialize() != kNoError) { 68 delete apm; 69 apm = NULL; 70 } 71 72 return apm; 73 } 74 75 AudioProcessingImpl::AudioProcessingImpl(const Config& config) 76 : echo_cancellation_(NULL), 77 echo_control_mobile_(NULL), 78 gain_control_(NULL), 79 high_pass_filter_(NULL), 80 level_estimator_(NULL), 81 noise_suppression_(NULL), 82 voice_detection_(NULL), 83 crit_(CriticalSectionWrapper::CreateCriticalSection()), 84 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP 85 debug_file_(FileWrapper::Create()), 86 event_msg_(new audioproc::Event()), 87 #endif 88 fwd_in_format_(kSampleRate16kHz, 1), 89 fwd_proc_format_(kSampleRate16kHz, 1), 90 fwd_out_format_(kSampleRate16kHz), 91 rev_in_format_(kSampleRate16kHz, 1), 92 rev_proc_format_(kSampleRate16kHz, 1), 93 split_rate_(kSampleRate16kHz), 94 stream_delay_ms_(0), 95 delay_offset_ms_(0), 96 was_stream_delay_set_(false), 97 output_will_be_muted_(false), 98 key_pressed_(false) { 99 echo_cancellation_ = new EchoCancellationImpl(this, crit_); 100 component_list_.push_back(echo_cancellation_); 101 102 echo_control_mobile_ = new EchoControlMobileImpl(this, crit_); 103 component_list_.push_back(echo_control_mobile_); 104 105 gain_control_ = new GainControlImpl(this, crit_); 106 component_list_.push_back(gain_control_); 107 108 high_pass_filter_ = new HighPassFilterImpl(this, crit_); 109 component_list_.push_back(high_pass_filter_); 110 111 level_estimator_ = new LevelEstimatorImpl(this, crit_); 112 component_list_.push_back(level_estimator_); 113 114 noise_suppression_ = new NoiseSuppressionImpl(this, crit_); 115 component_list_.push_back(noise_suppression_); 116 117 voice_detection_ = new VoiceDetectionImpl(this, crit_); 118 component_list_.push_back(voice_detection_); 119 120 SetExtraOptions(config); 121 } 122 123 AudioProcessingImpl::~AudioProcessingImpl() { 124 { 125 CriticalSectionScoped crit_scoped(crit_); 126 while (!component_list_.empty()) { 127 ProcessingComponent* component = component_list_.front(); 128 component->Destroy(); 129 delete component; 130 component_list_.pop_front(); 131 } 132 133 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP 134 if (debug_file_->Open()) { 135 debug_file_->CloseFile(); 136 } 137 #endif 138 } 139 delete crit_; 140 crit_ = NULL; 141 } 142 143 int AudioProcessingImpl::Initialize() { 144 CriticalSectionScoped crit_scoped(crit_); 145 return InitializeLocked(); 146 } 147 148 int AudioProcessingImpl::set_sample_rate_hz(int rate) { 149 CriticalSectionScoped crit_scoped(crit_); 150 return InitializeLocked(rate, 151 rate, 152 rev_in_format_.rate(), 153 fwd_in_format_.num_channels(), 154 fwd_proc_format_.num_channels(), 155 rev_in_format_.num_channels()); 156 } 157 158 int AudioProcessingImpl::Initialize(int input_sample_rate_hz, 159 int output_sample_rate_hz, 160 int reverse_sample_rate_hz, 161 ChannelLayout input_layout, 162 ChannelLayout output_layout, 163 ChannelLayout reverse_layout) { 164 CriticalSectionScoped crit_scoped(crit_); 165 return InitializeLocked(input_sample_rate_hz, 166 output_sample_rate_hz, 167 reverse_sample_rate_hz, 168 ChannelsFromLayout(input_layout), 169 ChannelsFromLayout(output_layout), 170 ChannelsFromLayout(reverse_layout)); 171 } 172 173 int AudioProcessingImpl::InitializeLocked() { 174 render_audio_.reset(new AudioBuffer(rev_in_format_.samples_per_channel(), 175 rev_in_format_.num_channels(), 176 rev_proc_format_.samples_per_channel(), 177 rev_proc_format_.num_channels(), 178 rev_proc_format_.samples_per_channel())); 179 capture_audio_.reset(new AudioBuffer(fwd_in_format_.samples_per_channel(), 180 fwd_in_format_.num_channels(), 181 fwd_proc_format_.samples_per_channel(), 182 fwd_proc_format_.num_channels(), 183 fwd_out_format_.samples_per_channel())); 184 185 // Initialize all components. 186 std::list<ProcessingComponent*>::iterator it; 187 for (it = component_list_.begin(); it != component_list_.end(); ++it) { 188 int err = (*it)->Initialize(); 189 if (err != kNoError) { 190 return err; 191 } 192 } 193 194 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP 195 if (debug_file_->Open()) { 196 int err = WriteInitMessage(); 197 if (err != kNoError) { 198 return err; 199 } 200 } 201 #endif 202 203 return kNoError; 204 } 205 206 int AudioProcessingImpl::InitializeLocked(int input_sample_rate_hz, 207 int output_sample_rate_hz, 208 int reverse_sample_rate_hz, 209 int num_input_channels, 210 int num_output_channels, 211 int num_reverse_channels) { 212 if (input_sample_rate_hz <= 0 || 213 output_sample_rate_hz <= 0 || 214 reverse_sample_rate_hz <= 0) { 215 return kBadSampleRateError; 216 } 217 if (num_output_channels > num_input_channels) { 218 return kBadNumberChannelsError; 219 } 220 // Only mono and stereo supported currently. 221 if (num_input_channels > 2 || num_input_channels < 1 || 222 num_output_channels > 2 || num_output_channels < 1 || 223 num_reverse_channels > 2 || num_reverse_channels < 1) { 224 return kBadNumberChannelsError; 225 } 226 227 fwd_in_format_.set(input_sample_rate_hz, num_input_channels); 228 fwd_out_format_.set(output_sample_rate_hz); 229 rev_in_format_.set(reverse_sample_rate_hz, num_reverse_channels); 230 231 // We process at the closest native rate >= min(input rate, output rate)... 232 int min_proc_rate = std::min(fwd_in_format_.rate(), fwd_out_format_.rate()); 233 int fwd_proc_rate; 234 if (min_proc_rate > kSampleRate16kHz) { 235 fwd_proc_rate = kSampleRate32kHz; 236 } else if (min_proc_rate > kSampleRate8kHz) { 237 fwd_proc_rate = kSampleRate16kHz; 238 } else { 239 fwd_proc_rate = kSampleRate8kHz; 240 } 241 // ...with one exception. 242 if (echo_control_mobile_->is_enabled() && min_proc_rate > kSampleRate16kHz) { 243 fwd_proc_rate = kSampleRate16kHz; 244 } 245 246 fwd_proc_format_.set(fwd_proc_rate, num_output_channels); 247 248 // We normally process the reverse stream at 16 kHz. Unless... 249 int rev_proc_rate = kSampleRate16kHz; 250 if (fwd_proc_format_.rate() == kSampleRate8kHz) { 251 // ...the forward stream is at 8 kHz. 252 rev_proc_rate = kSampleRate8kHz; 253 } else { 254 if (rev_in_format_.rate() == kSampleRate32kHz) { 255 // ...or the input is at 32 kHz, in which case we use the splitting 256 // filter rather than the resampler. 257 rev_proc_rate = kSampleRate32kHz; 258 } 259 } 260 261 // Always downmix the reverse stream to mono for analysis. This has been 262 // demonstrated to work well for AEC in most practical scenarios. 263 rev_proc_format_.set(rev_proc_rate, 1); 264 265 if (fwd_proc_format_.rate() == kSampleRate32kHz) { 266 split_rate_ = kSampleRate16kHz; 267 } else { 268 split_rate_ = fwd_proc_format_.rate(); 269 } 270 271 return InitializeLocked(); 272 } 273 274 // Calls InitializeLocked() if any of the audio parameters have changed from 275 // their current values. 276 int AudioProcessingImpl::MaybeInitializeLocked(int input_sample_rate_hz, 277 int output_sample_rate_hz, 278 int reverse_sample_rate_hz, 279 int num_input_channels, 280 int num_output_channels, 281 int num_reverse_channels) { 282 if (input_sample_rate_hz == fwd_in_format_.rate() && 283 output_sample_rate_hz == fwd_out_format_.rate() && 284 reverse_sample_rate_hz == rev_in_format_.rate() && 285 num_input_channels == fwd_in_format_.num_channels() && 286 num_output_channels == fwd_proc_format_.num_channels() && 287 num_reverse_channels == rev_in_format_.num_channels()) { 288 return kNoError; 289 } 290 291 return InitializeLocked(input_sample_rate_hz, 292 output_sample_rate_hz, 293 reverse_sample_rate_hz, 294 num_input_channels, 295 num_output_channels, 296 num_reverse_channels); 297 } 298 299 void AudioProcessingImpl::SetExtraOptions(const Config& config) { 300 CriticalSectionScoped crit_scoped(crit_); 301 std::list<ProcessingComponent*>::iterator it; 302 for (it = component_list_.begin(); it != component_list_.end(); ++it) 303 (*it)->SetExtraOptions(config); 304 } 305 306 int AudioProcessingImpl::input_sample_rate_hz() const { 307 CriticalSectionScoped crit_scoped(crit_); 308 return fwd_in_format_.rate(); 309 } 310 311 int AudioProcessingImpl::sample_rate_hz() const { 312 CriticalSectionScoped crit_scoped(crit_); 313 return fwd_in_format_.rate(); 314 } 315 316 int AudioProcessingImpl::proc_sample_rate_hz() const { 317 return fwd_proc_format_.rate(); 318 } 319 320 int AudioProcessingImpl::proc_split_sample_rate_hz() const { 321 return split_rate_; 322 } 323 324 int AudioProcessingImpl::num_reverse_channels() const { 325 return rev_proc_format_.num_channels(); 326 } 327 328 int AudioProcessingImpl::num_input_channels() const { 329 return fwd_in_format_.num_channels(); 330 } 331 332 int AudioProcessingImpl::num_output_channels() const { 333 return fwd_proc_format_.num_channels(); 334 } 335 336 void AudioProcessingImpl::set_output_will_be_muted(bool muted) { 337 output_will_be_muted_ = muted; 338 } 339 340 bool AudioProcessingImpl::output_will_be_muted() const { 341 return output_will_be_muted_; 342 } 343 344 int AudioProcessingImpl::ProcessStream(const float* const* src, 345 int samples_per_channel, 346 int input_sample_rate_hz, 347 ChannelLayout input_layout, 348 int output_sample_rate_hz, 349 ChannelLayout output_layout, 350 float* const* dest) { 351 CriticalSectionScoped crit_scoped(crit_); 352 if (!src || !dest) { 353 return kNullPointerError; 354 } 355 356 RETURN_ON_ERR(MaybeInitializeLocked(input_sample_rate_hz, 357 output_sample_rate_hz, 358 rev_in_format_.rate(), 359 ChannelsFromLayout(input_layout), 360 ChannelsFromLayout(output_layout), 361 rev_in_format_.num_channels())); 362 if (samples_per_channel != fwd_in_format_.samples_per_channel()) { 363 return kBadDataLengthError; 364 } 365 366 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP 367 if (debug_file_->Open()) { 368 event_msg_->set_type(audioproc::Event::STREAM); 369 audioproc::Stream* msg = event_msg_->mutable_stream(); 370 const size_t channel_size = 371 sizeof(float) * fwd_in_format_.samples_per_channel(); 372 for (int i = 0; i < fwd_in_format_.num_channels(); ++i) 373 msg->add_input_channel(src[i], channel_size); 374 } 375 #endif 376 377 capture_audio_->CopyFrom(src, samples_per_channel, input_layout); 378 RETURN_ON_ERR(ProcessStreamLocked()); 379 if (output_copy_needed(is_data_processed())) { 380 capture_audio_->CopyTo(fwd_out_format_.samples_per_channel(), 381 output_layout, 382 dest); 383 } 384 385 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP 386 if (debug_file_->Open()) { 387 audioproc::Stream* msg = event_msg_->mutable_stream(); 388 const size_t channel_size = 389 sizeof(float) * fwd_out_format_.samples_per_channel(); 390 for (int i = 0; i < fwd_proc_format_.num_channels(); ++i) 391 msg->add_output_channel(dest[i], channel_size); 392 RETURN_ON_ERR(WriteMessageToDebugFile()); 393 } 394 #endif 395 396 return kNoError; 397 } 398 399 int AudioProcessingImpl::ProcessStream(AudioFrame* frame) { 400 CriticalSectionScoped crit_scoped(crit_); 401 if (!frame) { 402 return kNullPointerError; 403 } 404 // Must be a native rate. 405 if (frame->sample_rate_hz_ != kSampleRate8kHz && 406 frame->sample_rate_hz_ != kSampleRate16kHz && 407 frame->sample_rate_hz_ != kSampleRate32kHz) { 408 return kBadSampleRateError; 409 } 410 if (echo_control_mobile_->is_enabled() && 411 frame->sample_rate_hz_ > kSampleRate16kHz) { 412 LOG(LS_ERROR) << "AECM only supports 16 or 8 kHz sample rates"; 413 return kUnsupportedComponentError; 414 } 415 416 // TODO(ajm): The input and output rates and channels are currently 417 // constrained to be identical in the int16 interface. 418 RETURN_ON_ERR(MaybeInitializeLocked(frame->sample_rate_hz_, 419 frame->sample_rate_hz_, 420 rev_in_format_.rate(), 421 frame->num_channels_, 422 frame->num_channels_, 423 rev_in_format_.num_channels())); 424 if (frame->samples_per_channel_ != fwd_in_format_.samples_per_channel()) { 425 return kBadDataLengthError; 426 } 427 428 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP 429 if (debug_file_->Open()) { 430 event_msg_->set_type(audioproc::Event::STREAM); 431 audioproc::Stream* msg = event_msg_->mutable_stream(); 432 const size_t data_size = sizeof(int16_t) * 433 frame->samples_per_channel_ * 434 frame->num_channels_; 435 msg->set_input_data(frame->data_, data_size); 436 } 437 #endif 438 439 capture_audio_->DeinterleaveFrom(frame); 440 RETURN_ON_ERR(ProcessStreamLocked()); 441 capture_audio_->InterleaveTo(frame, output_copy_needed(is_data_processed())); 442 443 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP 444 if (debug_file_->Open()) { 445 audioproc::Stream* msg = event_msg_->mutable_stream(); 446 const size_t data_size = sizeof(int16_t) * 447 frame->samples_per_channel_ * 448 frame->num_channels_; 449 msg->set_output_data(frame->data_, data_size); 450 RETURN_ON_ERR(WriteMessageToDebugFile()); 451 } 452 #endif 453 454 return kNoError; 455 } 456 457 458 int AudioProcessingImpl::ProcessStreamLocked() { 459 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP 460 if (debug_file_->Open()) { 461 audioproc::Stream* msg = event_msg_->mutable_stream(); 462 msg->set_delay(stream_delay_ms_); 463 msg->set_drift(echo_cancellation_->stream_drift_samples()); 464 msg->set_level(gain_control_->stream_analog_level()); 465 msg->set_keypress(key_pressed_); 466 } 467 #endif 468 469 AudioBuffer* ca = capture_audio_.get(); // For brevity. 470 bool data_processed = is_data_processed(); 471 if (analysis_needed(data_processed)) { 472 for (int i = 0; i < fwd_proc_format_.num_channels(); i++) { 473 // Split into a low and high band. 474 WebRtcSpl_AnalysisQMF(ca->data(i), 475 ca->samples_per_channel(), 476 ca->low_pass_split_data(i), 477 ca->high_pass_split_data(i), 478 ca->filter_states(i)->analysis_filter_state1, 479 ca->filter_states(i)->analysis_filter_state2); 480 } 481 } 482 483 RETURN_ON_ERR(high_pass_filter_->ProcessCaptureAudio(ca)); 484 RETURN_ON_ERR(gain_control_->AnalyzeCaptureAudio(ca)); 485 RETURN_ON_ERR(noise_suppression_->AnalyzeCaptureAudio(ca)); 486 RETURN_ON_ERR(echo_cancellation_->ProcessCaptureAudio(ca)); 487 488 if (echo_control_mobile_->is_enabled() && noise_suppression_->is_enabled()) { 489 ca->CopyLowPassToReference(); 490 } 491 RETURN_ON_ERR(noise_suppression_->ProcessCaptureAudio(ca)); 492 RETURN_ON_ERR(echo_control_mobile_->ProcessCaptureAudio(ca)); 493 RETURN_ON_ERR(voice_detection_->ProcessCaptureAudio(ca)); 494 RETURN_ON_ERR(gain_control_->ProcessCaptureAudio(ca)); 495 496 if (synthesis_needed(data_processed)) { 497 for (int i = 0; i < fwd_proc_format_.num_channels(); i++) { 498 // Recombine low and high bands. 499 WebRtcSpl_SynthesisQMF(ca->low_pass_split_data(i), 500 ca->high_pass_split_data(i), 501 ca->samples_per_split_channel(), 502 ca->data(i), 503 ca->filter_states(i)->synthesis_filter_state1, 504 ca->filter_states(i)->synthesis_filter_state2); 505 } 506 } 507 508 // The level estimator operates on the recombined data. 509 RETURN_ON_ERR(level_estimator_->ProcessStream(ca)); 510 511 was_stream_delay_set_ = false; 512 return kNoError; 513 } 514 515 int AudioProcessingImpl::AnalyzeReverseStream(const float* const* data, 516 int samples_per_channel, 517 int sample_rate_hz, 518 ChannelLayout layout) { 519 CriticalSectionScoped crit_scoped(crit_); 520 if (data == NULL) { 521 return kNullPointerError; 522 } 523 524 const int num_channels = ChannelsFromLayout(layout); 525 RETURN_ON_ERR(MaybeInitializeLocked(fwd_in_format_.rate(), 526 fwd_out_format_.rate(), 527 sample_rate_hz, 528 fwd_in_format_.num_channels(), 529 fwd_proc_format_.num_channels(), 530 num_channels)); 531 if (samples_per_channel != rev_in_format_.samples_per_channel()) { 532 return kBadDataLengthError; 533 } 534 535 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP 536 if (debug_file_->Open()) { 537 event_msg_->set_type(audioproc::Event::REVERSE_STREAM); 538 audioproc::ReverseStream* msg = event_msg_->mutable_reverse_stream(); 539 const size_t channel_size = 540 sizeof(float) * rev_in_format_.samples_per_channel(); 541 for (int i = 0; i < num_channels; ++i) 542 msg->add_channel(data[i], channel_size); 543 RETURN_ON_ERR(WriteMessageToDebugFile()); 544 } 545 #endif 546 547 render_audio_->CopyFrom(data, samples_per_channel, layout); 548 return AnalyzeReverseStreamLocked(); 549 } 550 551 int AudioProcessingImpl::AnalyzeReverseStream(AudioFrame* frame) { 552 CriticalSectionScoped crit_scoped(crit_); 553 if (frame == NULL) { 554 return kNullPointerError; 555 } 556 // Must be a native rate. 557 if (frame->sample_rate_hz_ != kSampleRate8kHz && 558 frame->sample_rate_hz_ != kSampleRate16kHz && 559 frame->sample_rate_hz_ != kSampleRate32kHz) { 560 return kBadSampleRateError; 561 } 562 // This interface does not tolerate different forward and reverse rates. 563 if (frame->sample_rate_hz_ != fwd_in_format_.rate()) { 564 return kBadSampleRateError; 565 } 566 567 RETURN_ON_ERR(MaybeInitializeLocked(fwd_in_format_.rate(), 568 fwd_out_format_.rate(), 569 frame->sample_rate_hz_, 570 fwd_in_format_.num_channels(), 571 fwd_in_format_.num_channels(), 572 frame->num_channels_)); 573 if (frame->samples_per_channel_ != rev_in_format_.samples_per_channel()) { 574 return kBadDataLengthError; 575 } 576 577 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP 578 if (debug_file_->Open()) { 579 event_msg_->set_type(audioproc::Event::REVERSE_STREAM); 580 audioproc::ReverseStream* msg = event_msg_->mutable_reverse_stream(); 581 const size_t data_size = sizeof(int16_t) * 582 frame->samples_per_channel_ * 583 frame->num_channels_; 584 msg->set_data(frame->data_, data_size); 585 RETURN_ON_ERR(WriteMessageToDebugFile()); 586 } 587 #endif 588 589 render_audio_->DeinterleaveFrom(frame); 590 return AnalyzeReverseStreamLocked(); 591 } 592 593 int AudioProcessingImpl::AnalyzeReverseStreamLocked() { 594 AudioBuffer* ra = render_audio_.get(); // For brevity. 595 if (rev_proc_format_.rate() == kSampleRate32kHz) { 596 for (int i = 0; i < rev_proc_format_.num_channels(); i++) { 597 // Split into low and high band. 598 WebRtcSpl_AnalysisQMF(ra->data(i), 599 ra->samples_per_channel(), 600 ra->low_pass_split_data(i), 601 ra->high_pass_split_data(i), 602 ra->filter_states(i)->analysis_filter_state1, 603 ra->filter_states(i)->analysis_filter_state2); 604 } 605 } 606 607 RETURN_ON_ERR(echo_cancellation_->ProcessRenderAudio(ra)); 608 RETURN_ON_ERR(echo_control_mobile_->ProcessRenderAudio(ra)); 609 RETURN_ON_ERR(gain_control_->ProcessRenderAudio(ra)); 610 611 return kNoError; 612 } 613 614 int AudioProcessingImpl::set_stream_delay_ms(int delay) { 615 Error retval = kNoError; 616 was_stream_delay_set_ = true; 617 delay += delay_offset_ms_; 618 619 if (delay < 0) { 620 delay = 0; 621 retval = kBadStreamParameterWarning; 622 } 623 624 // TODO(ajm): the max is rather arbitrarily chosen; investigate. 625 if (delay > 500) { 626 delay = 500; 627 retval = kBadStreamParameterWarning; 628 } 629 630 stream_delay_ms_ = delay; 631 return retval; 632 } 633 634 int AudioProcessingImpl::stream_delay_ms() const { 635 return stream_delay_ms_; 636 } 637 638 bool AudioProcessingImpl::was_stream_delay_set() const { 639 return was_stream_delay_set_; 640 } 641 642 void AudioProcessingImpl::set_stream_key_pressed(bool key_pressed) { 643 key_pressed_ = key_pressed; 644 } 645 646 bool AudioProcessingImpl::stream_key_pressed() const { 647 return key_pressed_; 648 } 649 650 void AudioProcessingImpl::set_delay_offset_ms(int offset) { 651 CriticalSectionScoped crit_scoped(crit_); 652 delay_offset_ms_ = offset; 653 } 654 655 int AudioProcessingImpl::delay_offset_ms() const { 656 return delay_offset_ms_; 657 } 658 659 int AudioProcessingImpl::StartDebugRecording( 660 const char filename[AudioProcessing::kMaxFilenameSize]) { 661 CriticalSectionScoped crit_scoped(crit_); 662 assert(kMaxFilenameSize == FileWrapper::kMaxFileNameSize); 663 664 if (filename == NULL) { 665 return kNullPointerError; 666 } 667 668 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP 669 // Stop any ongoing recording. 670 if (debug_file_->Open()) { 671 if (debug_file_->CloseFile() == -1) { 672 return kFileError; 673 } 674 } 675 676 if (debug_file_->OpenFile(filename, false) == -1) { 677 debug_file_->CloseFile(); 678 return kFileError; 679 } 680 681 int err = WriteInitMessage(); 682 if (err != kNoError) { 683 return err; 684 } 685 return kNoError; 686 #else 687 return kUnsupportedFunctionError; 688 #endif // WEBRTC_AUDIOPROC_DEBUG_DUMP 689 } 690 691 int AudioProcessingImpl::StartDebugRecording(FILE* handle) { 692 CriticalSectionScoped crit_scoped(crit_); 693 694 if (handle == NULL) { 695 return kNullPointerError; 696 } 697 698 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP 699 // Stop any ongoing recording. 700 if (debug_file_->Open()) { 701 if (debug_file_->CloseFile() == -1) { 702 return kFileError; 703 } 704 } 705 706 if (debug_file_->OpenFromFileHandle(handle, true, false) == -1) { 707 return kFileError; 708 } 709 710 int err = WriteInitMessage(); 711 if (err != kNoError) { 712 return err; 713 } 714 return kNoError; 715 #else 716 return kUnsupportedFunctionError; 717 #endif // WEBRTC_AUDIOPROC_DEBUG_DUMP 718 } 719 720 int AudioProcessingImpl::StartDebugRecordingForPlatformFile( 721 rtc::PlatformFile handle) { 722 FILE* stream = rtc::FdopenPlatformFileForWriting(handle); 723 return StartDebugRecording(stream); 724 } 725 726 int AudioProcessingImpl::StopDebugRecording() { 727 CriticalSectionScoped crit_scoped(crit_); 728 729 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP 730 // We just return if recording hasn't started. 731 if (debug_file_->Open()) { 732 if (debug_file_->CloseFile() == -1) { 733 return kFileError; 734 } 735 } 736 return kNoError; 737 #else 738 return kUnsupportedFunctionError; 739 #endif // WEBRTC_AUDIOPROC_DEBUG_DUMP 740 } 741 742 EchoCancellation* AudioProcessingImpl::echo_cancellation() const { 743 return echo_cancellation_; 744 } 745 746 EchoControlMobile* AudioProcessingImpl::echo_control_mobile() const { 747 return echo_control_mobile_; 748 } 749 750 GainControl* AudioProcessingImpl::gain_control() const { 751 return gain_control_; 752 } 753 754 HighPassFilter* AudioProcessingImpl::high_pass_filter() const { 755 return high_pass_filter_; 756 } 757 758 LevelEstimator* AudioProcessingImpl::level_estimator() const { 759 return level_estimator_; 760 } 761 762 NoiseSuppression* AudioProcessingImpl::noise_suppression() const { 763 return noise_suppression_; 764 } 765 766 VoiceDetection* AudioProcessingImpl::voice_detection() const { 767 return voice_detection_; 768 } 769 770 bool AudioProcessingImpl::is_data_processed() const { 771 int enabled_count = 0; 772 std::list<ProcessingComponent*>::const_iterator it; 773 for (it = component_list_.begin(); it != component_list_.end(); it++) { 774 if ((*it)->is_component_enabled()) { 775 enabled_count++; 776 } 777 } 778 779 // Data is unchanged if no components are enabled, or if only level_estimator_ 780 // or voice_detection_ is enabled. 781 if (enabled_count == 0) { 782 return false; 783 } else if (enabled_count == 1) { 784 if (level_estimator_->is_enabled() || voice_detection_->is_enabled()) { 785 return false; 786 } 787 } else if (enabled_count == 2) { 788 if (level_estimator_->is_enabled() && voice_detection_->is_enabled()) { 789 return false; 790 } 791 } 792 return true; 793 } 794 795 bool AudioProcessingImpl::output_copy_needed(bool is_data_processed) const { 796 // Check if we've upmixed or downmixed the audio. 797 return ((fwd_proc_format_.num_channels() != fwd_in_format_.num_channels()) || 798 is_data_processed); 799 } 800 801 bool AudioProcessingImpl::synthesis_needed(bool is_data_processed) const { 802 return (is_data_processed && fwd_proc_format_.rate() == kSampleRate32kHz); 803 } 804 805 bool AudioProcessingImpl::analysis_needed(bool is_data_processed) const { 806 if (!is_data_processed && !voice_detection_->is_enabled()) { 807 // Only level_estimator_ is enabled. 808 return false; 809 } else if (fwd_proc_format_.rate() == kSampleRate32kHz) { 810 // Something besides level_estimator_ is enabled, and we have super-wb. 811 return true; 812 } 813 return false; 814 } 815 816 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP 817 int AudioProcessingImpl::WriteMessageToDebugFile() { 818 int32_t size = event_msg_->ByteSize(); 819 if (size <= 0) { 820 return kUnspecifiedError; 821 } 822 #if defined(WEBRTC_ARCH_BIG_ENDIAN) 823 // TODO(ajm): Use little-endian "on the wire". For the moment, we can be 824 // pretty safe in assuming little-endian. 825 #endif 826 827 if (!event_msg_->SerializeToString(&event_str_)) { 828 return kUnspecifiedError; 829 } 830 831 // Write message preceded by its size. 832 if (!debug_file_->Write(&size, sizeof(int32_t))) { 833 return kFileError; 834 } 835 if (!debug_file_->Write(event_str_.data(), event_str_.length())) { 836 return kFileError; 837 } 838 839 event_msg_->Clear(); 840 841 return kNoError; 842 } 843 844 int AudioProcessingImpl::WriteInitMessage() { 845 event_msg_->set_type(audioproc::Event::INIT); 846 audioproc::Init* msg = event_msg_->mutable_init(); 847 msg->set_sample_rate(fwd_in_format_.rate()); 848 msg->set_num_input_channels(fwd_in_format_.num_channels()); 849 msg->set_num_output_channels(fwd_proc_format_.num_channels()); 850 msg->set_num_reverse_channels(rev_in_format_.num_channels()); 851 msg->set_reverse_sample_rate(rev_in_format_.rate()); 852 msg->set_output_sample_rate(fwd_out_format_.rate()); 853 854 int err = WriteMessageToDebugFile(); 855 if (err != kNoError) { 856 return err; 857 } 858 859 return kNoError; 860 } 861 #endif // WEBRTC_AUDIOPROC_DEBUG_DUMP 862 863 } // namespace webrtc 864