blob: 2dea0e93a2be55314348445134e9256f890de132 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
andrew@webrtc.org40654032012-01-30 20:51:15 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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 "audio_processing_impl.h"
12
ajm@google.com808e0e02011-08-03 21:08:51 +000013#include <assert.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000014
15#include "audio_buffer.h"
ajm@google.com808e0e02011-08-03 21:08:51 +000016#include "critical_section_wrapper.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000017#include "echo_cancellation_impl.h"
18#include "echo_control_mobile_impl.h"
ajm@google.com808e0e02011-08-03 21:08:51 +000019#include "file_wrapper.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000020#include "high_pass_filter_impl.h"
21#include "gain_control_impl.h"
22#include "level_estimator_impl.h"
ajm@google.com808e0e02011-08-03 21:08:51 +000023#include "module_common_types.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000024#include "noise_suppression_impl.h"
25#include "processing_component.h"
26#include "splitting_filter.h"
27#include "voice_detection_impl.h"
andrew@webrtc.org7bf26462011-12-03 00:03:31 +000028
29#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
30// Files generated at build-time by the protobuf compiler.
leozwang@google.comce9bfbb2011-08-03 23:34:31 +000031#ifdef WEBRTC_ANDROID
andrew@webrtc.org4d5d5c12011-10-19 01:40:33 +000032#include "external/webrtc/src/modules/audio_processing/debug.pb.h"
leozwang@google.comce9bfbb2011-08-03 23:34:31 +000033#else
ajm@google.com808e0e02011-08-03 21:08:51 +000034#include "webrtc/audio_processing/debug.pb.h"
leozwang@google.comce9bfbb2011-08-03 23:34:31 +000035#endif
andrew@webrtc.org7bf26462011-12-03 00:03:31 +000036#endif // WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +000037
38namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000039AudioProcessing* AudioProcessing::Create(int id) {
niklase@google.com470e71d2011-07-07 08:21:25 +000040
41 AudioProcessingImpl* apm = new AudioProcessingImpl(id);
42 if (apm->Initialize() != kNoError) {
43 delete apm;
44 apm = NULL;
45 }
46
47 return apm;
48}
49
50void AudioProcessing::Destroy(AudioProcessing* apm) {
51 delete static_cast<AudioProcessingImpl*>(apm);
52}
53
54AudioProcessingImpl::AudioProcessingImpl(int id)
55 : id_(id),
56 echo_cancellation_(NULL),
57 echo_control_mobile_(NULL),
58 gain_control_(NULL),
59 high_pass_filter_(NULL),
60 level_estimator_(NULL),
61 noise_suppression_(NULL),
62 voice_detection_(NULL),
niklase@google.com470e71d2011-07-07 08:21:25 +000063 crit_(CriticalSectionWrapper::CreateCriticalSection()),
64 render_audio_(NULL),
65 capture_audio_(NULL),
andrew@webrtc.org7bf26462011-12-03 00:03:31 +000066#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
67 debug_file_(FileWrapper::Create()),
68 event_msg_(new audioproc::Event()),
69#endif
niklase@google.com470e71d2011-07-07 08:21:25 +000070 sample_rate_hz_(kSampleRate16kHz),
71 split_sample_rate_hz_(kSampleRate16kHz),
72 samples_per_channel_(sample_rate_hz_ / 100),
73 stream_delay_ms_(0),
andrew@webrtc.org6f9f8172012-03-06 19:03:39 +000074 delay_offset_ms_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +000075 was_stream_delay_set_(false),
ajm@google.com808e0e02011-08-03 21:08:51 +000076 num_reverse_channels_(1),
77 num_input_channels_(1),
78 num_output_channels_(1) {
niklase@google.com470e71d2011-07-07 08:21:25 +000079
80 echo_cancellation_ = new EchoCancellationImpl(this);
81 component_list_.push_back(echo_cancellation_);
82
83 echo_control_mobile_ = new EchoControlMobileImpl(this);
84 component_list_.push_back(echo_control_mobile_);
85
86 gain_control_ = new GainControlImpl(this);
87 component_list_.push_back(gain_control_);
88
89 high_pass_filter_ = new HighPassFilterImpl(this);
90 component_list_.push_back(high_pass_filter_);
91
92 level_estimator_ = new LevelEstimatorImpl(this);
93 component_list_.push_back(level_estimator_);
94
95 noise_suppression_ = new NoiseSuppressionImpl(this);
96 component_list_.push_back(noise_suppression_);
97
98 voice_detection_ = new VoiceDetectionImpl(this);
99 component_list_.push_back(voice_detection_);
100}
101
102AudioProcessingImpl::~AudioProcessingImpl() {
103 while (!component_list_.empty()) {
104 ProcessingComponent* component = component_list_.front();
105 component->Destroy();
106 delete component;
107 component_list_.pop_front();
108 }
109
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000110#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000111 if (debug_file_->Open()) {
112 debug_file_->CloseFile();
113 }
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000114#endif
ajm@google.com808e0e02011-08-03 21:08:51 +0000115
niklase@google.com470e71d2011-07-07 08:21:25 +0000116 delete crit_;
117 crit_ = NULL;
118
ajm@google.com808e0e02011-08-03 21:08:51 +0000119 if (render_audio_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000120 delete render_audio_;
121 render_audio_ = NULL;
122 }
123
ajm@google.com808e0e02011-08-03 21:08:51 +0000124 if (capture_audio_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000125 delete capture_audio_;
126 capture_audio_ = NULL;
127 }
128}
129
130CriticalSectionWrapper* AudioProcessingImpl::crit() const {
131 return crit_;
132}
133
134int AudioProcessingImpl::split_sample_rate_hz() const {
135 return split_sample_rate_hz_;
136}
137
138int AudioProcessingImpl::Initialize() {
andrew@webrtc.org40654032012-01-30 20:51:15 +0000139 CriticalSectionScoped crit_scoped(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000140 return InitializeLocked();
141}
142
143int AudioProcessingImpl::InitializeLocked() {
144 if (render_audio_ != NULL) {
145 delete render_audio_;
146 render_audio_ = NULL;
147 }
148
149 if (capture_audio_ != NULL) {
150 delete capture_audio_;
151 capture_audio_ = NULL;
152 }
153
ajm@google.com808e0e02011-08-03 21:08:51 +0000154 render_audio_ = new AudioBuffer(num_reverse_channels_,
niklase@google.com470e71d2011-07-07 08:21:25 +0000155 samples_per_channel_);
ajm@google.com808e0e02011-08-03 21:08:51 +0000156 capture_audio_ = new AudioBuffer(num_input_channels_,
niklase@google.com470e71d2011-07-07 08:21:25 +0000157 samples_per_channel_);
158
159 was_stream_delay_set_ = false;
160
161 // Initialize all components.
162 std::list<ProcessingComponent*>::iterator it;
163 for (it = component_list_.begin(); it != component_list_.end(); it++) {
164 int err = (*it)->Initialize();
165 if (err != kNoError) {
166 return err;
167 }
168 }
169
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000170#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
ajm@google.com808e0e02011-08-03 21:08:51 +0000171 if (debug_file_->Open()) {
172 int err = WriteInitMessage();
173 if (err != kNoError) {
174 return err;
175 }
176 }
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000177#endif
ajm@google.com808e0e02011-08-03 21:08:51 +0000178
niklase@google.com470e71d2011-07-07 08:21:25 +0000179 return kNoError;
180}
181
182int AudioProcessingImpl::set_sample_rate_hz(int rate) {
andrew@webrtc.org40654032012-01-30 20:51:15 +0000183 CriticalSectionScoped crit_scoped(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000184 if (rate != kSampleRate8kHz &&
185 rate != kSampleRate16kHz &&
186 rate != kSampleRate32kHz) {
187 return kBadParameterError;
188 }
189
190 sample_rate_hz_ = rate;
191 samples_per_channel_ = rate / 100;
192
193 if (sample_rate_hz_ == kSampleRate32kHz) {
194 split_sample_rate_hz_ = kSampleRate16kHz;
195 } else {
196 split_sample_rate_hz_ = sample_rate_hz_;
197 }
198
199 return InitializeLocked();
200}
201
202int AudioProcessingImpl::sample_rate_hz() const {
203 return sample_rate_hz_;
204}
205
206int AudioProcessingImpl::set_num_reverse_channels(int channels) {
andrew@webrtc.org40654032012-01-30 20:51:15 +0000207 CriticalSectionScoped crit_scoped(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000208 // Only stereo supported currently.
209 if (channels > 2 || channels < 1) {
210 return kBadParameterError;
211 }
212
ajm@google.com808e0e02011-08-03 21:08:51 +0000213 num_reverse_channels_ = channels;
niklase@google.com470e71d2011-07-07 08:21:25 +0000214
215 return InitializeLocked();
216}
217
218int AudioProcessingImpl::num_reverse_channels() const {
ajm@google.com808e0e02011-08-03 21:08:51 +0000219 return num_reverse_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000220}
221
222int AudioProcessingImpl::set_num_channels(
223 int input_channels,
224 int output_channels) {
andrew@webrtc.org40654032012-01-30 20:51:15 +0000225 CriticalSectionScoped crit_scoped(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000226 if (output_channels > input_channels) {
227 return kBadParameterError;
228 }
229
230 // Only stereo supported currently.
231 if (input_channels > 2 || input_channels < 1) {
232 return kBadParameterError;
233 }
234
235 if (output_channels > 2 || output_channels < 1) {
236 return kBadParameterError;
237 }
238
ajm@google.com808e0e02011-08-03 21:08:51 +0000239 num_input_channels_ = input_channels;
240 num_output_channels_ = output_channels;
niklase@google.com470e71d2011-07-07 08:21:25 +0000241
242 return InitializeLocked();
243}
244
245int AudioProcessingImpl::num_input_channels() const {
ajm@google.com808e0e02011-08-03 21:08:51 +0000246 return num_input_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000247}
248
249int AudioProcessingImpl::num_output_channels() const {
ajm@google.com808e0e02011-08-03 21:08:51 +0000250 return num_output_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000251}
252
253int AudioProcessingImpl::ProcessStream(AudioFrame* frame) {
andrew@webrtc.org40654032012-01-30 20:51:15 +0000254 CriticalSectionScoped crit_scoped(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000255 int err = kNoError;
256
257 if (frame == NULL) {
258 return kNullPointerError;
259 }
260
xians@google.com0b0665a2011-08-08 08:18:44 +0000261 if (frame->_frequencyInHz != sample_rate_hz_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000262 return kBadSampleRateError;
263 }
264
ajm@google.com808e0e02011-08-03 21:08:51 +0000265 if (frame->_audioChannel != num_input_channels_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000266 return kBadNumberChannelsError;
267 }
268
269 if (frame->_payloadDataLengthInSamples != samples_per_channel_) {
270 return kBadDataLengthError;
271 }
272
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000273#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000274 if (debug_file_->Open()) {
ajm@google.com808e0e02011-08-03 21:08:51 +0000275 event_msg_->set_type(audioproc::Event::STREAM);
276 audioproc::Stream* msg = event_msg_->mutable_stream();
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000277 const size_t data_size = sizeof(int16_t) *
ajm@google.com808e0e02011-08-03 21:08:51 +0000278 frame->_payloadDataLengthInSamples *
279 frame->_audioChannel;
280 msg->set_input_data(frame->_payloadData, data_size);
281 msg->set_delay(stream_delay_ms_);
282 msg->set_drift(echo_cancellation_->stream_drift_samples());
283 msg->set_level(gain_control_->stream_analog_level());
niklase@google.com470e71d2011-07-07 08:21:25 +0000284 }
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000285#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000286
287 capture_audio_->DeinterleaveFrom(frame);
288
289 // TODO(ajm): experiment with mixing and AEC placement.
ajm@google.com808e0e02011-08-03 21:08:51 +0000290 if (num_output_channels_ < num_input_channels_) {
291 capture_audio_->Mix(num_output_channels_);
ajm@google.com808e0e02011-08-03 21:08:51 +0000292 frame->_audioChannel = num_output_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000293 }
294
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000295 bool data_changed = stream_data_changed();
296 if (analysis_needed(data_changed)) {
297 for (int i = 0; i < num_output_channels_; i++) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000298 // Split into a low and high band.
299 SplittingFilterAnalysis(capture_audio_->data(i),
300 capture_audio_->low_pass_split_data(i),
301 capture_audio_->high_pass_split_data(i),
302 capture_audio_->analysis_filter_state1(i),
303 capture_audio_->analysis_filter_state2(i));
304 }
305 }
306
307 err = high_pass_filter_->ProcessCaptureAudio(capture_audio_);
308 if (err != kNoError) {
309 return err;
310 }
311
312 err = gain_control_->AnalyzeCaptureAudio(capture_audio_);
313 if (err != kNoError) {
314 return err;
315 }
316
317 err = echo_cancellation_->ProcessCaptureAudio(capture_audio_);
318 if (err != kNoError) {
319 return err;
320 }
321
322 if (echo_control_mobile_->is_enabled() &&
323 noise_suppression_->is_enabled()) {
324 capture_audio_->CopyLowPassToReference();
325 }
326
327 err = noise_suppression_->ProcessCaptureAudio(capture_audio_);
328 if (err != kNoError) {
329 return err;
330 }
331
332 err = echo_control_mobile_->ProcessCaptureAudio(capture_audio_);
333 if (err != kNoError) {
334 return err;
335 }
336
337 err = voice_detection_->ProcessCaptureAudio(capture_audio_);
338 if (err != kNoError) {
339 return err;
340 }
341
342 err = gain_control_->ProcessCaptureAudio(capture_audio_);
343 if (err != kNoError) {
344 return err;
345 }
346
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000347 if (synthesis_needed(data_changed)) {
ajm@google.com808e0e02011-08-03 21:08:51 +0000348 for (int i = 0; i < num_output_channels_; i++) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000349 // Recombine low and high bands.
350 SplittingFilterSynthesis(capture_audio_->low_pass_split_data(i),
351 capture_audio_->high_pass_split_data(i),
352 capture_audio_->data(i),
353 capture_audio_->synthesis_filter_state1(i),
354 capture_audio_->synthesis_filter_state2(i));
355 }
356 }
357
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000358 // The level estimator operates on the recombined data.
359 err = level_estimator_->ProcessStream(capture_audio_);
360 if (err != kNoError) {
361 return err;
362 }
363
364 capture_audio_->InterleaveTo(frame, data_changed);
niklase@google.com470e71d2011-07-07 08:21:25 +0000365
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000366#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
ajm@google.com808e0e02011-08-03 21:08:51 +0000367 if (debug_file_->Open()) {
368 audioproc::Stream* msg = event_msg_->mutable_stream();
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000369 const size_t data_size = sizeof(int16_t) *
ajm@google.com808e0e02011-08-03 21:08:51 +0000370 frame->_payloadDataLengthInSamples *
371 frame->_audioChannel;
372 msg->set_output_data(frame->_payloadData, data_size);
373 err = WriteMessageToDebugFile();
374 if (err != kNoError) {
375 return err;
376 }
377 }
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000378#endif
ajm@google.com808e0e02011-08-03 21:08:51 +0000379
andrew@webrtc.org1e916932011-11-29 18:28:57 +0000380 was_stream_delay_set_ = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000381 return kNoError;
382}
383
384int AudioProcessingImpl::AnalyzeReverseStream(AudioFrame* frame) {
andrew@webrtc.org40654032012-01-30 20:51:15 +0000385 CriticalSectionScoped crit_scoped(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000386 int err = kNoError;
387
388 if (frame == NULL) {
389 return kNullPointerError;
390 }
391
xians@google.com0b0665a2011-08-08 08:18:44 +0000392 if (frame->_frequencyInHz != sample_rate_hz_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000393 return kBadSampleRateError;
394 }
395
ajm@google.com808e0e02011-08-03 21:08:51 +0000396 if (frame->_audioChannel != num_reverse_channels_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000397 return kBadNumberChannelsError;
398 }
399
400 if (frame->_payloadDataLengthInSamples != samples_per_channel_) {
401 return kBadDataLengthError;
402 }
403
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000404#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000405 if (debug_file_->Open()) {
ajm@google.com808e0e02011-08-03 21:08:51 +0000406 event_msg_->set_type(audioproc::Event::REVERSE_STREAM);
407 audioproc::ReverseStream* msg = event_msg_->mutable_reverse_stream();
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000408 const size_t data_size = sizeof(int16_t) *
ajm@google.com808e0e02011-08-03 21:08:51 +0000409 frame->_payloadDataLengthInSamples *
410 frame->_audioChannel;
411 msg->set_data(frame->_payloadData, data_size);
412 err = WriteMessageToDebugFile();
413 if (err != kNoError) {
414 return err;
niklase@google.com470e71d2011-07-07 08:21:25 +0000415 }
416 }
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000417#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000418
419 render_audio_->DeinterleaveFrom(frame);
420
421 // TODO(ajm): turn the splitting filter into a component?
422 if (sample_rate_hz_ == kSampleRate32kHz) {
ajm@google.com808e0e02011-08-03 21:08:51 +0000423 for (int i = 0; i < num_reverse_channels_; i++) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000424 // Split into low and high band.
425 SplittingFilterAnalysis(render_audio_->data(i),
426 render_audio_->low_pass_split_data(i),
427 render_audio_->high_pass_split_data(i),
428 render_audio_->analysis_filter_state1(i),
429 render_audio_->analysis_filter_state2(i));
430 }
431 }
432
433 // TODO(ajm): warnings possible from components?
434 err = echo_cancellation_->ProcessRenderAudio(render_audio_);
435 if (err != kNoError) {
436 return err;
437 }
438
439 err = echo_control_mobile_->ProcessRenderAudio(render_audio_);
440 if (err != kNoError) {
441 return err;
442 }
443
444 err = gain_control_->ProcessRenderAudio(render_audio_);
445 if (err != kNoError) {
446 return err;
447 }
448
niklase@google.com470e71d2011-07-07 08:21:25 +0000449 return err; // TODO(ajm): this is for returning warnings; necessary?
450}
451
452int AudioProcessingImpl::set_stream_delay_ms(int delay) {
453 was_stream_delay_set_ = true;
andrew@webrtc.org6f9f8172012-03-06 19:03:39 +0000454 delay += delay_offset_ms_;
455
niklase@google.com470e71d2011-07-07 08:21:25 +0000456 if (delay < 0) {
457 return kBadParameterError;
458 }
459
460 // TODO(ajm): the max is rather arbitrarily chosen; investigate.
461 if (delay > 500) {
462 stream_delay_ms_ = 500;
463 return kBadStreamParameterWarning;
464 }
465
466 stream_delay_ms_ = delay;
467 return kNoError;
468}
469
470int AudioProcessingImpl::stream_delay_ms() const {
471 return stream_delay_ms_;
472}
473
474bool AudioProcessingImpl::was_stream_delay_set() const {
475 return was_stream_delay_set_;
476}
477
andrew@webrtc.org6f9f8172012-03-06 19:03:39 +0000478void AudioProcessingImpl::set_delay_offset_ms(int offset) {
479 CriticalSectionScoped crit_scoped(crit_);
480 delay_offset_ms_ = offset;
481}
482
483int AudioProcessingImpl::delay_offset_ms() const {
484 return delay_offset_ms_;
485}
486
niklase@google.com470e71d2011-07-07 08:21:25 +0000487int AudioProcessingImpl::StartDebugRecording(
488 const char filename[AudioProcessing::kMaxFilenameSize]) {
andrew@webrtc.org40654032012-01-30 20:51:15 +0000489 CriticalSectionScoped crit_scoped(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000490 assert(kMaxFilenameSize == FileWrapper::kMaxFileNameSize);
491
492 if (filename == NULL) {
493 return kNullPointerError;
494 }
495
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000496#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000497 // Stop any ongoing recording.
498 if (debug_file_->Open()) {
499 if (debug_file_->CloseFile() == -1) {
500 return kFileError;
501 }
502 }
503
504 if (debug_file_->OpenFile(filename, false) == -1) {
505 debug_file_->CloseFile();
506 return kFileError;
507 }
508
ajm@google.com808e0e02011-08-03 21:08:51 +0000509 int err = WriteInitMessage();
510 if (err != kNoError) {
511 return err;
niklase@google.com470e71d2011-07-07 08:21:25 +0000512 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000513 return kNoError;
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000514#else
515 return kUnsupportedFunctionError;
516#endif // WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000517}
518
519int AudioProcessingImpl::StopDebugRecording() {
andrew@webrtc.org40654032012-01-30 20:51:15 +0000520 CriticalSectionScoped crit_scoped(crit_);
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000521
522#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000523 // We just return if recording hasn't started.
524 if (debug_file_->Open()) {
525 if (debug_file_->CloseFile() == -1) {
526 return kFileError;
527 }
528 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000529 return kNoError;
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000530#else
531 return kUnsupportedFunctionError;
532#endif // WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000533}
534
535EchoCancellation* AudioProcessingImpl::echo_cancellation() const {
536 return echo_cancellation_;
537}
538
539EchoControlMobile* AudioProcessingImpl::echo_control_mobile() const {
540 return echo_control_mobile_;
541}
542
543GainControl* AudioProcessingImpl::gain_control() const {
544 return gain_control_;
545}
546
547HighPassFilter* AudioProcessingImpl::high_pass_filter() const {
548 return high_pass_filter_;
549}
550
551LevelEstimator* AudioProcessingImpl::level_estimator() const {
552 return level_estimator_;
553}
554
555NoiseSuppression* AudioProcessingImpl::noise_suppression() const {
556 return noise_suppression_;
557}
558
559VoiceDetection* AudioProcessingImpl::voice_detection() const {
560 return voice_detection_;
561}
562
niklase@google.com470e71d2011-07-07 08:21:25 +0000563WebRtc_Word32 AudioProcessingImpl::ChangeUniqueId(const WebRtc_Word32 id) {
andrew@webrtc.org40654032012-01-30 20:51:15 +0000564 CriticalSectionScoped crit_scoped(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000565 id_ = id;
566
567 return kNoError;
568}
ajm@google.com808e0e02011-08-03 21:08:51 +0000569
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000570bool AudioProcessingImpl::stream_data_changed() const {
571 int enabled_count = 0;
572 std::list<ProcessingComponent*>::const_iterator it;
573 for (it = component_list_.begin(); it != component_list_.end(); it++) {
574 if ((*it)->is_component_enabled()) {
575 enabled_count++;
576 }
577 }
578
579 // Data is unchanged if no components are enabled, or if only level_estimator_
580 // or voice_detection_ is enabled.
581 if (enabled_count == 0) {
582 return false;
583 } else if (enabled_count == 1) {
584 if (level_estimator_->is_enabled() || voice_detection_->is_enabled()) {
585 return false;
586 }
587 } else if (enabled_count == 2) {
588 if (level_estimator_->is_enabled() && voice_detection_->is_enabled()) {
589 return false;
590 }
591 }
592 return true;
593}
594
595bool AudioProcessingImpl::synthesis_needed(bool stream_data_changed) const {
596 return (stream_data_changed && sample_rate_hz_ == kSampleRate32kHz);
597}
598
599bool AudioProcessingImpl::analysis_needed(bool stream_data_changed) const {
600 if (!stream_data_changed && !voice_detection_->is_enabled()) {
601 // Only level_estimator_ is enabled.
602 return false;
603 } else if (sample_rate_hz_ == kSampleRate32kHz) {
604 // Something besides level_estimator_ is enabled, and we have super-wb.
605 return true;
606 }
607 return false;
608}
609
610#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
ajm@google.com808e0e02011-08-03 21:08:51 +0000611int AudioProcessingImpl::WriteMessageToDebugFile() {
612 int32_t size = event_msg_->ByteSize();
613 if (size <= 0) {
614 return kUnspecifiedError;
615 }
616#if defined(WEBRTC_BIG_ENDIAN)
617 // TODO(ajm): Use little-endian "on the wire". For the moment, we can be
618 // pretty safe in assuming little-endian.
619#endif
620
621 if (!event_msg_->SerializeToString(&event_str_)) {
622 return kUnspecifiedError;
623 }
624
625 // Write message preceded by its size.
626 if (!debug_file_->Write(&size, sizeof(int32_t))) {
627 return kFileError;
628 }
629 if (!debug_file_->Write(event_str_.data(), event_str_.length())) {
630 return kFileError;
631 }
632
633 event_msg_->Clear();
634
635 return 0;
636}
637
638int AudioProcessingImpl::WriteInitMessage() {
639 event_msg_->set_type(audioproc::Event::INIT);
640 audioproc::Init* msg = event_msg_->mutable_init();
641 msg->set_sample_rate(sample_rate_hz_);
642 msg->set_device_sample_rate(echo_cancellation_->device_sample_rate_hz());
643 msg->set_num_input_channels(num_input_channels_);
644 msg->set_num_output_channels(num_output_channels_);
645 msg->set_num_reverse_channels(num_reverse_channels_);
646
647 int err = WriteMessageToDebugFile();
648 if (err != kNoError) {
649 return err;
650 }
651
652 return kNoError;
653}
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000654#endif // WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000655} // namespace webrtc