Home | History | Annotate | Download | only in audio_processing
      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