blob: 8ce9c21e555730f8f9bbd0224ebc26f2dfd4ae13 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
2 * Copyright (c) 2011 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 "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) {
40 /*WEBRTC_TRACE(webrtc::kTraceModuleCall,
41 webrtc::kTraceAudioProcessing,
42 id,
43 "AudioProcessing::Create()");*/
44
45 AudioProcessingImpl* apm = new AudioProcessingImpl(id);
46 if (apm->Initialize() != kNoError) {
47 delete apm;
48 apm = NULL;
49 }
50
51 return apm;
52}
53
54void AudioProcessing::Destroy(AudioProcessing* apm) {
55 delete static_cast<AudioProcessingImpl*>(apm);
56}
57
58AudioProcessingImpl::AudioProcessingImpl(int id)
59 : id_(id),
60 echo_cancellation_(NULL),
61 echo_control_mobile_(NULL),
62 gain_control_(NULL),
63 high_pass_filter_(NULL),
64 level_estimator_(NULL),
65 noise_suppression_(NULL),
66 voice_detection_(NULL),
niklase@google.com470e71d2011-07-07 08:21:25 +000067 crit_(CriticalSectionWrapper::CreateCriticalSection()),
68 render_audio_(NULL),
69 capture_audio_(NULL),
andrew@webrtc.org7bf26462011-12-03 00:03:31 +000070#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
71 debug_file_(FileWrapper::Create()),
72 event_msg_(new audioproc::Event()),
73#endif
niklase@google.com470e71d2011-07-07 08:21:25 +000074 sample_rate_hz_(kSampleRate16kHz),
75 split_sample_rate_hz_(kSampleRate16kHz),
76 samples_per_channel_(sample_rate_hz_ / 100),
77 stream_delay_ms_(0),
78 was_stream_delay_set_(false),
ajm@google.com808e0e02011-08-03 21:08:51 +000079 num_reverse_channels_(1),
80 num_input_channels_(1),
81 num_output_channels_(1) {
niklase@google.com470e71d2011-07-07 08:21:25 +000082
83 echo_cancellation_ = new EchoCancellationImpl(this);
84 component_list_.push_back(echo_cancellation_);
85
86 echo_control_mobile_ = new EchoControlMobileImpl(this);
87 component_list_.push_back(echo_control_mobile_);
88
89 gain_control_ = new GainControlImpl(this);
90 component_list_.push_back(gain_control_);
91
92 high_pass_filter_ = new HighPassFilterImpl(this);
93 component_list_.push_back(high_pass_filter_);
94
95 level_estimator_ = new LevelEstimatorImpl(this);
96 component_list_.push_back(level_estimator_);
97
98 noise_suppression_ = new NoiseSuppressionImpl(this);
99 component_list_.push_back(noise_suppression_);
100
101 voice_detection_ = new VoiceDetectionImpl(this);
102 component_list_.push_back(voice_detection_);
103}
104
105AudioProcessingImpl::~AudioProcessingImpl() {
106 while (!component_list_.empty()) {
107 ProcessingComponent* component = component_list_.front();
108 component->Destroy();
109 delete component;
110 component_list_.pop_front();
111 }
112
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000113#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000114 if (debug_file_->Open()) {
115 debug_file_->CloseFile();
116 }
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000117#endif
ajm@google.com808e0e02011-08-03 21:08:51 +0000118
niklase@google.com470e71d2011-07-07 08:21:25 +0000119 delete crit_;
120 crit_ = NULL;
121
ajm@google.com808e0e02011-08-03 21:08:51 +0000122 if (render_audio_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000123 delete render_audio_;
124 render_audio_ = NULL;
125 }
126
ajm@google.com808e0e02011-08-03 21:08:51 +0000127 if (capture_audio_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000128 delete capture_audio_;
129 capture_audio_ = NULL;
130 }
131}
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() {
142 CriticalSectionScoped crit_scoped(*crit_);
143 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;
166 for (it = component_list_.begin(); it != component_list_.end(); it++) {
167 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) {
186 CriticalSectionScoped crit_scoped(*crit_);
187 if (rate != kSampleRate8kHz &&
188 rate != kSampleRate16kHz &&
189 rate != kSampleRate32kHz) {
190 return kBadParameterError;
191 }
192
193 sample_rate_hz_ = rate;
194 samples_per_channel_ = rate / 100;
195
196 if (sample_rate_hz_ == kSampleRate32kHz) {
197 split_sample_rate_hz_ = kSampleRate16kHz;
198 } else {
199 split_sample_rate_hz_ = sample_rate_hz_;
200 }
201
202 return InitializeLocked();
203}
204
205int AudioProcessingImpl::sample_rate_hz() const {
206 return sample_rate_hz_;
207}
208
209int AudioProcessingImpl::set_num_reverse_channels(int channels) {
210 CriticalSectionScoped crit_scoped(*crit_);
211 // Only stereo supported currently.
212 if (channels > 2 || channels < 1) {
213 return kBadParameterError;
214 }
215
ajm@google.com808e0e02011-08-03 21:08:51 +0000216 num_reverse_channels_ = channels;
niklase@google.com470e71d2011-07-07 08:21:25 +0000217
218 return InitializeLocked();
219}
220
221int AudioProcessingImpl::num_reverse_channels() const {
ajm@google.com808e0e02011-08-03 21:08:51 +0000222 return num_reverse_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000223}
224
225int AudioProcessingImpl::set_num_channels(
226 int input_channels,
227 int output_channels) {
228 CriticalSectionScoped crit_scoped(*crit_);
229 if (output_channels > input_channels) {
230 return kBadParameterError;
231 }
232
233 // Only stereo supported currently.
234 if (input_channels > 2 || input_channels < 1) {
235 return kBadParameterError;
236 }
237
238 if (output_channels > 2 || output_channels < 1) {
239 return kBadParameterError;
240 }
241
ajm@google.com808e0e02011-08-03 21:08:51 +0000242 num_input_channels_ = input_channels;
243 num_output_channels_ = output_channels;
niklase@google.com470e71d2011-07-07 08:21:25 +0000244
245 return InitializeLocked();
246}
247
248int AudioProcessingImpl::num_input_channels() const {
ajm@google.com808e0e02011-08-03 21:08:51 +0000249 return num_input_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000250}
251
252int AudioProcessingImpl::num_output_channels() const {
ajm@google.com808e0e02011-08-03 21:08:51 +0000253 return num_output_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000254}
255
256int AudioProcessingImpl::ProcessStream(AudioFrame* frame) {
257 CriticalSectionScoped crit_scoped(*crit_);
258 int err = kNoError;
259
260 if (frame == NULL) {
261 return kNullPointerError;
262 }
263
xians@google.com0b0665a2011-08-08 08:18:44 +0000264 if (frame->_frequencyInHz != sample_rate_hz_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000265 return kBadSampleRateError;
266 }
267
ajm@google.com808e0e02011-08-03 21:08:51 +0000268 if (frame->_audioChannel != num_input_channels_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000269 return kBadNumberChannelsError;
270 }
271
272 if (frame->_payloadDataLengthInSamples != samples_per_channel_) {
273 return kBadDataLengthError;
274 }
275
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000276#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000277 if (debug_file_->Open()) {
ajm@google.com808e0e02011-08-03 21:08:51 +0000278 event_msg_->set_type(audioproc::Event::STREAM);
279 audioproc::Stream* msg = event_msg_->mutable_stream();
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000280 const size_t data_size = sizeof(int16_t) *
ajm@google.com808e0e02011-08-03 21:08:51 +0000281 frame->_payloadDataLengthInSamples *
282 frame->_audioChannel;
283 msg->set_input_data(frame->_payloadData, data_size);
284 msg->set_delay(stream_delay_ms_);
285 msg->set_drift(echo_cancellation_->stream_drift_samples());
286 msg->set_level(gain_control_->stream_analog_level());
niklase@google.com470e71d2011-07-07 08:21:25 +0000287 }
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000288#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000289
290 capture_audio_->DeinterleaveFrom(frame);
291
292 // TODO(ajm): experiment with mixing and AEC placement.
ajm@google.com808e0e02011-08-03 21:08:51 +0000293 if (num_output_channels_ < num_input_channels_) {
294 capture_audio_->Mix(num_output_channels_);
ajm@google.com808e0e02011-08-03 21:08:51 +0000295 frame->_audioChannel = num_output_channels_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000296 }
297
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000298 bool data_changed = stream_data_changed();
299 if (analysis_needed(data_changed)) {
300 for (int i = 0; i < num_output_channels_; i++) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000301 // Split into a low and high band.
302 SplittingFilterAnalysis(capture_audio_->data(i),
303 capture_audio_->low_pass_split_data(i),
304 capture_audio_->high_pass_split_data(i),
305 capture_audio_->analysis_filter_state1(i),
306 capture_audio_->analysis_filter_state2(i));
307 }
308 }
309
310 err = high_pass_filter_->ProcessCaptureAudio(capture_audio_);
311 if (err != kNoError) {
312 return err;
313 }
314
315 err = gain_control_->AnalyzeCaptureAudio(capture_audio_);
316 if (err != kNoError) {
317 return err;
318 }
319
320 err = echo_cancellation_->ProcessCaptureAudio(capture_audio_);
321 if (err != kNoError) {
322 return err;
323 }
324
325 if (echo_control_mobile_->is_enabled() &&
326 noise_suppression_->is_enabled()) {
327 capture_audio_->CopyLowPassToReference();
328 }
329
330 err = noise_suppression_->ProcessCaptureAudio(capture_audio_);
331 if (err != kNoError) {
332 return err;
333 }
334
335 err = echo_control_mobile_->ProcessCaptureAudio(capture_audio_);
336 if (err != kNoError) {
337 return err;
338 }
339
340 err = voice_detection_->ProcessCaptureAudio(capture_audio_);
341 if (err != kNoError) {
342 return err;
343 }
344
345 err = gain_control_->ProcessCaptureAudio(capture_audio_);
346 if (err != kNoError) {
347 return err;
348 }
349
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000350 if (synthesis_needed(data_changed)) {
ajm@google.com808e0e02011-08-03 21:08:51 +0000351 for (int i = 0; i < num_output_channels_; i++) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000352 // Recombine low and high bands.
353 SplittingFilterSynthesis(capture_audio_->low_pass_split_data(i),
354 capture_audio_->high_pass_split_data(i),
355 capture_audio_->data(i),
356 capture_audio_->synthesis_filter_state1(i),
357 capture_audio_->synthesis_filter_state2(i));
358 }
359 }
360
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000361 // The level estimator operates on the recombined data.
362 err = level_estimator_->ProcessStream(capture_audio_);
363 if (err != kNoError) {
364 return err;
365 }
366
367 capture_audio_->InterleaveTo(frame, data_changed);
niklase@google.com470e71d2011-07-07 08:21:25 +0000368
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000369#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
ajm@google.com808e0e02011-08-03 21:08:51 +0000370 if (debug_file_->Open()) {
371 audioproc::Stream* msg = event_msg_->mutable_stream();
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000372 const size_t data_size = sizeof(int16_t) *
ajm@google.com808e0e02011-08-03 21:08:51 +0000373 frame->_payloadDataLengthInSamples *
374 frame->_audioChannel;
375 msg->set_output_data(frame->_payloadData, data_size);
376 err = WriteMessageToDebugFile();
377 if (err != kNoError) {
378 return err;
379 }
380 }
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000381#endif
ajm@google.com808e0e02011-08-03 21:08:51 +0000382
andrew@webrtc.org1e916932011-11-29 18:28:57 +0000383 was_stream_delay_set_ = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000384 return kNoError;
385}
386
387int AudioProcessingImpl::AnalyzeReverseStream(AudioFrame* frame) {
388 CriticalSectionScoped crit_scoped(*crit_);
389 int err = kNoError;
390
391 if (frame == NULL) {
392 return kNullPointerError;
393 }
394
xians@google.com0b0665a2011-08-08 08:18:44 +0000395 if (frame->_frequencyInHz != sample_rate_hz_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000396 return kBadSampleRateError;
397 }
398
ajm@google.com808e0e02011-08-03 21:08:51 +0000399 if (frame->_audioChannel != num_reverse_channels_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000400 return kBadNumberChannelsError;
401 }
402
403 if (frame->_payloadDataLengthInSamples != samples_per_channel_) {
404 return kBadDataLengthError;
405 }
406
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000407#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000408 if (debug_file_->Open()) {
ajm@google.com808e0e02011-08-03 21:08:51 +0000409 event_msg_->set_type(audioproc::Event::REVERSE_STREAM);
410 audioproc::ReverseStream* msg = event_msg_->mutable_reverse_stream();
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000411 const size_t data_size = sizeof(int16_t) *
ajm@google.com808e0e02011-08-03 21:08:51 +0000412 frame->_payloadDataLengthInSamples *
413 frame->_audioChannel;
414 msg->set_data(frame->_payloadData, data_size);
415 err = WriteMessageToDebugFile();
416 if (err != kNoError) {
417 return err;
niklase@google.com470e71d2011-07-07 08:21:25 +0000418 }
419 }
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000420#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000421
422 render_audio_->DeinterleaveFrom(frame);
423
424 // TODO(ajm): turn the splitting filter into a component?
425 if (sample_rate_hz_ == kSampleRate32kHz) {
ajm@google.com808e0e02011-08-03 21:08:51 +0000426 for (int i = 0; i < num_reverse_channels_; i++) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000427 // Split into low and high band.
428 SplittingFilterAnalysis(render_audio_->data(i),
429 render_audio_->low_pass_split_data(i),
430 render_audio_->high_pass_split_data(i),
431 render_audio_->analysis_filter_state1(i),
432 render_audio_->analysis_filter_state2(i));
433 }
434 }
435
436 // TODO(ajm): warnings possible from components?
437 err = echo_cancellation_->ProcessRenderAudio(render_audio_);
438 if (err != kNoError) {
439 return err;
440 }
441
442 err = echo_control_mobile_->ProcessRenderAudio(render_audio_);
443 if (err != kNoError) {
444 return err;
445 }
446
447 err = gain_control_->ProcessRenderAudio(render_audio_);
448 if (err != kNoError) {
449 return err;
450 }
451
niklase@google.com470e71d2011-07-07 08:21:25 +0000452 return err; // TODO(ajm): this is for returning warnings; necessary?
453}
454
455int AudioProcessingImpl::set_stream_delay_ms(int delay) {
456 was_stream_delay_set_ = true;
457 if (delay < 0) {
458 return kBadParameterError;
459 }
460
461 // TODO(ajm): the max is rather arbitrarily chosen; investigate.
462 if (delay > 500) {
463 stream_delay_ms_ = 500;
464 return kBadStreamParameterWarning;
465 }
466
467 stream_delay_ms_ = delay;
468 return kNoError;
469}
470
471int AudioProcessingImpl::stream_delay_ms() const {
472 return stream_delay_ms_;
473}
474
475bool AudioProcessingImpl::was_stream_delay_set() const {
476 return was_stream_delay_set_;
477}
478
479int AudioProcessingImpl::StartDebugRecording(
480 const char filename[AudioProcessing::kMaxFilenameSize]) {
481 CriticalSectionScoped crit_scoped(*crit_);
482 assert(kMaxFilenameSize == FileWrapper::kMaxFileNameSize);
483
484 if (filename == NULL) {
485 return kNullPointerError;
486 }
487
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000488#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000489 // Stop any ongoing recording.
490 if (debug_file_->Open()) {
491 if (debug_file_->CloseFile() == -1) {
492 return kFileError;
493 }
494 }
495
496 if (debug_file_->OpenFile(filename, false) == -1) {
497 debug_file_->CloseFile();
498 return kFileError;
499 }
500
ajm@google.com808e0e02011-08-03 21:08:51 +0000501 int err = WriteInitMessage();
502 if (err != kNoError) {
503 return err;
niklase@google.com470e71d2011-07-07 08:21:25 +0000504 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000505 return kNoError;
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000506#else
507 return kUnsupportedFunctionError;
508#endif // WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000509}
510
511int AudioProcessingImpl::StopDebugRecording() {
512 CriticalSectionScoped crit_scoped(*crit_);
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000513
514#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000515 // We just return if recording hasn't started.
516 if (debug_file_->Open()) {
517 if (debug_file_->CloseFile() == -1) {
518 return kFileError;
519 }
520 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000521 return kNoError;
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000522#else
523 return kUnsupportedFunctionError;
524#endif // WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000525}
526
527EchoCancellation* AudioProcessingImpl::echo_cancellation() const {
528 return echo_cancellation_;
529}
530
531EchoControlMobile* AudioProcessingImpl::echo_control_mobile() const {
532 return echo_control_mobile_;
533}
534
535GainControl* AudioProcessingImpl::gain_control() const {
536 return gain_control_;
537}
538
539HighPassFilter* AudioProcessingImpl::high_pass_filter() const {
540 return high_pass_filter_;
541}
542
543LevelEstimator* AudioProcessingImpl::level_estimator() const {
544 return level_estimator_;
545}
546
547NoiseSuppression* AudioProcessingImpl::noise_suppression() const {
548 return noise_suppression_;
549}
550
551VoiceDetection* AudioProcessingImpl::voice_detection() const {
552 return voice_detection_;
553}
554
555WebRtc_Word32 AudioProcessingImpl::Version(WebRtc_Word8* version,
556 WebRtc_UWord32& bytes_remaining, WebRtc_UWord32& position) const {
557 if (version == NULL) {
558 /*WEBRTC_TRACE(webrtc::kTraceError,
559 webrtc::kTraceAudioProcessing,
560 -1,
561 "Null version pointer");*/
562 return kNullPointerError;
563 }
564 memset(&version[position], 0, bytes_remaining);
565
ajm@google.com808e0e02011-08-03 21:08:51 +0000566 char my_version[] = "AudioProcessing 1.0.0";
niklase@google.com470e71d2011-07-07 08:21:25 +0000567 // Includes null termination.
568 WebRtc_UWord32 length = static_cast<WebRtc_UWord32>(strlen(my_version));
569 if (bytes_remaining < length) {
570 /*WEBRTC_TRACE(webrtc::kTraceError,
571 webrtc::kTraceAudioProcessing,
572 -1,
573 "Buffer of insufficient length");*/
574 return kBadParameterError;
575 }
576 memcpy(&version[position], my_version, length);
577 bytes_remaining -= length;
578 position += length;
579
580 std::list<ProcessingComponent*>::const_iterator it;
581 for (it = component_list_.begin(); it != component_list_.end(); it++) {
582 char component_version[256];
583 strcpy(component_version, "\n");
584 int err = (*it)->get_version(&component_version[1],
585 sizeof(component_version) - 1);
586 if (err != kNoError) {
587 return err;
588 }
589 if (strncmp(&component_version[1], "\0", 1) == 0) {
590 // Assume empty if first byte is NULL.
591 continue;
592 }
593
594 length = static_cast<WebRtc_UWord32>(strlen(component_version));
595 if (bytes_remaining < length) {
596 /*WEBRTC_TRACE(webrtc::kTraceError,
597 webrtc::kTraceAudioProcessing,
598 -1,
599 "Buffer of insufficient length");*/
600 return kBadParameterError;
601 }
602 memcpy(&version[position], component_version, length);
603 bytes_remaining -= length;
604 position += length;
605 }
606
607 return kNoError;
608}
609
610WebRtc_Word32 AudioProcessingImpl::ChangeUniqueId(const WebRtc_Word32 id) {
611 CriticalSectionScoped crit_scoped(*crit_);
612 /*WEBRTC_TRACE(webrtc::kTraceModuleCall,
613 webrtc::kTraceAudioProcessing,
614 id_,
615 "ChangeUniqueId(new id = %d)",
616 id);*/
617 id_ = id;
618
619 return kNoError;
620}
ajm@google.com808e0e02011-08-03 21:08:51 +0000621
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000622bool AudioProcessingImpl::stream_data_changed() const {
623 int enabled_count = 0;
624 std::list<ProcessingComponent*>::const_iterator it;
625 for (it = component_list_.begin(); it != component_list_.end(); it++) {
626 if ((*it)->is_component_enabled()) {
627 enabled_count++;
628 }
629 }
630
631 // Data is unchanged if no components are enabled, or if only level_estimator_
632 // or voice_detection_ is enabled.
633 if (enabled_count == 0) {
634 return false;
635 } else if (enabled_count == 1) {
636 if (level_estimator_->is_enabled() || voice_detection_->is_enabled()) {
637 return false;
638 }
639 } else if (enabled_count == 2) {
640 if (level_estimator_->is_enabled() && voice_detection_->is_enabled()) {
641 return false;
642 }
643 }
644 return true;
645}
646
647bool AudioProcessingImpl::synthesis_needed(bool stream_data_changed) const {
648 return (stream_data_changed && sample_rate_hz_ == kSampleRate32kHz);
649}
650
651bool AudioProcessingImpl::analysis_needed(bool stream_data_changed) const {
652 if (!stream_data_changed && !voice_detection_->is_enabled()) {
653 // Only level_estimator_ is enabled.
654 return false;
655 } else if (sample_rate_hz_ == kSampleRate32kHz) {
656 // Something besides level_estimator_ is enabled, and we have super-wb.
657 return true;
658 }
659 return false;
660}
661
662#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
ajm@google.com808e0e02011-08-03 21:08:51 +0000663int AudioProcessingImpl::WriteMessageToDebugFile() {
664 int32_t size = event_msg_->ByteSize();
665 if (size <= 0) {
666 return kUnspecifiedError;
667 }
668#if defined(WEBRTC_BIG_ENDIAN)
669 // TODO(ajm): Use little-endian "on the wire". For the moment, we can be
670 // pretty safe in assuming little-endian.
671#endif
672
673 if (!event_msg_->SerializeToString(&event_str_)) {
674 return kUnspecifiedError;
675 }
676
677 // Write message preceded by its size.
678 if (!debug_file_->Write(&size, sizeof(int32_t))) {
679 return kFileError;
680 }
681 if (!debug_file_->Write(event_str_.data(), event_str_.length())) {
682 return kFileError;
683 }
684
685 event_msg_->Clear();
686
687 return 0;
688}
689
690int AudioProcessingImpl::WriteInitMessage() {
691 event_msg_->set_type(audioproc::Event::INIT);
692 audioproc::Init* msg = event_msg_->mutable_init();
693 msg->set_sample_rate(sample_rate_hz_);
694 msg->set_device_sample_rate(echo_cancellation_->device_sample_rate_hz());
695 msg->set_num_input_channels(num_input_channels_);
696 msg->set_num_output_channels(num_output_channels_);
697 msg->set_num_reverse_channels(num_reverse_channels_);
698
699 int err = WriteMessageToDebugFile();
700 if (err != kNoError) {
701 return err;
702 }
703
704 return kNoError;
705}
andrew@webrtc.org7bf26462011-12-03 00:03:31 +0000706#endif // WEBRTC_AUDIOPROC_DEBUG_DUMP
niklase@google.com470e71d2011-07-07 08:21:25 +0000707} // namespace webrtc