blob: 3877a389dba46649146a12778ab38c2f4acd18b1 [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@webrtc.orga3736342012-03-16 21:36:00 +000031#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
leozwang@webrtc.org534e4952012-10-22 21:21:52 +000032#include "external/webrtc/webrtc/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() {
andrew@webrtc.org81865342012-10-27 00:28:27 +0000103 {
104 CriticalSectionScoped crit_scoped(crit_);
105 while (!component_list_.empty()) {
106 ProcessingComponent* component = component_list_.front();
107 component->Destroy();
108 delete component;
109 component_list_.pop_front();
110 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000111
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000112#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
andrew@webrtc.org81865342012-10-27 00:28:27 +0000113 if (debug_file_->Open()) {
114 debug_file_->CloseFile();
115 }
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000116#endif
ajm@google.com808e0e02011-08-03 21:08:51 +0000117
andrew@webrtc.org81865342012-10-27 00:28:27 +0000118 if (render_audio_) {
119 delete render_audio_;
120 render_audio_ = NULL;
121 }
122
123 if (capture_audio_) {
124 delete capture_audio_;
125 capture_audio_ = NULL;
126 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000127 }
128
andrew@webrtc.org16cfbe22012-08-29 16:58:25 +0000129 delete crit_;
130 crit_ = NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000131}
132
133CriticalSectionWrapper* AudioProcessingImpl::crit() const {
134 return crit_;
135}
136
137int AudioProcessingImpl::split_sample_rate_hz() const {
138 return split_sample_rate_hz_;
139}
140
141int AudioProcessingImpl::Initialize() {
andrew@webrtc.org40654032012-01-30 20:51:15 +0000142 CriticalSectionScoped crit_scoped(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000143 return InitializeLocked();
144}
145
146int AudioProcessingImpl::InitializeLocked() {
147 if (render_audio_ != NULL) {
148 delete render_audio_;
149 render_audio_ = NULL;
150 }
151
152 if (capture_audio_ != NULL) {
153 delete capture_audio_;
154 capture_audio_ = NULL;
155 }
156
ajm@google.com808e0e02011-08-03 21:08:51 +0000157 render_audio_ = new AudioBuffer(num_reverse_channels_,
niklase@google.com470e71d2011-07-07 08:21:25 +0000158 samples_per_channel_);
ajm@google.com808e0e02011-08-03 21:08:51 +0000159 capture_audio_ = new AudioBuffer(num_input_channels_,
niklase@google.com470e71d2011-07-07 08:21:25 +0000160 samples_per_channel_);
161
162 was_stream_delay_set_ = false;
163
164 // Initialize all components.
165 std::list<ProcessingComponent*>::iterator it;
andrew@webrtc.org81865342012-10-27 00:28:27 +0000166 for (it = component_list_.begin(); it != component_list_.end(); ++it) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000167 int err = (*it)->Initialize();
168 if (err != kNoError) {
169 return err;
170 }
171 }
172
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000173#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
ajm@google.com808e0e02011-08-03 21:08:51 +0000174 if (debug_file_->Open()) {
175 int err = WriteInitMessage();
176 if (err != kNoError) {
177 return err;
178 }
179 }
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000180#endif
ajm@google.com808e0e02011-08-03 21:08:51 +0000181
niklase@google.com470e71d2011-07-07 08:21:25 +0000182 return kNoError;
183}
184
185int AudioProcessingImpl::set_sample_rate_hz(int rate) {
andrew@webrtc.org40654032012-01-30 20:51:15 +0000186 CriticalSectionScoped crit_scoped(crit_);
andrew@webrtc.org81865342012-10-27 00:28:27 +0000187 if (rate == sample_rate_hz_) {
188 return kNoError;
189 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000190 if (rate != kSampleRate8kHz &&
191 rate != kSampleRate16kHz &&
192 rate != kSampleRate32kHz) {
193 return kBadParameterError;
194 }
195
196 sample_rate_hz_ = rate;
197 samples_per_channel_ = rate / 100;
198
199 if (sample_rate_hz_ == kSampleRate32kHz) {
200 split_sample_rate_hz_ = kSampleRate16kHz;
201 } else {
202 split_sample_rate_hz_ = sample_rate_hz_;
203 }
204
205 return InitializeLocked();
206}
207
208int AudioProcessingImpl::sample_rate_hz() const {
209 return sample_rate_hz_;
210}
211
212int AudioProcessingImpl::set_num_reverse_channels(int channels) {
andrew@webrtc.org40654032012-01-30 20:51:15 +0000213 CriticalSectionScoped crit_scoped(crit_);
andrew@webrtc.org81865342012-10-27 00:28:27 +0000214 if (channels == num_reverse_channels_) {
215 return kNoError;
216 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000217 // Only stereo supported currently.
218 if (channels > 2 || channels < 1) {
219 return kBadParameterError;
220 }
221
ajm@google.com808e0e02011-08-03 21:08:51 +0000222 num_reverse_channels_ = channels;
niklase@google.com470e71d2011-07-07 08:21:25 +0000223
224 return InitializeLocked();
225}
226
227int AudioProcessingImpl::num_reverse_channels() const {
ajm@google.com808e0e02011-08-03 21:08:51 +0000228 return num_reverse_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000229}
230
231int AudioProcessingImpl::set_num_channels(
232 int input_channels,
233 int output_channels) {
andrew@webrtc.org40654032012-01-30 20:51:15 +0000234 CriticalSectionScoped crit_scoped(crit_);
andrew@webrtc.org81865342012-10-27 00:28:27 +0000235 if (input_channels == num_input_channels_ &&
236 output_channels == num_output_channels_) {
237 return kNoError;
238 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000239 if (output_channels > input_channels) {
240 return kBadParameterError;
241 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000242 // Only stereo supported currently.
andrew@webrtc.org81865342012-10-27 00:28:27 +0000243 if (input_channels > 2 || input_channels < 1 ||
244 output_channels > 2 || output_channels < 1) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000245 return kBadParameterError;
246 }
247
ajm@google.com808e0e02011-08-03 21:08:51 +0000248 num_input_channels_ = input_channels;
249 num_output_channels_ = output_channels;
niklase@google.com470e71d2011-07-07 08:21:25 +0000250
251 return InitializeLocked();
252}
253
254int AudioProcessingImpl::num_input_channels() const {
ajm@google.com808e0e02011-08-03 21:08:51 +0000255 return num_input_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000256}
257
258int AudioProcessingImpl::num_output_channels() const {
ajm@google.com808e0e02011-08-03 21:08:51 +0000259 return num_output_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000260}
261
262int AudioProcessingImpl::ProcessStream(AudioFrame* frame) {
andrew@webrtc.org40654032012-01-30 20:51:15 +0000263 CriticalSectionScoped crit_scoped(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000264 int err = kNoError;
265
266 if (frame == NULL) {
267 return kNullPointerError;
268 }
269
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000270 if (frame->sample_rate_hz_ != sample_rate_hz_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000271 return kBadSampleRateError;
272 }
273
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000274 if (frame->num_channels_ != num_input_channels_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000275 return kBadNumberChannelsError;
276 }
277
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000278 if (frame->samples_per_channel_ != samples_per_channel_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000279 return kBadDataLengthError;
280 }
281
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000282#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000283 if (debug_file_->Open()) {
ajm@google.com808e0e02011-08-03 21:08:51 +0000284 event_msg_->set_type(audioproc::Event::STREAM);
285 audioproc::Stream* msg = event_msg_->mutable_stream();
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000286 const size_t data_size = sizeof(int16_t) *
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000287 frame->samples_per_channel_ *
288 frame->num_channels_;
289 msg->set_input_data(frame->data_, data_size);
ajm@google.com808e0e02011-08-03 21:08:51 +0000290 msg->set_delay(stream_delay_ms_);
291 msg->set_drift(echo_cancellation_->stream_drift_samples());
292 msg->set_level(gain_control_->stream_analog_level());
niklase@google.com470e71d2011-07-07 08:21:25 +0000293 }
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000294#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000295
296 capture_audio_->DeinterleaveFrom(frame);
297
298 // TODO(ajm): experiment with mixing and AEC placement.
ajm@google.com808e0e02011-08-03 21:08:51 +0000299 if (num_output_channels_ < num_input_channels_) {
300 capture_audio_->Mix(num_output_channels_);
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000301 frame->num_channels_ = num_output_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000302 }
303
andrew@webrtc.org369166a2012-04-24 18:38:03 +0000304 bool data_processed = is_data_processed();
305 if (analysis_needed(data_processed)) {
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000306 for (int i = 0; i < num_output_channels_; i++) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000307 // Split into a low and high band.
308 SplittingFilterAnalysis(capture_audio_->data(i),
309 capture_audio_->low_pass_split_data(i),
310 capture_audio_->high_pass_split_data(i),
311 capture_audio_->analysis_filter_state1(i),
312 capture_audio_->analysis_filter_state2(i));
313 }
314 }
315
316 err = high_pass_filter_->ProcessCaptureAudio(capture_audio_);
317 if (err != kNoError) {
318 return err;
319 }
320
321 err = gain_control_->AnalyzeCaptureAudio(capture_audio_);
322 if (err != kNoError) {
323 return err;
324 }
325
326 err = echo_cancellation_->ProcessCaptureAudio(capture_audio_);
327 if (err != kNoError) {
328 return err;
329 }
330
331 if (echo_control_mobile_->is_enabled() &&
332 noise_suppression_->is_enabled()) {
333 capture_audio_->CopyLowPassToReference();
334 }
335
336 err = noise_suppression_->ProcessCaptureAudio(capture_audio_);
337 if (err != kNoError) {
338 return err;
339 }
340
341 err = echo_control_mobile_->ProcessCaptureAudio(capture_audio_);
342 if (err != kNoError) {
343 return err;
344 }
345
346 err = voice_detection_->ProcessCaptureAudio(capture_audio_);
347 if (err != kNoError) {
348 return err;
349 }
350
351 err = gain_control_->ProcessCaptureAudio(capture_audio_);
352 if (err != kNoError) {
353 return err;
354 }
355
andrew@webrtc.org369166a2012-04-24 18:38:03 +0000356 if (synthesis_needed(data_processed)) {
ajm@google.com808e0e02011-08-03 21:08:51 +0000357 for (int i = 0; i < num_output_channels_; i++) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000358 // Recombine low and high bands.
359 SplittingFilterSynthesis(capture_audio_->low_pass_split_data(i),
360 capture_audio_->high_pass_split_data(i),
361 capture_audio_->data(i),
362 capture_audio_->synthesis_filter_state1(i),
363 capture_audio_->synthesis_filter_state2(i));
364 }
365 }
366
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000367 // The level estimator operates on the recombined data.
368 err = level_estimator_->ProcessStream(capture_audio_);
369 if (err != kNoError) {
370 return err;
371 }
372
andrew@webrtc.org369166a2012-04-24 18:38:03 +0000373 capture_audio_->InterleaveTo(frame, interleave_needed(data_processed));
niklase@google.com470e71d2011-07-07 08:21:25 +0000374
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000375#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
ajm@google.com808e0e02011-08-03 21:08:51 +0000376 if (debug_file_->Open()) {
377 audioproc::Stream* msg = event_msg_->mutable_stream();
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000378 const size_t data_size = sizeof(int16_t) *
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000379 frame->samples_per_channel_ *
380 frame->num_channels_;
381 msg->set_output_data(frame->data_, data_size);
ajm@google.com808e0e02011-08-03 21:08:51 +0000382 err = WriteMessageToDebugFile();
383 if (err != kNoError) {
384 return err;
385 }
386 }
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000387#endif
ajm@google.com808e0e02011-08-03 21:08:51 +0000388
andrew@webrtc.org1e916932011-11-29 18:28:57 +0000389 was_stream_delay_set_ = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000390 return kNoError;
391}
392
393int AudioProcessingImpl::AnalyzeReverseStream(AudioFrame* frame) {
andrew@webrtc.org40654032012-01-30 20:51:15 +0000394 CriticalSectionScoped crit_scoped(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000395 int err = kNoError;
396
397 if (frame == NULL) {
398 return kNullPointerError;
399 }
400
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000401 if (frame->sample_rate_hz_ != sample_rate_hz_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000402 return kBadSampleRateError;
403 }
404
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000405 if (frame->num_channels_ != num_reverse_channels_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000406 return kBadNumberChannelsError;
407 }
408
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000409 if (frame->samples_per_channel_ != samples_per_channel_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000410 return kBadDataLengthError;
411 }
412
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000413#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000414 if (debug_file_->Open()) {
ajm@google.com808e0e02011-08-03 21:08:51 +0000415 event_msg_->set_type(audioproc::Event::REVERSE_STREAM);
416 audioproc::ReverseStream* msg = event_msg_->mutable_reverse_stream();
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000417 const size_t data_size = sizeof(int16_t) *
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000418 frame->samples_per_channel_ *
419 frame->num_channels_;
420 msg->set_data(frame->data_, data_size);
ajm@google.com808e0e02011-08-03 21:08:51 +0000421 err = WriteMessageToDebugFile();
422 if (err != kNoError) {
423 return err;
niklase@google.com470e71d2011-07-07 08:21:25 +0000424 }
425 }
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000426#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000427
428 render_audio_->DeinterleaveFrom(frame);
429
430 // TODO(ajm): turn the splitting filter into a component?
431 if (sample_rate_hz_ == kSampleRate32kHz) {
ajm@google.com808e0e02011-08-03 21:08:51 +0000432 for (int i = 0; i < num_reverse_channels_; i++) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000433 // Split into low and high band.
434 SplittingFilterAnalysis(render_audio_->data(i),
435 render_audio_->low_pass_split_data(i),
436 render_audio_->high_pass_split_data(i),
437 render_audio_->analysis_filter_state1(i),
438 render_audio_->analysis_filter_state2(i));
439 }
440 }
441
442 // TODO(ajm): warnings possible from components?
443 err = echo_cancellation_->ProcessRenderAudio(render_audio_);
444 if (err != kNoError) {
445 return err;
446 }
447
448 err = echo_control_mobile_->ProcessRenderAudio(render_audio_);
449 if (err != kNoError) {
450 return err;
451 }
452
453 err = gain_control_->ProcessRenderAudio(render_audio_);
454 if (err != kNoError) {
455 return err;
456 }
457
niklase@google.com470e71d2011-07-07 08:21:25 +0000458 return err; // TODO(ajm): this is for returning warnings; necessary?
459}
460
461int AudioProcessingImpl::set_stream_delay_ms(int delay) {
andrew@webrtc.org5f23d642012-05-29 21:14:06 +0000462 Error retval = kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000463 was_stream_delay_set_ = true;
andrew@webrtc.org6f9f8172012-03-06 19:03:39 +0000464 delay += delay_offset_ms_;
465
niklase@google.com470e71d2011-07-07 08:21:25 +0000466 if (delay < 0) {
andrew@webrtc.org5f23d642012-05-29 21:14:06 +0000467 delay = 0;
468 retval = kBadStreamParameterWarning;
niklase@google.com470e71d2011-07-07 08:21:25 +0000469 }
470
471 // TODO(ajm): the max is rather arbitrarily chosen; investigate.
472 if (delay > 500) {
andrew@webrtc.org5f23d642012-05-29 21:14:06 +0000473 delay = 500;
474 retval = kBadStreamParameterWarning;
niklase@google.com470e71d2011-07-07 08:21:25 +0000475 }
476
477 stream_delay_ms_ = delay;
andrew@webrtc.org5f23d642012-05-29 21:14:06 +0000478 return retval;
niklase@google.com470e71d2011-07-07 08:21:25 +0000479}
480
481int AudioProcessingImpl::stream_delay_ms() const {
482 return stream_delay_ms_;
483}
484
485bool AudioProcessingImpl::was_stream_delay_set() const {
486 return was_stream_delay_set_;
487}
488
andrew@webrtc.org6f9f8172012-03-06 19:03:39 +0000489void AudioProcessingImpl::set_delay_offset_ms(int offset) {
490 CriticalSectionScoped crit_scoped(crit_);
491 delay_offset_ms_ = offset;
492}
493
494int AudioProcessingImpl::delay_offset_ms() const {
495 return delay_offset_ms_;
496}
497
niklase@google.com470e71d2011-07-07 08:21:25 +0000498int AudioProcessingImpl::StartDebugRecording(
499 const char filename[AudioProcessing::kMaxFilenameSize]) {
andrew@webrtc.org40654032012-01-30 20:51:15 +0000500 CriticalSectionScoped crit_scoped(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000501 assert(kMaxFilenameSize == FileWrapper::kMaxFileNameSize);
502
503 if (filename == NULL) {
504 return kNullPointerError;
505 }
506
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000507#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000508 // Stop any ongoing recording.
509 if (debug_file_->Open()) {
510 if (debug_file_->CloseFile() == -1) {
511 return kFileError;
512 }
513 }
514
515 if (debug_file_->OpenFile(filename, false) == -1) {
516 debug_file_->CloseFile();
517 return kFileError;
518 }
519
ajm@google.com808e0e02011-08-03 21:08:51 +0000520 int err = WriteInitMessage();
521 if (err != kNoError) {
522 return err;
niklase@google.com470e71d2011-07-07 08:21:25 +0000523 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000524 return kNoError;
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000525#else
526 return kUnsupportedFunctionError;
527#endif // WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000528}
529
530int AudioProcessingImpl::StopDebugRecording() {
andrew@webrtc.org40654032012-01-30 20:51:15 +0000531 CriticalSectionScoped crit_scoped(crit_);
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000532
533#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000534 // We just return if recording hasn't started.
535 if (debug_file_->Open()) {
536 if (debug_file_->CloseFile() == -1) {
537 return kFileError;
538 }
539 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000540 return kNoError;
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000541#else
542 return kUnsupportedFunctionError;
543#endif // WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000544}
545
546EchoCancellation* AudioProcessingImpl::echo_cancellation() const {
547 return echo_cancellation_;
548}
549
550EchoControlMobile* AudioProcessingImpl::echo_control_mobile() const {
551 return echo_control_mobile_;
552}
553
554GainControl* AudioProcessingImpl::gain_control() const {
555 return gain_control_;
556}
557
558HighPassFilter* AudioProcessingImpl::high_pass_filter() const {
559 return high_pass_filter_;
560}
561
562LevelEstimator* AudioProcessingImpl::level_estimator() const {
563 return level_estimator_;
564}
565
566NoiseSuppression* AudioProcessingImpl::noise_suppression() const {
567 return noise_suppression_;
568}
569
570VoiceDetection* AudioProcessingImpl::voice_detection() const {
571 return voice_detection_;
572}
573
niklase@google.com470e71d2011-07-07 08:21:25 +0000574WebRtc_Word32 AudioProcessingImpl::ChangeUniqueId(const WebRtc_Word32 id) {
andrew@webrtc.org40654032012-01-30 20:51:15 +0000575 CriticalSectionScoped crit_scoped(crit_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000576 id_ = id;
577
578 return kNoError;
579}
ajm@google.com808e0e02011-08-03 21:08:51 +0000580
andrew@webrtc.org369166a2012-04-24 18:38:03 +0000581bool AudioProcessingImpl::is_data_processed() const {
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000582 int enabled_count = 0;
583 std::list<ProcessingComponent*>::const_iterator it;
584 for (it = component_list_.begin(); it != component_list_.end(); it++) {
585 if ((*it)->is_component_enabled()) {
586 enabled_count++;
587 }
588 }
589
590 // Data is unchanged if no components are enabled, or if only level_estimator_
591 // or voice_detection_ is enabled.
592 if (enabled_count == 0) {
593 return false;
594 } else if (enabled_count == 1) {
595 if (level_estimator_->is_enabled() || voice_detection_->is_enabled()) {
596 return false;
597 }
598 } else if (enabled_count == 2) {
599 if (level_estimator_->is_enabled() && voice_detection_->is_enabled()) {
600 return false;
601 }
602 }
603 return true;
604}
605
andrew@webrtc.org369166a2012-04-24 18:38:03 +0000606bool AudioProcessingImpl::interleave_needed(bool is_data_processed) const {
607 // Check if we've upmixed or downmixed the audio.
608 return (num_output_channels_ != num_input_channels_ || is_data_processed);
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000609}
610
andrew@webrtc.org369166a2012-04-24 18:38:03 +0000611bool AudioProcessingImpl::synthesis_needed(bool is_data_processed) const {
612 return (is_data_processed && sample_rate_hz_ == kSampleRate32kHz);
613}
614
615bool AudioProcessingImpl::analysis_needed(bool is_data_processed) const {
616 if (!is_data_processed && !voice_detection_->is_enabled()) {
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000617 // Only level_estimator_ is enabled.
618 return false;
619 } else if (sample_rate_hz_ == kSampleRate32kHz) {
620 // Something besides level_estimator_ is enabled, and we have super-wb.
621 return true;
622 }
623 return false;
624}
625
626#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
ajm@google.com808e0e02011-08-03 21:08:51 +0000627int AudioProcessingImpl::WriteMessageToDebugFile() {
628 int32_t size = event_msg_->ByteSize();
629 if (size <= 0) {
630 return kUnspecifiedError;
631 }
632#if defined(WEBRTC_BIG_ENDIAN)
633 // TODO(ajm): Use little-endian "on the wire". For the moment, we can be
634 // pretty safe in assuming little-endian.
635#endif
636
637 if (!event_msg_->SerializeToString(&event_str_)) {
638 return kUnspecifiedError;
639 }
640
641 // Write message preceded by its size.
642 if (!debug_file_->Write(&size, sizeof(int32_t))) {
643 return kFileError;
644 }
645 if (!debug_file_->Write(event_str_.data(), event_str_.length())) {
646 return kFileError;
647 }
648
649 event_msg_->Clear();
650
651 return 0;
652}
653
654int AudioProcessingImpl::WriteInitMessage() {
655 event_msg_->set_type(audioproc::Event::INIT);
656 audioproc::Init* msg = event_msg_->mutable_init();
657 msg->set_sample_rate(sample_rate_hz_);
658 msg->set_device_sample_rate(echo_cancellation_->device_sample_rate_hz());
659 msg->set_num_input_channels(num_input_channels_);
660 msg->set_num_output_channels(num_output_channels_);
661 msg->set_num_reverse_channels(num_reverse_channels_);
662
663 int err = WriteMessageToDebugFile();
664 if (err != kNoError) {
665 return err;
666 }
667
668 return kNoError;
669}
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000670#endif // WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000671} // namespace webrtc