1e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/*
2e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *
4e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *  Use of this source code is governed by a BSD-style license
5e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *  that can be found in the LICENSE file in the root of the source
6e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *  tree. An additional intellectual property rights grant can be found
7e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *  in the file PATENTS.  All contributing project authors may
8e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *  be found in the AUTHORS file in the root of the source tree.
9e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */
10e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
11e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "audio_processing_impl.h"
12e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
13c55a96383497a772a307b346368133960b02ad03Eric Laurent#include <assert.h>
14e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
15e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "audio_buffer.h"
16c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "critical_section_wrapper.h"
17e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "echo_cancellation_impl.h"
18e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "echo_control_mobile_impl.h"
19c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "file_wrapper.h"
20e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "high_pass_filter_impl.h"
21e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "gain_control_impl.h"
22e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "level_estimator_impl.h"
23c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "module_common_types.h"
24e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "noise_suppression_impl.h"
25e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "processing_component.h"
26e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "splitting_filter.h"
27e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "voice_detection_impl.h"
28e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
29c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
30c55a96383497a772a307b346368133960b02ad03Eric Laurent// Files generated at build-time by the protobuf compiler.
31c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_ANDROID
32c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "external/webrtc/src/modules/audio_processing/debug.pb.h"
33c55a96383497a772a307b346368133960b02ad03Eric Laurent#else
34c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "webrtc/audio_processing/debug.pb.h"
35c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif
36c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
37e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
38c55a96383497a772a307b346368133960b02ad03Eric Laurentnamespace webrtc {
39e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentAudioProcessing* AudioProcessing::Create(int id) {
40e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  /*WEBRTC_TRACE(webrtc::kTraceModuleCall,
41e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent             webrtc::kTraceAudioProcessing,
42e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent             id,
43e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent             "AudioProcessing::Create()");*/
44e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
45e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  AudioProcessingImpl* apm = new AudioProcessingImpl(id);
46e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (apm->Initialize() != kNoError) {
47e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    delete apm;
48e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    apm = NULL;
49e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
50e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
51e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return apm;
52e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
53e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
54e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid AudioProcessing::Destroy(AudioProcessing* apm) {
55e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  delete static_cast<AudioProcessingImpl*>(apm);
56e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
57e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
58e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentAudioProcessingImpl::AudioProcessingImpl(int id)
59e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    : id_(id),
60e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      echo_cancellation_(NULL),
61e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      echo_control_mobile_(NULL),
62e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      gain_control_(NULL),
63e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      high_pass_filter_(NULL),
64e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      level_estimator_(NULL),
65e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      noise_suppression_(NULL),
66e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      voice_detection_(NULL),
67e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      crit_(CriticalSectionWrapper::CreateCriticalSection()),
68e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      render_audio_(NULL),
69e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      capture_audio_(NULL),
70c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
71c55a96383497a772a307b346368133960b02ad03Eric Laurent      debug_file_(FileWrapper::Create()),
72c55a96383497a772a307b346368133960b02ad03Eric Laurent      event_msg_(new audioproc::Event()),
73c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif
74e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      sample_rate_hz_(kSampleRate16kHz),
75e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      split_sample_rate_hz_(kSampleRate16kHz),
76e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      samples_per_channel_(sample_rate_hz_ / 100),
77e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      stream_delay_ms_(0),
78e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      was_stream_delay_set_(false),
79c55a96383497a772a307b346368133960b02ad03Eric Laurent      num_reverse_channels_(1),
80c55a96383497a772a307b346368133960b02ad03Eric Laurent      num_input_channels_(1),
81c55a96383497a772a307b346368133960b02ad03Eric Laurent      num_output_channels_(1) {
82e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
83e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  echo_cancellation_ = new EchoCancellationImpl(this);
84e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  component_list_.push_back(echo_cancellation_);
85e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
86e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  echo_control_mobile_ = new EchoControlMobileImpl(this);
87e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  component_list_.push_back(echo_control_mobile_);
88e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
89e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  gain_control_ = new GainControlImpl(this);
90e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  component_list_.push_back(gain_control_);
91e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
92e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  high_pass_filter_ = new HighPassFilterImpl(this);
93e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  component_list_.push_back(high_pass_filter_);
94e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
95e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  level_estimator_ = new LevelEstimatorImpl(this);
96e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  component_list_.push_back(level_estimator_);
97e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
98e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  noise_suppression_ = new NoiseSuppressionImpl(this);
99e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  component_list_.push_back(noise_suppression_);
100e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
101e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  voice_detection_ = new VoiceDetectionImpl(this);
102e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  component_list_.push_back(voice_detection_);
103e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
104e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
105e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentAudioProcessingImpl::~AudioProcessingImpl() {
106e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  while (!component_list_.empty()) {
107e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    ProcessingComponent* component = component_list_.front();
108e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    component->Destroy();
109e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    delete component;
110e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    component_list_.pop_front();
111e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
112e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
113c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
114e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (debug_file_->Open()) {
115e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    debug_file_->CloseFile();
116e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
117c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif
118e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
119e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  delete crit_;
120e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  crit_ = NULL;
121e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
122c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (render_audio_) {
123e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    delete render_audio_;
124e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    render_audio_ = NULL;
125e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
126e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
127c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (capture_audio_) {
128e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    delete capture_audio_;
129e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    capture_audio_ = NULL;
130e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
131e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
132e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
133e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentCriticalSectionWrapper* AudioProcessingImpl::crit() const {
134e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return crit_;
135e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
136e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
137e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint AudioProcessingImpl::split_sample_rate_hz() const {
138e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return split_sample_rate_hz_;
139e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
140e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
141e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint AudioProcessingImpl::Initialize() {
142e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  CriticalSectionScoped crit_scoped(*crit_);
143e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return InitializeLocked();
144e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
145e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
146e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint AudioProcessingImpl::InitializeLocked() {
147e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (render_audio_ != NULL) {
148e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    delete render_audio_;
149e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    render_audio_ = NULL;
150e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
151e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
152e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (capture_audio_ != NULL) {
153e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    delete capture_audio_;
154e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    capture_audio_ = NULL;
155e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
156e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
157c55a96383497a772a307b346368133960b02ad03Eric Laurent  render_audio_ = new AudioBuffer(num_reverse_channels_,
158e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                  samples_per_channel_);
159c55a96383497a772a307b346368133960b02ad03Eric Laurent  capture_audio_ = new AudioBuffer(num_input_channels_,
160e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                   samples_per_channel_);
161e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
162e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  was_stream_delay_set_ = false;
163e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
164e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // Initialize all components.
165e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  std::list<ProcessingComponent*>::iterator it;
166e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  for (it = component_list_.begin(); it != component_list_.end(); it++) {
167e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    int err = (*it)->Initialize();
168e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (err != kNoError) {
169e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      return err;
170e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
171e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
172e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
173c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
174c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (debug_file_->Open()) {
175c55a96383497a772a307b346368133960b02ad03Eric Laurent    int err = WriteInitMessage();
176c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (err != kNoError) {
177c55a96383497a772a307b346368133960b02ad03Eric Laurent      return err;
178c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
179c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
180c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif
181c55a96383497a772a307b346368133960b02ad03Eric Laurent
182e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return kNoError;
183e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
184e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
185e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint AudioProcessingImpl::set_sample_rate_hz(int rate) {
186e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  CriticalSectionScoped crit_scoped(*crit_);
187e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (rate != kSampleRate8kHz &&
188e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      rate != kSampleRate16kHz &&
189e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      rate != kSampleRate32kHz) {
190e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return kBadParameterError;
191e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
192e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
193e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  sample_rate_hz_ = rate;
194e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  samples_per_channel_ = rate / 100;
195e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
196e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (sample_rate_hz_ == kSampleRate32kHz) {
197e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    split_sample_rate_hz_ = kSampleRate16kHz;
198e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  } else {
199e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    split_sample_rate_hz_ = sample_rate_hz_;
200e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
201e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
202e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return InitializeLocked();
203e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
204e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
205e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint AudioProcessingImpl::sample_rate_hz() const {
206e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return sample_rate_hz_;
207e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
208e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
209e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint AudioProcessingImpl::set_num_reverse_channels(int channels) {
210e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  CriticalSectionScoped crit_scoped(*crit_);
211e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // Only stereo supported currently.
212e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (channels > 2 || channels < 1) {
213e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return kBadParameterError;
214e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
215e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
216c55a96383497a772a307b346368133960b02ad03Eric Laurent  num_reverse_channels_ = channels;
217e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
218e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return InitializeLocked();
219e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
220e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
221e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint AudioProcessingImpl::num_reverse_channels() const {
222c55a96383497a772a307b346368133960b02ad03Eric Laurent  return num_reverse_channels_;
223e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
224e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
225e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint AudioProcessingImpl::set_num_channels(
226e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    int input_channels,
227e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    int output_channels) {
228e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  CriticalSectionScoped crit_scoped(*crit_);
229e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (output_channels > input_channels) {
230e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return kBadParameterError;
231e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
232e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
233e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // Only stereo supported currently.
234e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (input_channels > 2 || input_channels < 1) {
235e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return kBadParameterError;
236e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
237e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
238e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (output_channels > 2 || output_channels < 1) {
239e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return kBadParameterError;
240e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
241e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
242c55a96383497a772a307b346368133960b02ad03Eric Laurent  num_input_channels_ = input_channels;
243c55a96383497a772a307b346368133960b02ad03Eric Laurent  num_output_channels_ = output_channels;
244e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
245e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return InitializeLocked();
246e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
247e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
248e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint AudioProcessingImpl::num_input_channels() const {
249c55a96383497a772a307b346368133960b02ad03Eric Laurent  return num_input_channels_;
250e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
251e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
252e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint AudioProcessingImpl::num_output_channels() const {
253c55a96383497a772a307b346368133960b02ad03Eric Laurent  return num_output_channels_;
254e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
255e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
256e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint AudioProcessingImpl::ProcessStream(AudioFrame* frame) {
257e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  CriticalSectionScoped crit_scoped(*crit_);
258e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  int err = kNoError;
259e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
260e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (frame == NULL) {
261e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return kNullPointerError;
262e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
263e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
264c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (frame->_frequencyInHz != sample_rate_hz_) {
265e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return kBadSampleRateError;
266e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
267e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
268c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (frame->_audioChannel != num_input_channels_) {
269e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return kBadNumberChannelsError;
270e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
271e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
272e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (frame->_payloadDataLengthInSamples != samples_per_channel_) {
273e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return kBadDataLengthError;
274e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
275e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
276c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
277e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (debug_file_->Open()) {
278c55a96383497a772a307b346368133960b02ad03Eric Laurent    event_msg_->set_type(audioproc::Event::STREAM);
279c55a96383497a772a307b346368133960b02ad03Eric Laurent    audioproc::Stream* msg = event_msg_->mutable_stream();
280c55a96383497a772a307b346368133960b02ad03Eric Laurent    const size_t data_size = sizeof(int16_t) *
281c55a96383497a772a307b346368133960b02ad03Eric Laurent                             frame->_payloadDataLengthInSamples *
282c55a96383497a772a307b346368133960b02ad03Eric Laurent                             frame->_audioChannel;
283c55a96383497a772a307b346368133960b02ad03Eric Laurent    msg->set_input_data(frame->_payloadData, data_size);
284c55a96383497a772a307b346368133960b02ad03Eric Laurent    msg->set_delay(stream_delay_ms_);
285c55a96383497a772a307b346368133960b02ad03Eric Laurent    msg->set_drift(echo_cancellation_->stream_drift_samples());
286c55a96383497a772a307b346368133960b02ad03Eric Laurent    msg->set_level(gain_control_->stream_analog_level());
287c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
288c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif
289e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
290e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  capture_audio_->DeinterleaveFrom(frame);
291e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
292e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // TODO(ajm): experiment with mixing and AEC placement.
293c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (num_output_channels_ < num_input_channels_) {
294c55a96383497a772a307b346368133960b02ad03Eric Laurent    capture_audio_->Mix(num_output_channels_);
295c55a96383497a772a307b346368133960b02ad03Eric Laurent    frame->_audioChannel = num_output_channels_;
296e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
297e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
298c55a96383497a772a307b346368133960b02ad03Eric Laurent  bool data_changed = stream_data_changed();
299c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (analysis_needed(data_changed)) {
300c55a96383497a772a307b346368133960b02ad03Eric Laurent    for (int i = 0; i < num_output_channels_; i++) {
301e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      // Split into a low and high band.
302e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      SplittingFilterAnalysis(capture_audio_->data(i),
303e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                              capture_audio_->low_pass_split_data(i),
304e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                              capture_audio_->high_pass_split_data(i),
305e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                              capture_audio_->analysis_filter_state1(i),
306e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                              capture_audio_->analysis_filter_state2(i));
307e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
308e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
309e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
310e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  err = high_pass_filter_->ProcessCaptureAudio(capture_audio_);
311e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (err != kNoError) {
312e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return err;
313e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
314e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
315e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  err = gain_control_->AnalyzeCaptureAudio(capture_audio_);
316e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (err != kNoError) {
317e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return err;
318e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
319e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
320e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  err = echo_cancellation_->ProcessCaptureAudio(capture_audio_);
321e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (err != kNoError) {
322e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return err;
323e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
324e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
325e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (echo_control_mobile_->is_enabled() &&
326e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      noise_suppression_->is_enabled()) {
327e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    capture_audio_->CopyLowPassToReference();
328e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
329e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
330e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  err = noise_suppression_->ProcessCaptureAudio(capture_audio_);
331e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (err != kNoError) {
332e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return err;
333e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
334e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
335e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  err = echo_control_mobile_->ProcessCaptureAudio(capture_audio_);
336e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (err != kNoError) {
337e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return err;
338e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
339e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
340e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  err = voice_detection_->ProcessCaptureAudio(capture_audio_);
341e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (err != kNoError) {
342e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return err;
343e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
344e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
345e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  err = gain_control_->ProcessCaptureAudio(capture_audio_);
346e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (err != kNoError) {
347e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return err;
348e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
349e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
350c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (synthesis_needed(data_changed)) {
351c55a96383497a772a307b346368133960b02ad03Eric Laurent    for (int i = 0; i < num_output_channels_; i++) {
352e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      // Recombine low and high bands.
353e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      SplittingFilterSynthesis(capture_audio_->low_pass_split_data(i),
354e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                               capture_audio_->high_pass_split_data(i),
355e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                               capture_audio_->data(i),
356e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                               capture_audio_->synthesis_filter_state1(i),
357e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                               capture_audio_->synthesis_filter_state2(i));
358e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
359e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
360e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
361c55a96383497a772a307b346368133960b02ad03Eric Laurent  // The level estimator operates on the recombined data.
362c55a96383497a772a307b346368133960b02ad03Eric Laurent  err = level_estimator_->ProcessStream(capture_audio_);
363c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (err != kNoError) {
364c55a96383497a772a307b346368133960b02ad03Eric Laurent    return err;
365c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
366c55a96383497a772a307b346368133960b02ad03Eric Laurent
367c55a96383497a772a307b346368133960b02ad03Eric Laurent  capture_audio_->InterleaveTo(frame, data_changed);
368c55a96383497a772a307b346368133960b02ad03Eric Laurent
369c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
370c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (debug_file_->Open()) {
371c55a96383497a772a307b346368133960b02ad03Eric Laurent    audioproc::Stream* msg = event_msg_->mutable_stream();
372c55a96383497a772a307b346368133960b02ad03Eric Laurent    const size_t data_size = sizeof(int16_t) *
373c55a96383497a772a307b346368133960b02ad03Eric Laurent                             frame->_payloadDataLengthInSamples *
374c55a96383497a772a307b346368133960b02ad03Eric Laurent                             frame->_audioChannel;
375c55a96383497a772a307b346368133960b02ad03Eric Laurent    msg->set_output_data(frame->_payloadData, data_size);
376c55a96383497a772a307b346368133960b02ad03Eric Laurent    err = WriteMessageToDebugFile();
377c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (err != kNoError) {
378c55a96383497a772a307b346368133960b02ad03Eric Laurent      return err;
379c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
380c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
381c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif
382e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
383c55a96383497a772a307b346368133960b02ad03Eric Laurent  was_stream_delay_set_ = false;
384e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return kNoError;
385e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
386e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
387e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint AudioProcessingImpl::AnalyzeReverseStream(AudioFrame* frame) {
388e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  CriticalSectionScoped crit_scoped(*crit_);
389e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  int err = kNoError;
390e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
391e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (frame == NULL) {
392e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return kNullPointerError;
393e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
394e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
395c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (frame->_frequencyInHz != sample_rate_hz_) {
396e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return kBadSampleRateError;
397e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
398e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
399c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (frame->_audioChannel != num_reverse_channels_) {
400e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return kBadNumberChannelsError;
401e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
402e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
403e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (frame->_payloadDataLengthInSamples != samples_per_channel_) {
404e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return kBadDataLengthError;
405e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
406e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
407c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
408e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (debug_file_->Open()) {
409c55a96383497a772a307b346368133960b02ad03Eric Laurent    event_msg_->set_type(audioproc::Event::REVERSE_STREAM);
410c55a96383497a772a307b346368133960b02ad03Eric Laurent    audioproc::ReverseStream* msg = event_msg_->mutable_reverse_stream();
411c55a96383497a772a307b346368133960b02ad03Eric Laurent    const size_t data_size = sizeof(int16_t) *
412c55a96383497a772a307b346368133960b02ad03Eric Laurent                             frame->_payloadDataLengthInSamples *
413c55a96383497a772a307b346368133960b02ad03Eric Laurent                             frame->_audioChannel;
414c55a96383497a772a307b346368133960b02ad03Eric Laurent    msg->set_data(frame->_payloadData, data_size);
415c55a96383497a772a307b346368133960b02ad03Eric Laurent    err = WriteMessageToDebugFile();
416c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (err != kNoError) {
417c55a96383497a772a307b346368133960b02ad03Eric Laurent      return err;
418e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
419e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
420c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif
421e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
422e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  render_audio_->DeinterleaveFrom(frame);
423e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
424e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // TODO(ajm): turn the splitting filter into a component?
425e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (sample_rate_hz_ == kSampleRate32kHz) {
426c55a96383497a772a307b346368133960b02ad03Eric Laurent    for (int i = 0; i < num_reverse_channels_; i++) {
427e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      // Split into low and high band.
428e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      SplittingFilterAnalysis(render_audio_->data(i),
429e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                              render_audio_->low_pass_split_data(i),
430e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                              render_audio_->high_pass_split_data(i),
431e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                              render_audio_->analysis_filter_state1(i),
432e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                              render_audio_->analysis_filter_state2(i));
433e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
434e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
435e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
436e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // TODO(ajm): warnings possible from components?
437e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  err = echo_cancellation_->ProcessRenderAudio(render_audio_);
438e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (err != kNoError) {
439e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return err;
440e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
441e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
442e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  err = echo_control_mobile_->ProcessRenderAudio(render_audio_);
443e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (err != kNoError) {
444e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return err;
445e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
446e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
447e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  err = gain_control_->ProcessRenderAudio(render_audio_);
448e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (err != kNoError) {
449e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return err;
450e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
451e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
452e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return err;  // TODO(ajm): this is for returning warnings; necessary?
453e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
454e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
455e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint AudioProcessingImpl::set_stream_delay_ms(int delay) {
456e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  was_stream_delay_set_ = true;
457e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (delay < 0) {
458e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return kBadParameterError;
459e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
460e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
461e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // TODO(ajm): the max is rather arbitrarily chosen; investigate.
462e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (delay > 500) {
463e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    stream_delay_ms_ = 500;
464e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return kBadStreamParameterWarning;
465e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
466e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
467e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  stream_delay_ms_ = delay;
468e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return kNoError;
469e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
470e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
471e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint AudioProcessingImpl::stream_delay_ms() const {
472e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return stream_delay_ms_;
473e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
474e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
475e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentbool AudioProcessingImpl::was_stream_delay_set() const {
476e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return was_stream_delay_set_;
477e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
478e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
479e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint AudioProcessingImpl::StartDebugRecording(
480e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const char filename[AudioProcessing::kMaxFilenameSize]) {
481e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  CriticalSectionScoped crit_scoped(*crit_);
482e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  assert(kMaxFilenameSize == FileWrapper::kMaxFileNameSize);
483e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
484e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (filename == NULL) {
485e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return kNullPointerError;
486e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
487e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
488c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
489e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // Stop any ongoing recording.
490e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (debug_file_->Open()) {
491e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (debug_file_->CloseFile() == -1) {
492e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      return kFileError;
493e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
494e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
495e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
496e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (debug_file_->OpenFile(filename, false) == -1) {
497e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    debug_file_->CloseFile();
498e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return kFileError;
499e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
500e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
501c55a96383497a772a307b346368133960b02ad03Eric Laurent  int err = WriteInitMessage();
502c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (err != kNoError) {
503c55a96383497a772a307b346368133960b02ad03Eric Laurent    return err;
504e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
505e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return kNoError;
506c55a96383497a772a307b346368133960b02ad03Eric Laurent#else
507c55a96383497a772a307b346368133960b02ad03Eric Laurent  return kUnsupportedFunctionError;
508c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
509e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
510e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
511e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint AudioProcessingImpl::StopDebugRecording() {
512e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  CriticalSectionScoped crit_scoped(*crit_);
513c55a96383497a772a307b346368133960b02ad03Eric Laurent
514c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
515e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // We just return if recording hasn't started.
516e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (debug_file_->Open()) {
517e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (debug_file_->CloseFile() == -1) {
518e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      return kFileError;
519e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
520e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
521e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return kNoError;
522c55a96383497a772a307b346368133960b02ad03Eric Laurent#else
523c55a96383497a772a307b346368133960b02ad03Eric Laurent  return kUnsupportedFunctionError;
524c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
525e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
526e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
527e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentEchoCancellation* AudioProcessingImpl::echo_cancellation() const {
528e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return echo_cancellation_;
529e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
530e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
531e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentEchoControlMobile* AudioProcessingImpl::echo_control_mobile() const {
532e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return echo_control_mobile_;
533e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
534e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
535e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentGainControl* AudioProcessingImpl::gain_control() const {
536e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return gain_control_;
537e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
538e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
539e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentHighPassFilter* AudioProcessingImpl::high_pass_filter() const {
540e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return high_pass_filter_;
541e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
542e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
543e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentLevelEstimator* AudioProcessingImpl::level_estimator() const {
544e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return level_estimator_;
545e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
546e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
547e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentNoiseSuppression* AudioProcessingImpl::noise_suppression() const {
548e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return noise_suppression_;
549e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
550e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
551e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentVoiceDetection* AudioProcessingImpl::voice_detection() const {
552e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return voice_detection_;
553e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
554e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
555c55a96383497a772a307b346368133960b02ad03Eric LaurentWebRtc_Word32 AudioProcessingImpl::ChangeUniqueId(const WebRtc_Word32 id) {
556c55a96383497a772a307b346368133960b02ad03Eric Laurent  CriticalSectionScoped crit_scoped(*crit_);
557c55a96383497a772a307b346368133960b02ad03Eric Laurent  /*WEBRTC_TRACE(webrtc::kTraceModuleCall,
558c55a96383497a772a307b346368133960b02ad03Eric Laurent             webrtc::kTraceAudioProcessing,
559c55a96383497a772a307b346368133960b02ad03Eric Laurent             id_,
560c55a96383497a772a307b346368133960b02ad03Eric Laurent             "ChangeUniqueId(new id = %d)",
561c55a96383497a772a307b346368133960b02ad03Eric Laurent             id);*/
562c55a96383497a772a307b346368133960b02ad03Eric Laurent  id_ = id;
563e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
564c55a96383497a772a307b346368133960b02ad03Eric Laurent  return kNoError;
565c55a96383497a772a307b346368133960b02ad03Eric Laurent}
566e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
567c55a96383497a772a307b346368133960b02ad03Eric Laurentbool AudioProcessingImpl::stream_data_changed() const {
568c55a96383497a772a307b346368133960b02ad03Eric Laurent  int enabled_count = 0;
569e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  std::list<ProcessingComponent*>::const_iterator it;
570e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  for (it = component_list_.begin(); it != component_list_.end(); it++) {
571c55a96383497a772a307b346368133960b02ad03Eric Laurent    if ((*it)->is_component_enabled()) {
572c55a96383497a772a307b346368133960b02ad03Eric Laurent      enabled_count++;
573e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
574c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
575e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
576c55a96383497a772a307b346368133960b02ad03Eric Laurent  // Data is unchanged if no components are enabled, or if only level_estimator_
577c55a96383497a772a307b346368133960b02ad03Eric Laurent  // or voice_detection_ is enabled.
578c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (enabled_count == 0) {
579c55a96383497a772a307b346368133960b02ad03Eric Laurent    return false;
580c55a96383497a772a307b346368133960b02ad03Eric Laurent  } else if (enabled_count == 1) {
581c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (level_estimator_->is_enabled() || voice_detection_->is_enabled()) {
582c55a96383497a772a307b346368133960b02ad03Eric Laurent      return false;
583c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
584c55a96383497a772a307b346368133960b02ad03Eric Laurent  } else if (enabled_count == 2) {
585c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (level_estimator_->is_enabled() && voice_detection_->is_enabled()) {
586c55a96383497a772a307b346368133960b02ad03Eric Laurent      return false;
587e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
588e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
589c55a96383497a772a307b346368133960b02ad03Eric Laurent  return true;
590c55a96383497a772a307b346368133960b02ad03Eric Laurent}
591e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
592c55a96383497a772a307b346368133960b02ad03Eric Laurentbool AudioProcessingImpl::synthesis_needed(bool stream_data_changed) const {
593c55a96383497a772a307b346368133960b02ad03Eric Laurent  return (stream_data_changed && sample_rate_hz_ == kSampleRate32kHz);
594e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
595e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
596c55a96383497a772a307b346368133960b02ad03Eric Laurentbool AudioProcessingImpl::analysis_needed(bool stream_data_changed) const {
597c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (!stream_data_changed && !voice_detection_->is_enabled()) {
598c55a96383497a772a307b346368133960b02ad03Eric Laurent    // Only level_estimator_ is enabled.
599c55a96383497a772a307b346368133960b02ad03Eric Laurent    return false;
600c55a96383497a772a307b346368133960b02ad03Eric Laurent  } else if (sample_rate_hz_ == kSampleRate32kHz) {
601c55a96383497a772a307b346368133960b02ad03Eric Laurent    // Something besides level_estimator_ is enabled, and we have super-wb.
602c55a96383497a772a307b346368133960b02ad03Eric Laurent    return true;
603c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
604c55a96383497a772a307b346368133960b02ad03Eric Laurent  return false;
605c55a96383497a772a307b346368133960b02ad03Eric Laurent}
606c55a96383497a772a307b346368133960b02ad03Eric Laurent
607c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
608c55a96383497a772a307b346368133960b02ad03Eric Laurentint AudioProcessingImpl::WriteMessageToDebugFile() {
609c55a96383497a772a307b346368133960b02ad03Eric Laurent  int32_t size = event_msg_->ByteSize();
610c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (size <= 0) {
611c55a96383497a772a307b346368133960b02ad03Eric Laurent    return kUnspecifiedError;
612c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
613c55a96383497a772a307b346368133960b02ad03Eric Laurent#if defined(WEBRTC_BIG_ENDIAN)
614c55a96383497a772a307b346368133960b02ad03Eric Laurent  // TODO(ajm): Use little-endian "on the wire". For the moment, we can be
615c55a96383497a772a307b346368133960b02ad03Eric Laurent  //            pretty safe in assuming little-endian.
616c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif
617c55a96383497a772a307b346368133960b02ad03Eric Laurent
618c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (!event_msg_->SerializeToString(&event_str_)) {
619c55a96383497a772a307b346368133960b02ad03Eric Laurent    return kUnspecifiedError;
620c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
621c55a96383497a772a307b346368133960b02ad03Eric Laurent
622c55a96383497a772a307b346368133960b02ad03Eric Laurent  // Write message preceded by its size.
623c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (!debug_file_->Write(&size, sizeof(int32_t))) {
624c55a96383497a772a307b346368133960b02ad03Eric Laurent    return kFileError;
625c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
626c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (!debug_file_->Write(event_str_.data(), event_str_.length())) {
627c55a96383497a772a307b346368133960b02ad03Eric Laurent    return kFileError;
628c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
629c55a96383497a772a307b346368133960b02ad03Eric Laurent
630c55a96383497a772a307b346368133960b02ad03Eric Laurent  event_msg_->Clear();
631c55a96383497a772a307b346368133960b02ad03Eric Laurent
632c55a96383497a772a307b346368133960b02ad03Eric Laurent  return 0;
633c55a96383497a772a307b346368133960b02ad03Eric Laurent}
634c55a96383497a772a307b346368133960b02ad03Eric Laurent
635c55a96383497a772a307b346368133960b02ad03Eric Laurentint AudioProcessingImpl::WriteInitMessage() {
636c55a96383497a772a307b346368133960b02ad03Eric Laurent  event_msg_->set_type(audioproc::Event::INIT);
637c55a96383497a772a307b346368133960b02ad03Eric Laurent  audioproc::Init* msg = event_msg_->mutable_init();
638c55a96383497a772a307b346368133960b02ad03Eric Laurent  msg->set_sample_rate(sample_rate_hz_);
639c55a96383497a772a307b346368133960b02ad03Eric Laurent  msg->set_device_sample_rate(echo_cancellation_->device_sample_rate_hz());
640c55a96383497a772a307b346368133960b02ad03Eric Laurent  msg->set_num_input_channels(num_input_channels_);
641c55a96383497a772a307b346368133960b02ad03Eric Laurent  msg->set_num_output_channels(num_output_channels_);
642c55a96383497a772a307b346368133960b02ad03Eric Laurent  msg->set_num_reverse_channels(num_reverse_channels_);
643c55a96383497a772a307b346368133960b02ad03Eric Laurent
644c55a96383497a772a307b346368133960b02ad03Eric Laurent  int err = WriteMessageToDebugFile();
645c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (err != kNoError) {
646c55a96383497a772a307b346368133960b02ad03Eric Laurent    return err;
647c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
648e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
649e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return kNoError;
650e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
651c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
652e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}  // namespace webrtc
653