Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / audio_processing / audio_processing_impl.cc
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/signal_processing/include/signal_processing_library.h"
16 #include "webrtc/modules/audio_processing/audio_buffer.h"
17 #include "webrtc/modules/audio_processing/echo_cancellation_impl_wrapper.h"
18 #include "webrtc/modules/audio_processing/echo_control_mobile_impl.h"
19 #include "webrtc/modules/audio_processing/gain_control_impl.h"
20 #include "webrtc/modules/audio_processing/high_pass_filter_impl.h"
21 #include "webrtc/modules/audio_processing/level_estimator_impl.h"
22 #include "webrtc/modules/audio_processing/noise_suppression_impl.h"
23 #include "webrtc/modules/audio_processing/processing_component.h"
24 #include "webrtc/modules/audio_processing/voice_detection_impl.h"
25 #include "webrtc/modules/interface/module_common_types.h"
26 #include "webrtc/system_wrappers/interface/compile_assert.h"
27 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
28 #include "webrtc/system_wrappers/interface/file_wrapper.h"
29 #include "webrtc/system_wrappers/interface/logging.h"
30
31 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
32 // Files generated at build-time by the protobuf compiler.
33 #ifdef WEBRTC_ANDROID_PLATFORM_BUILD
34 #include "external/webrtc/webrtc/modules/audio_processing/debug.pb.h"
35 #else
36 #include "webrtc/audio_processing/debug.pb.h"
37 #endif
38 #endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
39
40 static const int kChunkSizeMs = 10;
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       render_audio_(NULL),
84       capture_audio_(NULL),
85 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
86       debug_file_(FileWrapper::Create()),
87       event_msg_(new audioproc::Event()),
88 #endif
89       sample_rate_hz_(kSampleRate16kHz),
90       split_sample_rate_hz_(kSampleRate16kHz),
91       samples_per_channel_(kChunkSizeMs * sample_rate_hz_ / 1000),
92       stream_delay_ms_(0),
93       delay_offset_ms_(0),
94       was_stream_delay_set_(false),
95       num_reverse_channels_(1),
96       num_input_channels_(1),
97       num_output_channels_(1),
98       output_will_be_muted_(false),
99       key_pressed_(false) {
100   echo_cancellation_ = EchoCancellationImplWrapper::Create(this);
101   component_list_.push_back(echo_cancellation_);
102
103   echo_control_mobile_ = new EchoControlMobileImpl(this);
104   component_list_.push_back(echo_control_mobile_);
105
106   gain_control_ = new GainControlImpl(this);
107   component_list_.push_back(gain_control_);
108
109   high_pass_filter_ = new HighPassFilterImpl(this);
110   component_list_.push_back(high_pass_filter_);
111
112   level_estimator_ = new LevelEstimatorImpl(this);
113   component_list_.push_back(level_estimator_);
114
115   noise_suppression_ = new NoiseSuppressionImpl(this);
116   component_list_.push_back(noise_suppression_);
117
118   voice_detection_ = new VoiceDetectionImpl(this);
119   component_list_.push_back(voice_detection_);
120
121   SetExtraOptions(config);
122 }
123
124 AudioProcessingImpl::~AudioProcessingImpl() {
125   {
126     CriticalSectionScoped crit_scoped(crit_);
127     while (!component_list_.empty()) {
128       ProcessingComponent* component = component_list_.front();
129       component->Destroy();
130       delete component;
131       component_list_.pop_front();
132     }
133
134 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
135     if (debug_file_->Open()) {
136       debug_file_->CloseFile();
137     }
138 #endif
139
140     if (render_audio_) {
141       delete render_audio_;
142       render_audio_ = NULL;
143     }
144
145     if (capture_audio_) {
146       delete capture_audio_;
147       capture_audio_ = NULL;
148     }
149   }
150
151   delete crit_;
152   crit_ = NULL;
153 }
154
155 CriticalSectionWrapper* AudioProcessingImpl::crit() const {
156   return crit_;
157 }
158
159 int AudioProcessingImpl::split_sample_rate_hz() const {
160   return split_sample_rate_hz_;
161 }
162
163 int AudioProcessingImpl::Initialize() {
164   CriticalSectionScoped crit_scoped(crit_);
165   return InitializeLocked();
166 }
167
168 int AudioProcessingImpl::InitializeLocked() {
169   if (render_audio_ != NULL) {
170     delete render_audio_;
171     render_audio_ = NULL;
172   }
173
174   if (capture_audio_ != NULL) {
175     delete capture_audio_;
176     capture_audio_ = NULL;
177   }
178
179   render_audio_ = new AudioBuffer(num_reverse_channels_,
180                                   samples_per_channel_);
181   capture_audio_ = new AudioBuffer(num_input_channels_,
182                                    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 void AudioProcessingImpl::SetExtraOptions(const Config& config) {
206   CriticalSectionScoped crit_scoped(crit_);
207   std::list<ProcessingComponent*>::iterator it;
208   for (it = component_list_.begin(); it != component_list_.end(); ++it)
209     (*it)->SetExtraOptions(config);
210 }
211
212 int AudioProcessingImpl::EnableExperimentalNs(bool enable) {
213   return kNoError;
214 }
215
216 int AudioProcessingImpl::set_sample_rate_hz(int rate) {
217   CriticalSectionScoped crit_scoped(crit_);
218   if (rate == sample_rate_hz_) {
219     return kNoError;
220   }
221   if (rate != kSampleRate8kHz &&
222       rate != kSampleRate16kHz &&
223       rate != kSampleRate32kHz) {
224     return kBadParameterError;
225   }
226   if (echo_control_mobile_->is_enabled() && rate > kSampleRate16kHz) {
227     LOG(LS_ERROR) << "AECM only supports 16 kHz or lower sample rates";
228     return kUnsupportedComponentError;
229   }
230
231   sample_rate_hz_ = rate;
232   samples_per_channel_ = rate / 100;
233
234   if (sample_rate_hz_ == kSampleRate32kHz) {
235     split_sample_rate_hz_ = kSampleRate16kHz;
236   } else {
237     split_sample_rate_hz_ = sample_rate_hz_;
238   }
239
240   return InitializeLocked();
241 }
242
243 int AudioProcessingImpl::sample_rate_hz() const {
244   CriticalSectionScoped crit_scoped(crit_);
245   return sample_rate_hz_;
246 }
247
248 int AudioProcessingImpl::set_num_reverse_channels(int channels) {
249   CriticalSectionScoped crit_scoped(crit_);
250   if (channels == num_reverse_channels_) {
251     return kNoError;
252   }
253   // Only stereo supported currently.
254   if (channels > 2 || channels < 1) {
255     return kBadParameterError;
256   }
257
258   num_reverse_channels_ = channels;
259
260   return InitializeLocked();
261 }
262
263 int AudioProcessingImpl::num_reverse_channels() const {
264   return num_reverse_channels_;
265 }
266
267 int AudioProcessingImpl::set_num_channels(
268     int input_channels,
269     int output_channels) {
270   CriticalSectionScoped crit_scoped(crit_);
271   if (input_channels == num_input_channels_ &&
272       output_channels == num_output_channels_) {
273     return kNoError;
274   }
275   if (output_channels > input_channels) {
276     return kBadParameterError;
277   }
278   // Only stereo supported currently.
279   if (input_channels > 2 || input_channels < 1 ||
280       output_channels > 2 || output_channels < 1) {
281     return kBadParameterError;
282   }
283
284   num_input_channels_ = input_channels;
285   num_output_channels_ = output_channels;
286
287   return InitializeLocked();
288 }
289
290 int AudioProcessingImpl::num_input_channels() const {
291   return num_input_channels_;
292 }
293
294 int AudioProcessingImpl::num_output_channels() const {
295   return num_output_channels_;
296 }
297
298 void AudioProcessingImpl::set_output_will_be_muted(bool muted) {
299   output_will_be_muted_ = muted;
300 }
301
302 bool AudioProcessingImpl::output_will_be_muted() const {
303   return output_will_be_muted_;
304 }
305
306 int AudioProcessingImpl::MaybeInitializeLocked(int sample_rate_hz,
307     int num_input_channels, int num_output_channels, int num_reverse_channels) {
308   if (sample_rate_hz == sample_rate_hz_ &&
309       num_input_channels == num_input_channels_ &&
310       num_output_channels == num_output_channels_ &&
311       num_reverse_channels == num_reverse_channels_) {
312     return kNoError;
313   }
314
315   if (sample_rate_hz != kSampleRate8kHz &&
316       sample_rate_hz != kSampleRate16kHz &&
317       sample_rate_hz != kSampleRate32kHz) {
318     return kBadSampleRateError;
319   }
320   if (num_output_channels > num_input_channels) {
321     return kBadNumberChannelsError;
322   }
323   // Only mono and stereo supported currently.
324   if (num_input_channels > 2 || num_input_channels < 1 ||
325       num_output_channels > 2 || num_output_channels < 1 ||
326       num_reverse_channels > 2 || num_reverse_channels < 1) {
327     return kBadNumberChannelsError;
328   }
329   if (echo_control_mobile_->is_enabled() && sample_rate_hz > kSampleRate16kHz) {
330     LOG(LS_ERROR) << "AECM only supports 16 or 8 kHz sample rates";
331     return kUnsupportedComponentError;
332   }
333
334   sample_rate_hz_ = sample_rate_hz;
335   samples_per_channel_ = kChunkSizeMs * sample_rate_hz / 1000;
336   num_input_channels_ = num_input_channels;
337   num_output_channels_ = num_output_channels;
338   num_reverse_channels_ = num_reverse_channels;
339
340   if (sample_rate_hz_ == kSampleRate32kHz) {
341     split_sample_rate_hz_ = kSampleRate16kHz;
342   } else {
343     split_sample_rate_hz_ = sample_rate_hz_;
344   }
345
346   return InitializeLocked();
347 }
348
349 int AudioProcessingImpl::ProcessStream(AudioFrame* frame) {
350   CriticalSectionScoped crit_scoped(crit_);
351   int err = kNoError;
352
353   if (frame == NULL) {
354     return kNullPointerError;
355   }
356   // TODO(ajm): We now always set the output channels equal to the input
357   // channels here. Remove the ability to downmix entirely.
358   RETURN_ON_ERR(MaybeInitializeLocked(frame->sample_rate_hz_,
359       frame->num_channels_, frame->num_channels_, num_reverse_channels_));
360   if (frame->samples_per_channel_ != samples_per_channel_) {
361     return kBadDataLengthError;
362   }
363
364 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
365   if (debug_file_->Open()) {
366     event_msg_->set_type(audioproc::Event::STREAM);
367     audioproc::Stream* msg = event_msg_->mutable_stream();
368     const size_t data_size = sizeof(int16_t) *
369                              frame->samples_per_channel_ *
370                              frame->num_channels_;
371     msg->set_input_data(frame->data_, data_size);
372     msg->set_delay(stream_delay_ms_);
373     msg->set_drift(echo_cancellation_->stream_drift_samples());
374     msg->set_level(gain_control_->stream_analog_level());
375     msg->set_keypress(key_pressed_);
376   }
377 #endif
378
379   capture_audio_->DeinterleaveFrom(frame);
380
381   // TODO(ajm): experiment with mixing and AEC placement.
382   if (num_output_channels_ < num_input_channels_) {
383     capture_audio_->Mix(num_output_channels_);
384     frame->num_channels_ = num_output_channels_;
385   }
386
387   bool data_processed = is_data_processed();
388   if (analysis_needed(data_processed)) {
389     for (int i = 0; i < num_output_channels_; i++) {
390       // Split into a low and high band.
391       WebRtcSpl_AnalysisQMF(capture_audio_->data(i),
392                             capture_audio_->samples_per_channel(),
393                             capture_audio_->low_pass_split_data(i),
394                             capture_audio_->high_pass_split_data(i),
395                             capture_audio_->analysis_filter_state1(i),
396                             capture_audio_->analysis_filter_state2(i));
397     }
398   }
399
400   err = high_pass_filter_->ProcessCaptureAudio(capture_audio_);
401   if (err != kNoError) {
402     return err;
403   }
404
405   err = gain_control_->AnalyzeCaptureAudio(capture_audio_);
406   if (err != kNoError) {
407     return err;
408   }
409
410   err = echo_cancellation_->ProcessCaptureAudio(capture_audio_);
411   if (err != kNoError) {
412     return err;
413   }
414
415   if (echo_control_mobile_->is_enabled() &&
416       noise_suppression_->is_enabled()) {
417     capture_audio_->CopyLowPassToReference();
418   }
419
420   err = noise_suppression_->ProcessCaptureAudio(capture_audio_);
421   if (err != kNoError) {
422     return err;
423   }
424
425   err = echo_control_mobile_->ProcessCaptureAudio(capture_audio_);
426   if (err != kNoError) {
427     return err;
428   }
429
430   err = voice_detection_->ProcessCaptureAudio(capture_audio_);
431   if (err != kNoError) {
432     return err;
433   }
434
435   err = gain_control_->ProcessCaptureAudio(capture_audio_);
436   if (err != kNoError) {
437     return err;
438   }
439
440   if (synthesis_needed(data_processed)) {
441     for (int i = 0; i < num_output_channels_; i++) {
442       // Recombine low and high bands.
443       WebRtcSpl_SynthesisQMF(capture_audio_->low_pass_split_data(i),
444                              capture_audio_->high_pass_split_data(i),
445                              capture_audio_->samples_per_split_channel(),
446                              capture_audio_->data(i),
447                              capture_audio_->synthesis_filter_state1(i),
448                              capture_audio_->synthesis_filter_state2(i));
449     }
450   }
451
452   // The level estimator operates on the recombined data.
453   err = level_estimator_->ProcessStream(capture_audio_);
454   if (err != kNoError) {
455     return err;
456   }
457
458   capture_audio_->InterleaveTo(frame, interleave_needed(data_processed));
459
460 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
461   if (debug_file_->Open()) {
462     audioproc::Stream* msg = event_msg_->mutable_stream();
463     const size_t data_size = sizeof(int16_t) *
464                              frame->samples_per_channel_ *
465                              frame->num_channels_;
466     msg->set_output_data(frame->data_, data_size);
467     err = WriteMessageToDebugFile();
468     if (err != kNoError) {
469       return err;
470     }
471   }
472 #endif
473
474   was_stream_delay_set_ = false;
475   return kNoError;
476 }
477
478 // TODO(ajm): Have AnalyzeReverseStream accept sample rates not matching the
479 // primary stream and convert ourselves rather than having the user manage it.
480 // We can be smarter and use the splitting filter when appropriate. Similarly,
481 // perform downmixing here.
482 int AudioProcessingImpl::AnalyzeReverseStream(AudioFrame* frame) {
483   CriticalSectionScoped crit_scoped(crit_);
484   int err = kNoError;
485   if (frame == NULL) {
486     return kNullPointerError;
487   }
488   if (frame->sample_rate_hz_ != sample_rate_hz_) {
489     return kBadSampleRateError;
490   }
491   RETURN_ON_ERR(MaybeInitializeLocked(sample_rate_hz_, num_input_channels_,
492       num_output_channels_, frame->num_channels_));
493
494 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
495   if (debug_file_->Open()) {
496     event_msg_->set_type(audioproc::Event::REVERSE_STREAM);
497     audioproc::ReverseStream* msg = event_msg_->mutable_reverse_stream();
498     const size_t data_size = sizeof(int16_t) *
499                              frame->samples_per_channel_ *
500                              frame->num_channels_;
501     msg->set_data(frame->data_, data_size);
502     err = WriteMessageToDebugFile();
503     if (err != kNoError) {
504       return err;
505     }
506   }
507 #endif
508
509   render_audio_->DeinterleaveFrom(frame);
510
511   if (sample_rate_hz_ == kSampleRate32kHz) {
512     for (int i = 0; i < num_reverse_channels_; i++) {
513       // Split into low and high band.
514       WebRtcSpl_AnalysisQMF(render_audio_->data(i),
515                             render_audio_->samples_per_channel(),
516                             render_audio_->low_pass_split_data(i),
517                             render_audio_->high_pass_split_data(i),
518                             render_audio_->analysis_filter_state1(i),
519                             render_audio_->analysis_filter_state2(i));
520     }
521   }
522
523   // TODO(ajm): warnings possible from components?
524   err = echo_cancellation_->ProcessRenderAudio(render_audio_);
525   if (err != kNoError) {
526     return err;
527   }
528
529   err = echo_control_mobile_->ProcessRenderAudio(render_audio_);
530   if (err != kNoError) {
531     return err;
532   }
533
534   err = gain_control_->ProcessRenderAudio(render_audio_);
535   if (err != kNoError) {
536     return err;
537   }
538
539   return err;  // TODO(ajm): this is for returning warnings; necessary?
540 }
541
542 int AudioProcessingImpl::set_stream_delay_ms(int delay) {
543   Error retval = kNoError;
544   was_stream_delay_set_ = true;
545   delay += delay_offset_ms_;
546
547   if (delay < 0) {
548     delay = 0;
549     retval = kBadStreamParameterWarning;
550   }
551
552   // TODO(ajm): the max is rather arbitrarily chosen; investigate.
553   if (delay > 500) {
554     delay = 500;
555     retval = kBadStreamParameterWarning;
556   }
557
558   stream_delay_ms_ = delay;
559   return retval;
560 }
561
562 int AudioProcessingImpl::stream_delay_ms() const {
563   return stream_delay_ms_;
564 }
565
566 bool AudioProcessingImpl::was_stream_delay_set() const {
567   return was_stream_delay_set_;
568 }
569
570 void AudioProcessingImpl::set_delay_offset_ms(int offset) {
571   CriticalSectionScoped crit_scoped(crit_);
572   delay_offset_ms_ = offset;
573 }
574
575 int AudioProcessingImpl::delay_offset_ms() const {
576   return delay_offset_ms_;
577 }
578
579 void AudioProcessingImpl::set_stream_key_pressed(bool key_pressed) {
580   key_pressed_ = key_pressed;
581 }
582
583 bool AudioProcessingImpl::stream_key_pressed() const {
584   return key_pressed_;
585 }
586
587 int AudioProcessingImpl::StartDebugRecording(
588     const char filename[AudioProcessing::kMaxFilenameSize]) {
589   CriticalSectionScoped crit_scoped(crit_);
590   assert(kMaxFilenameSize == FileWrapper::kMaxFileNameSize);
591
592   if (filename == NULL) {
593     return kNullPointerError;
594   }
595
596 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
597   // Stop any ongoing recording.
598   if (debug_file_->Open()) {
599     if (debug_file_->CloseFile() == -1) {
600       return kFileError;
601     }
602   }
603
604   if (debug_file_->OpenFile(filename, false) == -1) {
605     debug_file_->CloseFile();
606     return kFileError;
607   }
608
609   int err = WriteInitMessage();
610   if (err != kNoError) {
611     return err;
612   }
613   return kNoError;
614 #else
615   return kUnsupportedFunctionError;
616 #endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
617 }
618
619 int AudioProcessingImpl::StartDebugRecording(FILE* handle) {
620   CriticalSectionScoped crit_scoped(crit_);
621
622   if (handle == NULL) {
623     return kNullPointerError;
624   }
625
626 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
627   // Stop any ongoing recording.
628   if (debug_file_->Open()) {
629     if (debug_file_->CloseFile() == -1) {
630       return kFileError;
631     }
632   }
633
634   if (debug_file_->OpenFromFileHandle(handle, true, false) == -1) {
635     return kFileError;
636   }
637
638   int err = WriteInitMessage();
639   if (err != kNoError) {
640     return err;
641   }
642   return kNoError;
643 #else
644   return kUnsupportedFunctionError;
645 #endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
646 }
647
648 int AudioProcessingImpl::StopDebugRecording() {
649   CriticalSectionScoped crit_scoped(crit_);
650
651 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
652   // We just return if recording hasn't started.
653   if (debug_file_->Open()) {
654     if (debug_file_->CloseFile() == -1) {
655       return kFileError;
656     }
657   }
658   return kNoError;
659 #else
660   return kUnsupportedFunctionError;
661 #endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
662 }
663
664 EchoCancellation* AudioProcessingImpl::echo_cancellation() const {
665   return echo_cancellation_;
666 }
667
668 EchoControlMobile* AudioProcessingImpl::echo_control_mobile() const {
669   return echo_control_mobile_;
670 }
671
672 GainControl* AudioProcessingImpl::gain_control() const {
673   return gain_control_;
674 }
675
676 HighPassFilter* AudioProcessingImpl::high_pass_filter() const {
677   return high_pass_filter_;
678 }
679
680 LevelEstimator* AudioProcessingImpl::level_estimator() const {
681   return level_estimator_;
682 }
683
684 NoiseSuppression* AudioProcessingImpl::noise_suppression() const {
685   return noise_suppression_;
686 }
687
688 VoiceDetection* AudioProcessingImpl::voice_detection() const {
689   return voice_detection_;
690 }
691
692 bool AudioProcessingImpl::is_data_processed() const {
693   int enabled_count = 0;
694   std::list<ProcessingComponent*>::const_iterator it;
695   for (it = component_list_.begin(); it != component_list_.end(); it++) {
696     if ((*it)->is_component_enabled()) {
697       enabled_count++;
698     }
699   }
700
701   // Data is unchanged if no components are enabled, or if only level_estimator_
702   // or voice_detection_ is enabled.
703   if (enabled_count == 0) {
704     return false;
705   } else if (enabled_count == 1) {
706     if (level_estimator_->is_enabled() || voice_detection_->is_enabled()) {
707       return false;
708     }
709   } else if (enabled_count == 2) {
710     if (level_estimator_->is_enabled() && voice_detection_->is_enabled()) {
711       return false;
712     }
713   }
714   return true;
715 }
716
717 bool AudioProcessingImpl::interleave_needed(bool is_data_processed) const {
718   // Check if we've upmixed or downmixed the audio.
719   return (num_output_channels_ != num_input_channels_ || is_data_processed);
720 }
721
722 bool AudioProcessingImpl::synthesis_needed(bool is_data_processed) const {
723   return (is_data_processed && sample_rate_hz_ == kSampleRate32kHz);
724 }
725
726 bool AudioProcessingImpl::analysis_needed(bool is_data_processed) const {
727   if (!is_data_processed && !voice_detection_->is_enabled()) {
728     // Only level_estimator_ is enabled.
729     return false;
730   } else if (sample_rate_hz_ == kSampleRate32kHz) {
731     // Something besides level_estimator_ is enabled, and we have super-wb.
732     return true;
733   }
734   return false;
735 }
736
737 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
738 int AudioProcessingImpl::WriteMessageToDebugFile() {
739   int32_t size = event_msg_->ByteSize();
740   if (size <= 0) {
741     return kUnspecifiedError;
742   }
743 #if defined(WEBRTC_ARCH_BIG_ENDIAN)
744   // TODO(ajm): Use little-endian "on the wire". For the moment, we can be
745   //            pretty safe in assuming little-endian.
746 #endif
747
748   if (!event_msg_->SerializeToString(&event_str_)) {
749     return kUnspecifiedError;
750   }
751
752   // Write message preceded by its size.
753   if (!debug_file_->Write(&size, sizeof(int32_t))) {
754     return kFileError;
755   }
756   if (!debug_file_->Write(event_str_.data(), event_str_.length())) {
757     return kFileError;
758   }
759
760   event_msg_->Clear();
761
762   return 0;
763 }
764
765 int AudioProcessingImpl::WriteInitMessage() {
766   event_msg_->set_type(audioproc::Event::INIT);
767   audioproc::Init* msg = event_msg_->mutable_init();
768   msg->set_sample_rate(sample_rate_hz_);
769   msg->set_device_sample_rate(echo_cancellation_->device_sample_rate_hz());
770   msg->set_num_input_channels(num_input_channels_);
771   msg->set_num_output_channels(num_output_channels_);
772   msg->set_num_reverse_channels(num_reverse_channels_);
773
774   int err = WriteMessageToDebugFile();
775   if (err != kNoError) {
776     return err;
777   }
778
779   return kNoError;
780 }
781 #endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
782 }  // namespace webrtc