summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/webrtc/modules/audio_processing/audio_processing_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/webrtc/modules/audio_processing/audio_processing_impl.cc')
-rw-r--r--chromium/third_party/webrtc/modules/audio_processing/audio_processing_impl.cc646
1 files changed, 395 insertions, 251 deletions
diff --git a/chromium/third_party/webrtc/modules/audio_processing/audio_processing_impl.cc b/chromium/third_party/webrtc/modules/audio_processing/audio_processing_impl.cc
index 4d36ff7e7b4..de387edb2f5 100644
--- a/chromium/third_party/webrtc/modules/audio_processing/audio_processing_impl.cc
+++ b/chromium/third_party/webrtc/modules/audio_processing/audio_processing_impl.cc
@@ -12,17 +12,20 @@
#include <assert.h>
+#include "webrtc/common_audio/include/audio_util.h"
+#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
#include "webrtc/modules/audio_processing/audio_buffer.h"
-#include "webrtc/modules/audio_processing/echo_cancellation_impl_wrapper.h"
+#include "webrtc/modules/audio_processing/common.h"
+#include "webrtc/modules/audio_processing/echo_cancellation_impl.h"
#include "webrtc/modules/audio_processing/echo_control_mobile_impl.h"
#include "webrtc/modules/audio_processing/gain_control_impl.h"
#include "webrtc/modules/audio_processing/high_pass_filter_impl.h"
#include "webrtc/modules/audio_processing/level_estimator_impl.h"
#include "webrtc/modules/audio_processing/noise_suppression_impl.h"
#include "webrtc/modules/audio_processing/processing_component.h"
-#include "webrtc/modules/audio_processing/splitting_filter.h"
#include "webrtc/modules/audio_processing/voice_detection_impl.h"
#include "webrtc/modules/interface/module_common_types.h"
+#include "webrtc/system_wrappers/interface/compile_assert.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/file_wrapper.h"
#include "webrtc/system_wrappers/interface/logging.h"
@@ -36,9 +39,30 @@
#endif
#endif // WEBRTC_AUDIOPROC_DEBUG_DUMP
+#define RETURN_ON_ERR(expr) \
+ do { \
+ int err = expr; \
+ if (err != kNoError) { \
+ return err; \
+ } \
+ } while (0)
+
namespace webrtc {
+
+// Throughout webrtc, it's assumed that success is represented by zero.
+COMPILE_ASSERT(AudioProcessing::kNoError == 0, no_error_must_be_zero);
+
AudioProcessing* AudioProcessing::Create(int id) {
- AudioProcessingImpl* apm = new AudioProcessingImpl(id);
+ return Create();
+}
+
+AudioProcessing* AudioProcessing::Create() {
+ Config config;
+ return Create(config);
+}
+
+AudioProcessing* AudioProcessing::Create(const Config& config) {
+ AudioProcessingImpl* apm = new AudioProcessingImpl(config);
if (apm->Initialize() != kNoError) {
delete apm;
apm = NULL;
@@ -47,12 +71,8 @@ AudioProcessing* AudioProcessing::Create(int id) {
return apm;
}
-int32_t AudioProcessing::TimeUntilNextProcess() { return -1; }
-int32_t AudioProcessing::Process() { return -1; }
-
-AudioProcessingImpl::AudioProcessingImpl(int id)
- : id_(id),
- echo_cancellation_(NULL),
+AudioProcessingImpl::AudioProcessingImpl(const Config& config)
+ : echo_cancellation_(NULL),
echo_control_mobile_(NULL),
gain_control_(NULL),
high_pass_filter_(NULL),
@@ -60,41 +80,43 @@ AudioProcessingImpl::AudioProcessingImpl(int id)
noise_suppression_(NULL),
voice_detection_(NULL),
crit_(CriticalSectionWrapper::CreateCriticalSection()),
- render_audio_(NULL),
- capture_audio_(NULL),
#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
debug_file_(FileWrapper::Create()),
event_msg_(new audioproc::Event()),
#endif
- sample_rate_hz_(kSampleRate16kHz),
- split_sample_rate_hz_(kSampleRate16kHz),
- samples_per_channel_(sample_rate_hz_ / 100),
+ fwd_in_format_(kSampleRate16kHz, 1),
+ fwd_proc_format_(kSampleRate16kHz, 1),
+ fwd_out_format_(kSampleRate16kHz),
+ rev_in_format_(kSampleRate16kHz, 1),
+ rev_proc_format_(kSampleRate16kHz, 1),
+ split_rate_(kSampleRate16kHz),
stream_delay_ms_(0),
delay_offset_ms_(0),
was_stream_delay_set_(false),
- num_reverse_channels_(1),
- num_input_channels_(1),
- num_output_channels_(1) {
- echo_cancellation_ = EchoCancellationImplWrapper::Create(this);
+ output_will_be_muted_(false),
+ key_pressed_(false) {
+ echo_cancellation_ = new EchoCancellationImpl(this, crit_);
component_list_.push_back(echo_cancellation_);
- echo_control_mobile_ = new EchoControlMobileImpl(this);
+ echo_control_mobile_ = new EchoControlMobileImpl(this, crit_);
component_list_.push_back(echo_control_mobile_);
- gain_control_ = new GainControlImpl(this);
+ gain_control_ = new GainControlImpl(this, crit_);
component_list_.push_back(gain_control_);
- high_pass_filter_ = new HighPassFilterImpl(this);
+ high_pass_filter_ = new HighPassFilterImpl(this, crit_);
component_list_.push_back(high_pass_filter_);
- level_estimator_ = new LevelEstimatorImpl(this);
+ level_estimator_ = new LevelEstimatorImpl(this, crit_);
component_list_.push_back(level_estimator_);
- noise_suppression_ = new NoiseSuppressionImpl(this);
+ noise_suppression_ = new NoiseSuppressionImpl(this, crit_);
component_list_.push_back(noise_suppression_);
- voice_detection_ = new VoiceDetectionImpl(this);
+ voice_detection_ = new VoiceDetectionImpl(this, crit_);
component_list_.push_back(voice_detection_);
+
+ SetExtraOptions(config);
}
AudioProcessingImpl::~AudioProcessingImpl() {
@@ -112,52 +134,52 @@ AudioProcessingImpl::~AudioProcessingImpl() {
debug_file_->CloseFile();
}
#endif
-
- if (render_audio_) {
- delete render_audio_;
- render_audio_ = NULL;
- }
-
- if (capture_audio_) {
- delete capture_audio_;
- capture_audio_ = NULL;
- }
}
-
delete crit_;
crit_ = NULL;
}
-CriticalSectionWrapper* AudioProcessingImpl::crit() const {
- return crit_;
-}
-
-int AudioProcessingImpl::split_sample_rate_hz() const {
- return split_sample_rate_hz_;
-}
-
int AudioProcessingImpl::Initialize() {
CriticalSectionScoped crit_scoped(crit_);
return InitializeLocked();
}
-int AudioProcessingImpl::InitializeLocked() {
- if (render_audio_ != NULL) {
- delete render_audio_;
- render_audio_ = NULL;
- }
-
- if (capture_audio_ != NULL) {
- delete capture_audio_;
- capture_audio_ = NULL;
- }
-
- render_audio_ = new AudioBuffer(num_reverse_channels_,
- samples_per_channel_);
- capture_audio_ = new AudioBuffer(num_input_channels_,
- samples_per_channel_);
+int AudioProcessingImpl::set_sample_rate_hz(int rate) {
+ CriticalSectionScoped crit_scoped(crit_);
+ return InitializeLocked(rate,
+ rate,
+ rev_in_format_.rate(),
+ fwd_in_format_.num_channels(),
+ fwd_proc_format_.num_channels(),
+ rev_in_format_.num_channels());
+}
+
+int AudioProcessingImpl::Initialize(int input_sample_rate_hz,
+ int output_sample_rate_hz,
+ int reverse_sample_rate_hz,
+ ChannelLayout input_layout,
+ ChannelLayout output_layout,
+ ChannelLayout reverse_layout) {
+ CriticalSectionScoped crit_scoped(crit_);
+ return InitializeLocked(input_sample_rate_hz,
+ output_sample_rate_hz,
+ reverse_sample_rate_hz,
+ ChannelsFromLayout(input_layout),
+ ChannelsFromLayout(output_layout),
+ ChannelsFromLayout(reverse_layout));
+}
- was_stream_delay_set_ = false;
+int AudioProcessingImpl::InitializeLocked() {
+ render_audio_.reset(new AudioBuffer(rev_in_format_.samples_per_channel(),
+ rev_in_format_.num_channels(),
+ rev_proc_format_.samples_per_channel(),
+ rev_proc_format_.num_channels(),
+ rev_proc_format_.samples_per_channel()));
+ capture_audio_.reset(new AudioBuffer(fwd_in_format_.samples_per_channel(),
+ fwd_in_format_.num_channels(),
+ fwd_proc_format_.samples_per_channel(),
+ fwd_proc_format_.num_channels(),
+ fwd_out_format_.samples_per_channel()));
// Initialize all components.
std::list<ProcessingComponent*>::iterator it;
@@ -180,115 +202,228 @@ int AudioProcessingImpl::InitializeLocked() {
return kNoError;
}
-void AudioProcessingImpl::SetExtraOptions(const Config& config) {
- std::list<ProcessingComponent*>::iterator it;
- for (it = component_list_.begin(); it != component_list_.end(); ++it)
- (*it)->SetExtraOptions(config);
-}
+int AudioProcessingImpl::InitializeLocked(int input_sample_rate_hz,
+ int output_sample_rate_hz,
+ int reverse_sample_rate_hz,
+ int num_input_channels,
+ int num_output_channels,
+ int num_reverse_channels) {
+ if (input_sample_rate_hz <= 0 ||
+ output_sample_rate_hz <= 0 ||
+ reverse_sample_rate_hz <= 0) {
+ return kBadSampleRateError;
+ }
+ if (num_output_channels > num_input_channels) {
+ return kBadNumberChannelsError;
+ }
+ // Only mono and stereo supported currently.
+ if (num_input_channels > 2 || num_input_channels < 1 ||
+ num_output_channels > 2 || num_output_channels < 1 ||
+ num_reverse_channels > 2 || num_reverse_channels < 1) {
+ return kBadNumberChannelsError;
+ }
-int AudioProcessingImpl::EnableExperimentalNs(bool enable) {
- return kNoError;
-}
+ fwd_in_format_.set(input_sample_rate_hz, num_input_channels);
+ fwd_out_format_.set(output_sample_rate_hz);
+ rev_in_format_.set(reverse_sample_rate_hz, num_reverse_channels);
-int AudioProcessingImpl::set_sample_rate_hz(int rate) {
- CriticalSectionScoped crit_scoped(crit_);
- if (rate == sample_rate_hz_) {
- return kNoError;
+ // We process at the closest native rate >= min(input rate, output rate)...
+ int min_proc_rate = std::min(fwd_in_format_.rate(), fwd_out_format_.rate());
+ int fwd_proc_rate;
+ if (min_proc_rate > kSampleRate16kHz) {
+ fwd_proc_rate = kSampleRate32kHz;
+ } else if (min_proc_rate > kSampleRate8kHz) {
+ fwd_proc_rate = kSampleRate16kHz;
+ } else {
+ fwd_proc_rate = kSampleRate8kHz;
}
- if (rate != kSampleRate8kHz &&
- rate != kSampleRate16kHz &&
- rate != kSampleRate32kHz) {
- return kBadParameterError;
+ // ...with one exception.
+ if (echo_control_mobile_->is_enabled() && min_proc_rate > kSampleRate16kHz) {
+ fwd_proc_rate = kSampleRate16kHz;
}
- if (echo_control_mobile_->is_enabled() && rate > kSampleRate16kHz) {
- LOG(LS_ERROR) << "AECM only supports 16 kHz or lower sample rates";
- return kUnsupportedComponentError;
+
+ fwd_proc_format_.set(fwd_proc_rate, num_output_channels);
+
+ // We normally process the reverse stream at 16 kHz. Unless...
+ int rev_proc_rate = kSampleRate16kHz;
+ if (fwd_proc_format_.rate() == kSampleRate8kHz) {
+ // ...the forward stream is at 8 kHz.
+ rev_proc_rate = kSampleRate8kHz;
+ } else {
+ if (rev_in_format_.rate() == kSampleRate32kHz) {
+ // ...or the input is at 32 kHz, in which case we use the splitting
+ // filter rather than the resampler.
+ rev_proc_rate = kSampleRate32kHz;
+ }
}
- sample_rate_hz_ = rate;
- samples_per_channel_ = rate / 100;
+ // TODO(ajm): Enable this.
+ // Always downmix the reverse stream to mono for analysis.
+ //rev_proc_format_.set(rev_proc_rate, 1);
+ rev_proc_format_.set(rev_proc_rate, rev_in_format_.num_channels());
- if (sample_rate_hz_ == kSampleRate32kHz) {
- split_sample_rate_hz_ = kSampleRate16kHz;
+ if (fwd_proc_format_.rate() == kSampleRate32kHz) {
+ split_rate_ = kSampleRate16kHz;
} else {
- split_sample_rate_hz_ = sample_rate_hz_;
+ split_rate_ = fwd_proc_format_.rate();
}
return InitializeLocked();
}
-int AudioProcessingImpl::sample_rate_hz() const {
+// Calls InitializeLocked() if any of the audio parameters have changed from
+// their current values.
+int AudioProcessingImpl::MaybeInitializeLocked(int input_sample_rate_hz,
+ int output_sample_rate_hz,
+ int reverse_sample_rate_hz,
+ int num_input_channels,
+ int num_output_channels,
+ int num_reverse_channels) {
+ if (input_sample_rate_hz == fwd_in_format_.rate() &&
+ output_sample_rate_hz == fwd_out_format_.rate() &&
+ reverse_sample_rate_hz == rev_in_format_.rate() &&
+ num_input_channels == fwd_in_format_.num_channels() &&
+ num_output_channels == fwd_proc_format_.num_channels() &&
+ num_reverse_channels == rev_in_format_.num_channels()) {
+ return kNoError;
+ }
+
+ return InitializeLocked(input_sample_rate_hz,
+ output_sample_rate_hz,
+ reverse_sample_rate_hz,
+ num_input_channels,
+ num_output_channels,
+ num_reverse_channels);
+}
+
+void AudioProcessingImpl::SetExtraOptions(const Config& config) {
CriticalSectionScoped crit_scoped(crit_);
- return sample_rate_hz_;
+ std::list<ProcessingComponent*>::iterator it;
+ for (it = component_list_.begin(); it != component_list_.end(); ++it)
+ (*it)->SetExtraOptions(config);
+}
+
+int AudioProcessingImpl::EnableExperimentalNs(bool enable) {
+ return kNoError;
}
-int AudioProcessingImpl::set_num_reverse_channels(int channels) {
+int AudioProcessingImpl::input_sample_rate_hz() const {
CriticalSectionScoped crit_scoped(crit_);
- if (channels == num_reverse_channels_) {
- return kNoError;
- }
- // Only stereo supported currently.
- if (channels > 2 || channels < 1) {
- return kBadParameterError;
- }
+ return fwd_in_format_.rate();
+}
- num_reverse_channels_ = channels;
+int AudioProcessingImpl::sample_rate_hz() const {
+ CriticalSectionScoped crit_scoped(crit_);
+ return fwd_in_format_.rate();
+}
- return InitializeLocked();
+int AudioProcessingImpl::proc_sample_rate_hz() const {
+ return fwd_proc_format_.rate();
+}
+
+int AudioProcessingImpl::proc_split_sample_rate_hz() const {
+ return split_rate_;
}
int AudioProcessingImpl::num_reverse_channels() const {
- return num_reverse_channels_;
+ return rev_proc_format_.num_channels();
+}
+
+int AudioProcessingImpl::num_input_channels() const {
+ return fwd_in_format_.num_channels();
+}
+
+int AudioProcessingImpl::num_output_channels() const {
+ return fwd_proc_format_.num_channels();
+}
+
+void AudioProcessingImpl::set_output_will_be_muted(bool muted) {
+ output_will_be_muted_ = muted;
}
-int AudioProcessingImpl::set_num_channels(
- int input_channels,
- int output_channels) {
+bool AudioProcessingImpl::output_will_be_muted() const {
+ return output_will_be_muted_;
+}
+
+int AudioProcessingImpl::ProcessStream(const float* const* src,
+ int samples_per_channel,
+ int input_sample_rate_hz,
+ ChannelLayout input_layout,
+ int output_sample_rate_hz,
+ ChannelLayout output_layout,
+ float* const* dest) {
CriticalSectionScoped crit_scoped(crit_);
- if (input_channels == num_input_channels_ &&
- output_channels == num_output_channels_) {
- return kNoError;
- }
- if (output_channels > input_channels) {
- return kBadParameterError;
+ if (!src || !dest) {
+ return kNullPointerError;
}
- // Only stereo supported currently.
- if (input_channels > 2 || input_channels < 1 ||
- output_channels > 2 || output_channels < 1) {
- return kBadParameterError;
+
+ RETURN_ON_ERR(MaybeInitializeLocked(input_sample_rate_hz,
+ output_sample_rate_hz,
+ rev_in_format_.rate(),
+ ChannelsFromLayout(input_layout),
+ ChannelsFromLayout(output_layout),
+ rev_in_format_.num_channels()));
+ if (samples_per_channel != fwd_in_format_.samples_per_channel()) {
+ return kBadDataLengthError;
}
- num_input_channels_ = input_channels;
- num_output_channels_ = output_channels;
+#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
+ if (debug_file_->Open()) {
+ event_msg_->set_type(audioproc::Event::STREAM);
+ audioproc::Stream* msg = event_msg_->mutable_stream();
+ const size_t channel_size = sizeof(float) * samples_per_channel;
+ for (int i = 0; i < fwd_in_format_.num_channels(); ++i)
+ msg->add_input_channel(src[i], channel_size);
+ }
+#endif
- return InitializeLocked();
-}
+ capture_audio_->CopyFrom(src, samples_per_channel, input_layout);
+ RETURN_ON_ERR(ProcessStreamLocked());
+ if (output_copy_needed(is_data_processed())) {
+ capture_audio_->CopyTo(fwd_out_format_.samples_per_channel(),
+ output_layout,
+ dest);
+ }
-int AudioProcessingImpl::num_input_channels() const {
- return num_input_channels_;
-}
+#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
+ if (debug_file_->Open()) {
+ audioproc::Stream* msg = event_msg_->mutable_stream();
+ const size_t channel_size = sizeof(float) * samples_per_channel;
+ for (int i = 0; i < fwd_proc_format_.num_channels(); ++i)
+ msg->add_output_channel(dest[i], channel_size);
+ RETURN_ON_ERR(WriteMessageToDebugFile());
+ }
+#endif
-int AudioProcessingImpl::num_output_channels() const {
- return num_output_channels_;
+ return kNoError;
}
int AudioProcessingImpl::ProcessStream(AudioFrame* frame) {
CriticalSectionScoped crit_scoped(crit_);
- int err = kNoError;
-
- if (frame == NULL) {
+ if (!frame) {
return kNullPointerError;
}
-
- if (frame->sample_rate_hz_ != sample_rate_hz_) {
+ // Must be a native rate.
+ if (frame->sample_rate_hz_ != kSampleRate8kHz &&
+ frame->sample_rate_hz_ != kSampleRate16kHz &&
+ frame->sample_rate_hz_ != kSampleRate32kHz) {
return kBadSampleRateError;
}
-
- if (frame->num_channels_ != num_input_channels_) {
- return kBadNumberChannelsError;
+ if (echo_control_mobile_->is_enabled() &&
+ frame->sample_rate_hz_ > kSampleRate16kHz) {
+ LOG(LS_ERROR) << "AECM only supports 16 or 8 kHz sample rates";
+ return kUnsupportedComponentError;
}
- if (frame->samples_per_channel_ != samples_per_channel_) {
+ // TODO(ajm): The input and output rates and channels are currently
+ // constrained to be identical in the int16 interface.
+ RETURN_ON_ERR(MaybeInitializeLocked(frame->sample_rate_hz_,
+ frame->sample_rate_hz_,
+ rev_in_format_.rate(),
+ frame->num_channels_,
+ frame->num_channels_,
+ rev_in_format_.num_channels()));
+ if (frame->samples_per_channel_ != fwd_in_format_.samples_per_channel()) {
return kBadDataLengthError;
}
@@ -300,126 +435,142 @@ int AudioProcessingImpl::ProcessStream(AudioFrame* frame) {
frame->samples_per_channel_ *
frame->num_channels_;
msg->set_input_data(frame->data_, data_size);
- msg->set_delay(stream_delay_ms_);
- msg->set_drift(echo_cancellation_->stream_drift_samples());
- msg->set_level(gain_control_->stream_analog_level());
}
#endif
capture_audio_->DeinterleaveFrom(frame);
+ RETURN_ON_ERR(ProcessStreamLocked());
+ capture_audio_->InterleaveTo(frame, output_copy_needed(is_data_processed()));
- // TODO(ajm): experiment with mixing and AEC placement.
- if (num_output_channels_ < num_input_channels_) {
- capture_audio_->Mix(num_output_channels_);
- frame->num_channels_ = num_output_channels_;
- }
-
- bool data_processed = is_data_processed();
- if (analysis_needed(data_processed)) {
- for (int i = 0; i < num_output_channels_; i++) {
- // Split into a low and high band.
- SplittingFilterAnalysis(capture_audio_->data(i),
- capture_audio_->low_pass_split_data(i),
- capture_audio_->high_pass_split_data(i),
- capture_audio_->analysis_filter_state1(i),
- capture_audio_->analysis_filter_state2(i));
- }
- }
-
- err = high_pass_filter_->ProcessCaptureAudio(capture_audio_);
- if (err != kNoError) {
- return err;
- }
-
- err = gain_control_->AnalyzeCaptureAudio(capture_audio_);
- if (err != kNoError) {
- return err;
+#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
+ if (debug_file_->Open()) {
+ audioproc::Stream* msg = event_msg_->mutable_stream();
+ const size_t data_size = sizeof(int16_t) *
+ frame->samples_per_channel_ *
+ frame->num_channels_;
+ msg->set_output_data(frame->data_, data_size);
+ RETURN_ON_ERR(WriteMessageToDebugFile());
}
+#endif
- err = echo_cancellation_->ProcessCaptureAudio(capture_audio_);
- if (err != kNoError) {
- return err;
- }
+ return kNoError;
+}
- if (echo_control_mobile_->is_enabled() &&
- noise_suppression_->is_enabled()) {
- capture_audio_->CopyLowPassToReference();
- }
- err = noise_suppression_->ProcessCaptureAudio(capture_audio_);
- if (err != kNoError) {
- return err;
+int AudioProcessingImpl::ProcessStreamLocked() {
+#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
+ if (debug_file_->Open()) {
+ audioproc::Stream* msg = event_msg_->mutable_stream();
+ msg->set_delay(stream_delay_ms_);
+ msg->set_drift(echo_cancellation_->stream_drift_samples());
+ msg->set_level(gain_control_->stream_analog_level());
+ msg->set_keypress(key_pressed_);
}
+#endif
- err = echo_control_mobile_->ProcessCaptureAudio(capture_audio_);
- if (err != kNoError) {
- return err;
+ AudioBuffer* ca = capture_audio_.get(); // For brevity.
+ bool data_processed = is_data_processed();
+ if (analysis_needed(data_processed)) {
+ for (int i = 0; i < fwd_proc_format_.num_channels(); i++) {
+ // Split into a low and high band.
+ WebRtcSpl_AnalysisQMF(ca->data(i),
+ ca->samples_per_channel(),
+ ca->low_pass_split_data(i),
+ ca->high_pass_split_data(i),
+ ca->filter_states(i)->analysis_filter_state1,
+ ca->filter_states(i)->analysis_filter_state2);
+ }
}
- err = voice_detection_->ProcessCaptureAudio(capture_audio_);
- if (err != kNoError) {
- return err;
- }
+ RETURN_ON_ERR(high_pass_filter_->ProcessCaptureAudio(ca));
+ RETURN_ON_ERR(gain_control_->AnalyzeCaptureAudio(ca));
+ RETURN_ON_ERR(echo_cancellation_->ProcessCaptureAudio(ca));
- err = gain_control_->ProcessCaptureAudio(capture_audio_);
- if (err != kNoError) {
- return err;
+ if (echo_control_mobile_->is_enabled() && noise_suppression_->is_enabled()) {
+ ca->CopyLowPassToReference();
}
+ RETURN_ON_ERR(noise_suppression_->ProcessCaptureAudio(ca));
+ RETURN_ON_ERR(echo_control_mobile_->ProcessCaptureAudio(ca));
+ RETURN_ON_ERR(voice_detection_->ProcessCaptureAudio(ca));
+ RETURN_ON_ERR(gain_control_->ProcessCaptureAudio(ca));
if (synthesis_needed(data_processed)) {
- for (int i = 0; i < num_output_channels_; i++) {
+ for (int i = 0; i < fwd_proc_format_.num_channels(); i++) {
// Recombine low and high bands.
- SplittingFilterSynthesis(capture_audio_->low_pass_split_data(i),
- capture_audio_->high_pass_split_data(i),
- capture_audio_->data(i),
- capture_audio_->synthesis_filter_state1(i),
- capture_audio_->synthesis_filter_state2(i));
+ WebRtcSpl_SynthesisQMF(ca->low_pass_split_data(i),
+ ca->high_pass_split_data(i),
+ ca->samples_per_split_channel(),
+ ca->data(i),
+ ca->filter_states(i)->synthesis_filter_state1,
+ ca->filter_states(i)->synthesis_filter_state2);
}
}
// The level estimator operates on the recombined data.
- err = level_estimator_->ProcessStream(capture_audio_);
- if (err != kNoError) {
- return err;
+ RETURN_ON_ERR(level_estimator_->ProcessStream(ca));
+
+ was_stream_delay_set_ = false;
+ return kNoError;
+}
+
+int AudioProcessingImpl::AnalyzeReverseStream(const float* const* data,
+ int samples_per_channel,
+ int sample_rate_hz,
+ ChannelLayout layout) {
+ CriticalSectionScoped crit_scoped(crit_);
+ if (data == NULL) {
+ return kNullPointerError;
}
- capture_audio_->InterleaveTo(frame, interleave_needed(data_processed));
+ const int num_channels = ChannelsFromLayout(layout);
+ RETURN_ON_ERR(MaybeInitializeLocked(fwd_in_format_.rate(),
+ fwd_out_format_.rate(),
+ sample_rate_hz,
+ fwd_in_format_.num_channels(),
+ fwd_proc_format_.num_channels(),
+ num_channels));
+ if (samples_per_channel != rev_in_format_.samples_per_channel()) {
+ return kBadDataLengthError;
+ }
#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
if (debug_file_->Open()) {
- audioproc::Stream* msg = event_msg_->mutable_stream();
- const size_t data_size = sizeof(int16_t) *
- frame->samples_per_channel_ *
- frame->num_channels_;
- msg->set_output_data(frame->data_, data_size);
- err = WriteMessageToDebugFile();
- if (err != kNoError) {
- return err;
- }
+ event_msg_->set_type(audioproc::Event::REVERSE_STREAM);
+ audioproc::ReverseStream* msg = event_msg_->mutable_reverse_stream();
+ const size_t channel_size = sizeof(float) * samples_per_channel;
+ for (int i = 0; i < num_channels; ++i)
+ msg->add_channel(data[i], channel_size);
+ RETURN_ON_ERR(WriteMessageToDebugFile());
}
#endif
- was_stream_delay_set_ = false;
- return kNoError;
+ render_audio_->CopyFrom(data, samples_per_channel, layout);
+ return AnalyzeReverseStreamLocked();
}
int AudioProcessingImpl::AnalyzeReverseStream(AudioFrame* frame) {
CriticalSectionScoped crit_scoped(crit_);
- int err = kNoError;
-
if (frame == NULL) {
return kNullPointerError;
}
-
- if (frame->sample_rate_hz_ != sample_rate_hz_) {
+ // Must be a native rate.
+ if (frame->sample_rate_hz_ != kSampleRate8kHz &&
+ frame->sample_rate_hz_ != kSampleRate16kHz &&
+ frame->sample_rate_hz_ != kSampleRate32kHz) {
return kBadSampleRateError;
}
-
- if (frame->num_channels_ != num_reverse_channels_) {
- return kBadNumberChannelsError;
+ // This interface does not tolerate different forward and reverse rates.
+ if (frame->sample_rate_hz_ != fwd_in_format_.rate()) {
+ return kBadSampleRateError;
}
- if (frame->samples_per_channel_ != samples_per_channel_) {
+ RETURN_ON_ERR(MaybeInitializeLocked(fwd_in_format_.rate(),
+ fwd_out_format_.rate(),
+ frame->sample_rate_hz_,
+ fwd_in_format_.num_channels(),
+ fwd_in_format_.num_channels(),
+ frame->num_channels_));
+ if (frame->samples_per_channel_ != rev_in_format_.samples_per_channel()) {
return kBadDataLengthError;
}
@@ -431,44 +582,33 @@ int AudioProcessingImpl::AnalyzeReverseStream(AudioFrame* frame) {
frame->samples_per_channel_ *
frame->num_channels_;
msg->set_data(frame->data_, data_size);
- err = WriteMessageToDebugFile();
- if (err != kNoError) {
- return err;
- }
+ RETURN_ON_ERR(WriteMessageToDebugFile());
}
#endif
render_audio_->DeinterleaveFrom(frame);
+ return AnalyzeReverseStreamLocked();
+}
- // TODO(ajm): turn the splitting filter into a component?
- if (sample_rate_hz_ == kSampleRate32kHz) {
- for (int i = 0; i < num_reverse_channels_; i++) {
+int AudioProcessingImpl::AnalyzeReverseStreamLocked() {
+ AudioBuffer* ra = render_audio_.get(); // For brevity.
+ if (rev_proc_format_.rate() == kSampleRate32kHz) {
+ for (int i = 0; i < rev_proc_format_.num_channels(); i++) {
// Split into low and high band.
- SplittingFilterAnalysis(render_audio_->data(i),
- render_audio_->low_pass_split_data(i),
- render_audio_->high_pass_split_data(i),
- render_audio_->analysis_filter_state1(i),
- render_audio_->analysis_filter_state2(i));
+ WebRtcSpl_AnalysisQMF(ra->data(i),
+ ra->samples_per_channel(),
+ ra->low_pass_split_data(i),
+ ra->high_pass_split_data(i),
+ ra->filter_states(i)->analysis_filter_state1,
+ ra->filter_states(i)->analysis_filter_state2);
}
}
- // TODO(ajm): warnings possible from components?
- err = echo_cancellation_->ProcessRenderAudio(render_audio_);
- if (err != kNoError) {
- return err;
- }
-
- err = echo_control_mobile_->ProcessRenderAudio(render_audio_);
- if (err != kNoError) {
- return err;
- }
+ RETURN_ON_ERR(echo_cancellation_->ProcessRenderAudio(ra));
+ RETURN_ON_ERR(echo_control_mobile_->ProcessRenderAudio(ra));
+ RETURN_ON_ERR(gain_control_->ProcessRenderAudio(ra));
- err = gain_control_->ProcessRenderAudio(render_audio_);
- if (err != kNoError) {
- return err;
- }
-
- return err; // TODO(ajm): this is for returning warnings; necessary?
+ return kNoError;
}
int AudioProcessingImpl::set_stream_delay_ms(int delay) {
@@ -499,6 +639,14 @@ bool AudioProcessingImpl::was_stream_delay_set() const {
return was_stream_delay_set_;
}
+void AudioProcessingImpl::set_stream_key_pressed(bool key_pressed) {
+ key_pressed_ = key_pressed;
+}
+
+bool AudioProcessingImpl::stream_key_pressed() const {
+ return key_pressed_;
+}
+
void AudioProcessingImpl::set_delay_offset_ms(int offset) {
CriticalSectionScoped crit_scoped(crit_);
delay_offset_ms_ = offset;
@@ -613,13 +761,6 @@ VoiceDetection* AudioProcessingImpl::voice_detection() const {
return voice_detection_;
}
-int32_t AudioProcessingImpl::ChangeUniqueId(const int32_t id) {
- CriticalSectionScoped crit_scoped(crit_);
- id_ = id;
-
- return kNoError;
-}
-
bool AudioProcessingImpl::is_data_processed() const {
int enabled_count = 0;
std::list<ProcessingComponent*>::const_iterator it;
@@ -645,20 +786,21 @@ bool AudioProcessingImpl::is_data_processed() const {
return true;
}
-bool AudioProcessingImpl::interleave_needed(bool is_data_processed) const {
+bool AudioProcessingImpl::output_copy_needed(bool is_data_processed) const {
// Check if we've upmixed or downmixed the audio.
- return (num_output_channels_ != num_input_channels_ || is_data_processed);
+ return ((fwd_proc_format_.num_channels() != fwd_in_format_.num_channels()) ||
+ is_data_processed);
}
bool AudioProcessingImpl::synthesis_needed(bool is_data_processed) const {
- return (is_data_processed && sample_rate_hz_ == kSampleRate32kHz);
+ return (is_data_processed && fwd_proc_format_.rate() == kSampleRate32kHz);
}
bool AudioProcessingImpl::analysis_needed(bool is_data_processed) const {
if (!is_data_processed && !voice_detection_->is_enabled()) {
// Only level_estimator_ is enabled.
return false;
- } else if (sample_rate_hz_ == kSampleRate32kHz) {
+ } else if (fwd_proc_format_.rate() == kSampleRate32kHz) {
// Something besides level_estimator_ is enabled, and we have super-wb.
return true;
}
@@ -690,17 +832,18 @@ int AudioProcessingImpl::WriteMessageToDebugFile() {
event_msg_->Clear();
- return 0;
+ return kNoError;
}
int AudioProcessingImpl::WriteInitMessage() {
event_msg_->set_type(audioproc::Event::INIT);
audioproc::Init* msg = event_msg_->mutable_init();
- msg->set_sample_rate(sample_rate_hz_);
- msg->set_device_sample_rate(echo_cancellation_->device_sample_rate_hz());
- msg->set_num_input_channels(num_input_channels_);
- msg->set_num_output_channels(num_output_channels_);
- msg->set_num_reverse_channels(num_reverse_channels_);
+ msg->set_sample_rate(fwd_in_format_.rate());
+ msg->set_num_input_channels(fwd_in_format_.num_channels());
+ msg->set_num_output_channels(fwd_proc_format_.num_channels());
+ msg->set_num_reverse_channels(rev_in_format_.num_channels());
+ msg->set_reverse_sample_rate(rev_in_format_.rate());
+ msg->set_output_sample_rate(fwd_out_format_.rate());
int err = WriteMessageToDebugFile();
if (err != kNoError) {
@@ -710,4 +853,5 @@ int AudioProcessingImpl::WriteInitMessage() {
return kNoError;
}
#endif // WEBRTC_AUDIOPROC_DEBUG_DUMP
+
} // namespace webrtc