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/common_audio/include/audio_util.h"
     16 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
     17 #include "webrtc/modules/audio_processing/audio_buffer.h"
     18 #include "webrtc/modules/audio_processing/common.h"
     19 #include "webrtc/modules/audio_processing/echo_cancellation_impl.h"
     20 #include "webrtc/modules/audio_processing/echo_control_mobile_impl.h"
     21 #include "webrtc/modules/audio_processing/gain_control_impl.h"
     22 #include "webrtc/modules/audio_processing/high_pass_filter_impl.h"
     23 #include "webrtc/modules/audio_processing/level_estimator_impl.h"
     24 #include "webrtc/modules/audio_processing/noise_suppression_impl.h"
     25 #include "webrtc/modules/audio_processing/processing_component.h"
     26 #include "webrtc/modules/audio_processing/voice_detection_impl.h"
     27 #include "webrtc/modules/interface/module_common_types.h"
     28 #include "webrtc/system_wrappers/interface/compile_assert.h"
     29 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
     30 #include "webrtc/system_wrappers/interface/file_wrapper.h"
     31 #include "webrtc/system_wrappers/interface/logging.h"
     32 
     33 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
     34 // Files generated at build-time by the protobuf compiler.
     35 #ifdef WEBRTC_ANDROID_PLATFORM_BUILD
     36 #include "external/webrtc/webrtc/modules/audio_processing/debug.pb.h"
     37 #else
     38 #include "webrtc/audio_processing/debug.pb.h"
     39 #endif
     40 #endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
     41 
     42 #define RETURN_ON_ERR(expr)  \
     43   do {                       \
     44     int err = expr;          \
     45     if (err != kNoError) {   \
     46       return err;            \
     47     }                        \
     48   } while (0)
     49 
     50 namespace webrtc {
     51 
     52 // Throughout webrtc, it's assumed that success is represented by zero.
     53 COMPILE_ASSERT(AudioProcessing::kNoError == 0, no_error_must_be_zero);
     54 
     55 AudioProcessing* AudioProcessing::Create(int id) {
     56   return Create();
     57 }
     58 
     59 AudioProcessing* AudioProcessing::Create() {
     60   Config config;
     61   return Create(config);
     62 }
     63 
     64 AudioProcessing* AudioProcessing::Create(const Config& config) {
     65   AudioProcessingImpl* apm = new AudioProcessingImpl(config);
     66   if (apm->Initialize() != kNoError) {
     67     delete apm;
     68     apm = NULL;
     69   }
     70 
     71   return apm;
     72 }
     73 
     74 AudioProcessingImpl::AudioProcessingImpl(const Config& config)
     75     : echo_cancellation_(NULL),
     76       echo_control_mobile_(NULL),
     77       gain_control_(NULL),
     78       high_pass_filter_(NULL),
     79       level_estimator_(NULL),
     80       noise_suppression_(NULL),
     81       voice_detection_(NULL),
     82       crit_(CriticalSectionWrapper::CreateCriticalSection()),
     83 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
     84       debug_file_(FileWrapper::Create()),
     85       event_msg_(new audioproc::Event()),
     86 #endif
     87       fwd_in_format_(kSampleRate16kHz, 1),
     88       fwd_proc_format_(kSampleRate16kHz, 1),
     89       fwd_out_format_(kSampleRate16kHz),
     90       rev_in_format_(kSampleRate16kHz, 1),
     91       rev_proc_format_(kSampleRate16kHz, 1),
     92       split_rate_(kSampleRate16kHz),
     93       stream_delay_ms_(0),
     94       delay_offset_ms_(0),
     95       was_stream_delay_set_(false),
     96       output_will_be_muted_(false),
     97       key_pressed_(false) {
     98   echo_cancellation_ = new EchoCancellationImpl(this, crit_);
     99   component_list_.push_back(echo_cancellation_);
    100 
    101   echo_control_mobile_ = new EchoControlMobileImpl(this, crit_);
    102   component_list_.push_back(echo_control_mobile_);
    103 
    104   gain_control_ = new GainControlImpl(this, crit_);
    105   component_list_.push_back(gain_control_);
    106 
    107   high_pass_filter_ = new HighPassFilterImpl(this, crit_);
    108   component_list_.push_back(high_pass_filter_);
    109 
    110   level_estimator_ = new LevelEstimatorImpl(this, crit_);
    111   component_list_.push_back(level_estimator_);
    112 
    113   noise_suppression_ = new NoiseSuppressionImpl(this, crit_);
    114   component_list_.push_back(noise_suppression_);
    115 
    116   voice_detection_ = new VoiceDetectionImpl(this, crit_);
    117   component_list_.push_back(voice_detection_);
    118 
    119   SetExtraOptions(config);
    120 }
    121 
    122 AudioProcessingImpl::~AudioProcessingImpl() {
    123   {
    124     CriticalSectionScoped crit_scoped(crit_);
    125     while (!component_list_.empty()) {
    126       ProcessingComponent* component = component_list_.front();
    127       component->Destroy();
    128       delete component;
    129       component_list_.pop_front();
    130     }
    131 
    132 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
    133     if (debug_file_->Open()) {
    134       debug_file_->CloseFile();
    135     }
    136 #endif
    137   }
    138   delete crit_;
    139   crit_ = NULL;
    140 }
    141 
    142 int AudioProcessingImpl::Initialize() {
    143   CriticalSectionScoped crit_scoped(crit_);
    144   return InitializeLocked();
    145 }
    146 
    147 int AudioProcessingImpl::set_sample_rate_hz(int rate) {
    148   CriticalSectionScoped crit_scoped(crit_);
    149   return InitializeLocked(rate,
    150                           rate,
    151                           rev_in_format_.rate(),
    152                           fwd_in_format_.num_channels(),
    153                           fwd_proc_format_.num_channels(),
    154                           rev_in_format_.num_channels());
    155 }
    156 
    157 int AudioProcessingImpl::Initialize(int input_sample_rate_hz,
    158                                     int output_sample_rate_hz,
    159                                     int reverse_sample_rate_hz,
    160                                     ChannelLayout input_layout,
    161                                     ChannelLayout output_layout,
    162                                     ChannelLayout reverse_layout) {
    163   CriticalSectionScoped crit_scoped(crit_);
    164   return InitializeLocked(input_sample_rate_hz,
    165                           output_sample_rate_hz,
    166                           reverse_sample_rate_hz,
    167                           ChannelsFromLayout(input_layout),
    168                           ChannelsFromLayout(output_layout),
    169                           ChannelsFromLayout(reverse_layout));
    170 }
    171 
    172 int AudioProcessingImpl::InitializeLocked() {
    173   render_audio_.reset(new AudioBuffer(rev_in_format_.samples_per_channel(),
    174                                       rev_in_format_.num_channels(),
    175                                       rev_proc_format_.samples_per_channel(),
    176                                       rev_proc_format_.num_channels(),
    177                                       rev_proc_format_.samples_per_channel()));
    178   capture_audio_.reset(new AudioBuffer(fwd_in_format_.samples_per_channel(),
    179                                        fwd_in_format_.num_channels(),
    180                                        fwd_proc_format_.samples_per_channel(),
    181                                        fwd_proc_format_.num_channels(),
    182                                        fwd_out_format_.samples_per_channel()));
    183 
    184   // Initialize all components.
    185   std::list<ProcessingComponent*>::iterator it;
    186   for (it = component_list_.begin(); it != component_list_.end(); ++it) {
    187     int err = (*it)->Initialize();
    188     if (err != kNoError) {
    189       return err;
    190     }
    191   }
    192 
    193 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
    194   if (debug_file_->Open()) {
    195     int err = WriteInitMessage();
    196     if (err != kNoError) {
    197       return err;
    198     }
    199   }
    200 #endif
    201 
    202   return kNoError;
    203 }
    204 
    205 int AudioProcessingImpl::InitializeLocked(int input_sample_rate_hz,
    206                                           int output_sample_rate_hz,
    207                                           int reverse_sample_rate_hz,
    208                                           int num_input_channels,
    209                                           int num_output_channels,
    210                                           int num_reverse_channels) {
    211   if (input_sample_rate_hz <= 0 ||
    212       output_sample_rate_hz <= 0 ||
    213       reverse_sample_rate_hz <= 0) {
    214     return kBadSampleRateError;
    215   }
    216   if (num_output_channels > num_input_channels) {
    217     return kBadNumberChannelsError;
    218   }
    219   // Only mono and stereo supported currently.
    220   if (num_input_channels > 2 || num_input_channels < 1 ||
    221       num_output_channels > 2 || num_output_channels < 1 ||
    222       num_reverse_channels > 2 || num_reverse_channels < 1) {
    223     return kBadNumberChannelsError;
    224   }
    225 
    226   fwd_in_format_.set(input_sample_rate_hz, num_input_channels);
    227   fwd_out_format_.set(output_sample_rate_hz);
    228   rev_in_format_.set(reverse_sample_rate_hz, num_reverse_channels);
    229 
    230   // We process at the closest native rate >= min(input rate, output rate)...
    231   int min_proc_rate = std::min(fwd_in_format_.rate(), fwd_out_format_.rate());
    232   int fwd_proc_rate;
    233   if (min_proc_rate > kSampleRate16kHz) {
    234     fwd_proc_rate = kSampleRate32kHz;
    235   } else if (min_proc_rate > kSampleRate8kHz) {
    236     fwd_proc_rate = kSampleRate16kHz;
    237   } else {
    238     fwd_proc_rate = kSampleRate8kHz;
    239   }
    240   // ...with one exception.
    241   if (echo_control_mobile_->is_enabled() && min_proc_rate > kSampleRate16kHz) {
    242     fwd_proc_rate = kSampleRate16kHz;
    243   }
    244 
    245   fwd_proc_format_.set(fwd_proc_rate, num_output_channels);
    246 
    247   // We normally process the reverse stream at 16 kHz. Unless...
    248   int rev_proc_rate = kSampleRate16kHz;
    249   if (fwd_proc_format_.rate() == kSampleRate8kHz) {
    250     // ...the forward stream is at 8 kHz.
    251     rev_proc_rate = kSampleRate8kHz;
    252   } else {
    253     if (rev_in_format_.rate() == kSampleRate32kHz) {
    254       // ...or the input is at 32 kHz, in which case we use the splitting
    255       // filter rather than the resampler.
    256       rev_proc_rate = kSampleRate32kHz;
    257     }
    258   }
    259 
    260   // TODO(ajm): Enable this.
    261   // Always downmix the reverse stream to mono for analysis.
    262   //rev_proc_format_.set(rev_proc_rate, 1);
    263   rev_proc_format_.set(rev_proc_rate, rev_in_format_.num_channels());
    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::EnableExperimentalNs(bool enable) {
    307   return kNoError;
    308 }
    309 
    310 int AudioProcessingImpl::input_sample_rate_hz() const {
    311   CriticalSectionScoped crit_scoped(crit_);
    312   return fwd_in_format_.rate();
    313 }
    314 
    315 int AudioProcessingImpl::sample_rate_hz() const {
    316   CriticalSectionScoped crit_scoped(crit_);
    317   return fwd_in_format_.rate();
    318 }
    319 
    320 int AudioProcessingImpl::proc_sample_rate_hz() const {
    321   return fwd_proc_format_.rate();
    322 }
    323 
    324 int AudioProcessingImpl::proc_split_sample_rate_hz() const {
    325   return split_rate_;
    326 }
    327 
    328 int AudioProcessingImpl::num_reverse_channels() const {
    329   return rev_proc_format_.num_channels();
    330 }
    331 
    332 int AudioProcessingImpl::num_input_channels() const {
    333   return fwd_in_format_.num_channels();
    334 }
    335 
    336 int AudioProcessingImpl::num_output_channels() const {
    337   return fwd_proc_format_.num_channels();
    338 }
    339 
    340 void AudioProcessingImpl::set_output_will_be_muted(bool muted) {
    341   output_will_be_muted_ = muted;
    342 }
    343 
    344 bool AudioProcessingImpl::output_will_be_muted() const {
    345   return output_will_be_muted_;
    346 }
    347 
    348 int AudioProcessingImpl::ProcessStream(const float* const* src,
    349                                        int samples_per_channel,
    350                                        int input_sample_rate_hz,
    351                                        ChannelLayout input_layout,
    352                                        int output_sample_rate_hz,
    353                                        ChannelLayout output_layout,
    354                                        float* const* dest) {
    355   CriticalSectionScoped crit_scoped(crit_);
    356   if (!src || !dest) {
    357     return kNullPointerError;
    358   }
    359 
    360   RETURN_ON_ERR(MaybeInitializeLocked(input_sample_rate_hz,
    361                                       output_sample_rate_hz,
    362                                       rev_in_format_.rate(),
    363                                       ChannelsFromLayout(input_layout),
    364                                       ChannelsFromLayout(output_layout),
    365                                       rev_in_format_.num_channels()));
    366   if (samples_per_channel != fwd_in_format_.samples_per_channel()) {
    367     return kBadDataLengthError;
    368   }
    369 
    370 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
    371   if (debug_file_->Open()) {
    372     event_msg_->set_type(audioproc::Event::STREAM);
    373     audioproc::Stream* msg = event_msg_->mutable_stream();
    374     const size_t channel_size = sizeof(float) * samples_per_channel;
    375     for (int i = 0; i < fwd_in_format_.num_channels(); ++i)
    376       msg->add_input_channel(src[i], channel_size);
    377   }
    378 #endif
    379 
    380   capture_audio_->CopyFrom(src, samples_per_channel, input_layout);
    381   RETURN_ON_ERR(ProcessStreamLocked());
    382   if (output_copy_needed(is_data_processed())) {
    383     capture_audio_->CopyTo(fwd_out_format_.samples_per_channel(),
    384                            output_layout,
    385                            dest);
    386   }
    387 
    388 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
    389   if (debug_file_->Open()) {
    390     audioproc::Stream* msg = event_msg_->mutable_stream();
    391     const size_t channel_size = sizeof(float) * samples_per_channel;
    392     for (int i = 0; i < fwd_proc_format_.num_channels(); ++i)
    393       msg->add_output_channel(dest[i], channel_size);
    394     RETURN_ON_ERR(WriteMessageToDebugFile());
    395   }
    396 #endif
    397 
    398   return kNoError;
    399 }
    400 
    401 int AudioProcessingImpl::ProcessStream(AudioFrame* frame) {
    402   CriticalSectionScoped crit_scoped(crit_);
    403   if (!frame) {
    404     return kNullPointerError;
    405   }
    406   // Must be a native rate.
    407   if (frame->sample_rate_hz_ != kSampleRate8kHz &&
    408       frame->sample_rate_hz_ != kSampleRate16kHz &&
    409       frame->sample_rate_hz_ != kSampleRate32kHz) {
    410     return kBadSampleRateError;
    411   }
    412   if (echo_control_mobile_->is_enabled() &&
    413       frame->sample_rate_hz_ > kSampleRate16kHz) {
    414     LOG(LS_ERROR) << "AECM only supports 16 or 8 kHz sample rates";
    415     return kUnsupportedComponentError;
    416   }
    417 
    418   // TODO(ajm): The input and output rates and channels are currently
    419   // constrained to be identical in the int16 interface.
    420   RETURN_ON_ERR(MaybeInitializeLocked(frame->sample_rate_hz_,
    421                                       frame->sample_rate_hz_,
    422                                       rev_in_format_.rate(),
    423                                       frame->num_channels_,
    424                                       frame->num_channels_,
    425                                       rev_in_format_.num_channels()));
    426   if (frame->samples_per_channel_ != fwd_in_format_.samples_per_channel()) {
    427     return kBadDataLengthError;
    428   }
    429 
    430 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
    431   if (debug_file_->Open()) {
    432     event_msg_->set_type(audioproc::Event::STREAM);
    433     audioproc::Stream* msg = event_msg_->mutable_stream();
    434     const size_t data_size = sizeof(int16_t) *
    435                              frame->samples_per_channel_ *
    436                              frame->num_channels_;
    437     msg->set_input_data(frame->data_, data_size);
    438   }
    439 #endif
    440 
    441   capture_audio_->DeinterleaveFrom(frame);
    442   RETURN_ON_ERR(ProcessStreamLocked());
    443   capture_audio_->InterleaveTo(frame, output_copy_needed(is_data_processed()));
    444 
    445 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
    446   if (debug_file_->Open()) {
    447     audioproc::Stream* msg = event_msg_->mutable_stream();
    448     const size_t data_size = sizeof(int16_t) *
    449                              frame->samples_per_channel_ *
    450                              frame->num_channels_;
    451     msg->set_output_data(frame->data_, data_size);
    452     RETURN_ON_ERR(WriteMessageToDebugFile());
    453   }
    454 #endif
    455 
    456   return kNoError;
    457 }
    458 
    459 
    460 int AudioProcessingImpl::ProcessStreamLocked() {
    461 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
    462   if (debug_file_->Open()) {
    463     audioproc::Stream* msg = event_msg_->mutable_stream();
    464     msg->set_delay(stream_delay_ms_);
    465     msg->set_drift(echo_cancellation_->stream_drift_samples());
    466     msg->set_level(gain_control_->stream_analog_level());
    467     msg->set_keypress(key_pressed_);
    468   }
    469 #endif
    470 
    471   AudioBuffer* ca = capture_audio_.get();  // For brevity.
    472   bool data_processed = is_data_processed();
    473   if (analysis_needed(data_processed)) {
    474     for (int i = 0; i < fwd_proc_format_.num_channels(); i++) {
    475       // Split into a low and high band.
    476       WebRtcSpl_AnalysisQMF(ca->data(i),
    477                             ca->samples_per_channel(),
    478                             ca->low_pass_split_data(i),
    479                             ca->high_pass_split_data(i),
    480                             ca->filter_states(i)->analysis_filter_state1,
    481                             ca->filter_states(i)->analysis_filter_state2);
    482     }
    483   }
    484 
    485   RETURN_ON_ERR(high_pass_filter_->ProcessCaptureAudio(ca));
    486   RETURN_ON_ERR(gain_control_->AnalyzeCaptureAudio(ca));
    487   RETURN_ON_ERR(echo_cancellation_->ProcessCaptureAudio(ca));
    488 
    489   if (echo_control_mobile_->is_enabled() && noise_suppression_->is_enabled()) {
    490     ca->CopyLowPassToReference();
    491   }
    492   RETURN_ON_ERR(noise_suppression_->ProcessCaptureAudio(ca));
    493   RETURN_ON_ERR(echo_control_mobile_->ProcessCaptureAudio(ca));
    494   RETURN_ON_ERR(voice_detection_->ProcessCaptureAudio(ca));
    495   RETURN_ON_ERR(gain_control_->ProcessCaptureAudio(ca));
    496 
    497   if (synthesis_needed(data_processed)) {
    498     for (int i = 0; i < fwd_proc_format_.num_channels(); i++) {
    499       // Recombine low and high bands.
    500       WebRtcSpl_SynthesisQMF(ca->low_pass_split_data(i),
    501                              ca->high_pass_split_data(i),
    502                              ca->samples_per_split_channel(),
    503                              ca->data(i),
    504                              ca->filter_states(i)->synthesis_filter_state1,
    505                              ca->filter_states(i)->synthesis_filter_state2);
    506     }
    507   }
    508 
    509   // The level estimator operates on the recombined data.
    510   RETURN_ON_ERR(level_estimator_->ProcessStream(ca));
    511 
    512   was_stream_delay_set_ = false;
    513   return kNoError;
    514 }
    515 
    516 int AudioProcessingImpl::AnalyzeReverseStream(const float* const* data,
    517                                               int samples_per_channel,
    518                                               int sample_rate_hz,
    519                                               ChannelLayout layout) {
    520   CriticalSectionScoped crit_scoped(crit_);
    521   if (data == NULL) {
    522     return kNullPointerError;
    523   }
    524 
    525   const int num_channels = ChannelsFromLayout(layout);
    526   RETURN_ON_ERR(MaybeInitializeLocked(fwd_in_format_.rate(),
    527                                       fwd_out_format_.rate(),
    528                                       sample_rate_hz,
    529                                       fwd_in_format_.num_channels(),
    530                                       fwd_proc_format_.num_channels(),
    531                                       num_channels));
    532   if (samples_per_channel != rev_in_format_.samples_per_channel()) {
    533     return kBadDataLengthError;
    534   }
    535 
    536 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
    537   if (debug_file_->Open()) {
    538     event_msg_->set_type(audioproc::Event::REVERSE_STREAM);
    539     audioproc::ReverseStream* msg = event_msg_->mutable_reverse_stream();
    540     const size_t channel_size = sizeof(float) * 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::StopDebugRecording() {
    721   CriticalSectionScoped crit_scoped(crit_);
    722 
    723 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
    724   // We just return if recording hasn't started.
    725   if (debug_file_->Open()) {
    726     if (debug_file_->CloseFile() == -1) {
    727       return kFileError;
    728     }
    729   }
    730   return kNoError;
    731 #else
    732   return kUnsupportedFunctionError;
    733 #endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
    734 }
    735 
    736 EchoCancellation* AudioProcessingImpl::echo_cancellation() const {
    737   return echo_cancellation_;
    738 }
    739 
    740 EchoControlMobile* AudioProcessingImpl::echo_control_mobile() const {
    741   return echo_control_mobile_;
    742 }
    743 
    744 GainControl* AudioProcessingImpl::gain_control() const {
    745   return gain_control_;
    746 }
    747 
    748 HighPassFilter* AudioProcessingImpl::high_pass_filter() const {
    749   return high_pass_filter_;
    750 }
    751 
    752 LevelEstimator* AudioProcessingImpl::level_estimator() const {
    753   return level_estimator_;
    754 }
    755 
    756 NoiseSuppression* AudioProcessingImpl::noise_suppression() const {
    757   return noise_suppression_;
    758 }
    759 
    760 VoiceDetection* AudioProcessingImpl::voice_detection() const {
    761   return voice_detection_;
    762 }
    763 
    764 bool AudioProcessingImpl::is_data_processed() const {
    765   int enabled_count = 0;
    766   std::list<ProcessingComponent*>::const_iterator it;
    767   for (it = component_list_.begin(); it != component_list_.end(); it++) {
    768     if ((*it)->is_component_enabled()) {
    769       enabled_count++;
    770     }
    771   }
    772 
    773   // Data is unchanged if no components are enabled, or if only level_estimator_
    774   // or voice_detection_ is enabled.
    775   if (enabled_count == 0) {
    776     return false;
    777   } else if (enabled_count == 1) {
    778     if (level_estimator_->is_enabled() || voice_detection_->is_enabled()) {
    779       return false;
    780     }
    781   } else if (enabled_count == 2) {
    782     if (level_estimator_->is_enabled() && voice_detection_->is_enabled()) {
    783       return false;
    784     }
    785   }
    786   return true;
    787 }
    788 
    789 bool AudioProcessingImpl::output_copy_needed(bool is_data_processed) const {
    790   // Check if we've upmixed or downmixed the audio.
    791   return ((fwd_proc_format_.num_channels() != fwd_in_format_.num_channels()) ||
    792           is_data_processed);
    793 }
    794 
    795 bool AudioProcessingImpl::synthesis_needed(bool is_data_processed) const {
    796   return (is_data_processed && fwd_proc_format_.rate() == kSampleRate32kHz);
    797 }
    798 
    799 bool AudioProcessingImpl::analysis_needed(bool is_data_processed) const {
    800   if (!is_data_processed && !voice_detection_->is_enabled()) {
    801     // Only level_estimator_ is enabled.
    802     return false;
    803   } else if (fwd_proc_format_.rate() == kSampleRate32kHz) {
    804     // Something besides level_estimator_ is enabled, and we have super-wb.
    805     return true;
    806   }
    807   return false;
    808 }
    809 
    810 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
    811 int AudioProcessingImpl::WriteMessageToDebugFile() {
    812   int32_t size = event_msg_->ByteSize();
    813   if (size <= 0) {
    814     return kUnspecifiedError;
    815   }
    816 #if defined(WEBRTC_ARCH_BIG_ENDIAN)
    817   // TODO(ajm): Use little-endian "on the wire". For the moment, we can be
    818   //            pretty safe in assuming little-endian.
    819 #endif
    820 
    821   if (!event_msg_->SerializeToString(&event_str_)) {
    822     return kUnspecifiedError;
    823   }
    824 
    825   // Write message preceded by its size.
    826   if (!debug_file_->Write(&size, sizeof(int32_t))) {
    827     return kFileError;
    828   }
    829   if (!debug_file_->Write(event_str_.data(), event_str_.length())) {
    830     return kFileError;
    831   }
    832 
    833   event_msg_->Clear();
    834 
    835   return kNoError;
    836 }
    837 
    838 int AudioProcessingImpl::WriteInitMessage() {
    839   event_msg_->set_type(audioproc::Event::INIT);
    840   audioproc::Init* msg = event_msg_->mutable_init();
    841   msg->set_sample_rate(fwd_in_format_.rate());
    842   msg->set_num_input_channels(fwd_in_format_.num_channels());
    843   msg->set_num_output_channels(fwd_proc_format_.num_channels());
    844   msg->set_num_reverse_channels(rev_in_format_.num_channels());
    845   msg->set_reverse_sample_rate(rev_in_format_.rate());
    846   msg->set_output_sample_rate(fwd_out_format_.rate());
    847 
    848   int err = WriteMessageToDebugFile();
    849   if (err != kNoError) {
    850     return err;
    851   }
    852 
    853   return kNoError;
    854 }
    855 #endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
    856 
    857 }  // namespace webrtc
    858