diff options
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.cc | 646 |
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 |