diff --git a/webrtc/modules/audio_processing/audio_processing_impl.cc b/webrtc/modules/audio_processing/audio_processing_impl.cc index 0de6bf0396..f3ee0a399d 100644 --- a/webrtc/modules/audio_processing/audio_processing_impl.cc +++ b/webrtc/modules/audio_processing/audio_processing_impl.cc @@ -539,6 +539,8 @@ int AudioProcessingImpl::ProcessStream(const float* const* src, #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP if (debug_file_->Open()) { + RETURN_ON_ERR(WriteConfigMessage(false)); + event_msg_->set_type(audioproc::Event::STREAM); audioproc::Stream* msg = event_msg_->mutable_stream(); const size_t channel_size = @@ -920,10 +922,8 @@ int AudioProcessingImpl::StartDebugRecording( return kFileError; } - int err = WriteInitMessage(); - if (err != kNoError) { - return err; - } + RETURN_ON_ERR(WriteConfigMessage(true)); + RETURN_ON_ERR(WriteInitMessage()); return kNoError; #else return kUnsupportedFunctionError; @@ -949,10 +949,8 @@ int AudioProcessingImpl::StartDebugRecording(FILE* handle) { return kFileError; } - int err = WriteInitMessage(); - if (err != kNoError) { - return err; - } + RETURN_ON_ERR(WriteConfigMessage(true)); + RETURN_ON_ERR(WriteInitMessage()); return kNoError; #else return kUnsupportedFunctionError; @@ -1222,11 +1220,52 @@ int AudioProcessingImpl::WriteInitMessage() { msg->set_output_sample_rate(api_format_.output_stream().sample_rate_hz()); // TODO(ekmeyerson): Add reverse output fields to event_msg_. - int err = WriteMessageToDebugFile(); - if (err != kNoError) { - return err; + RETURN_ON_ERR(WriteMessageToDebugFile()); + return kNoError; +} + +int AudioProcessingImpl::WriteConfigMessage(bool forced) { + audioproc::Config config; + + config.set_aec_enabled(echo_cancellation_->is_enabled()); + config.set_aec_delay_agnostic_enabled( + echo_cancellation_->is_delay_agnostic_enabled()); + config.set_aec_drift_compensation_enabled( + echo_cancellation_->is_drift_compensation_enabled()); + config.set_aec_extended_filter_enabled( + echo_cancellation_->is_extended_filter_enabled()); + config.set_aec_suppression_level( + static_cast(echo_cancellation_->suppression_level())); + + config.set_aecm_enabled(echo_control_mobile_->is_enabled()); + config.set_aecm_comfort_noise_enabled( + echo_control_mobile_->is_comfort_noise_enabled()); + config.set_aecm_routing_mode( + static_cast(echo_control_mobile_->routing_mode())); + + config.set_agc_enabled(gain_control_->is_enabled()); + config.set_agc_mode(static_cast(gain_control_->mode())); + config.set_agc_limiter_enabled(gain_control_->is_limiter_enabled()); + config.set_noise_robust_agc_enabled(use_new_agc_); + + config.set_hpf_enabled(high_pass_filter_->is_enabled()); + + config.set_ns_enabled(noise_suppression_->is_enabled()); + config.set_ns_level(static_cast(noise_suppression_->level())); + + config.set_transient_suppression_enabled(transient_suppressor_enabled_); + + std::string serialized_config = config.SerializeAsString(); + if (!forced && last_serialized_config_ == serialized_config) { + return kNoError; } + last_serialized_config_ = serialized_config; + + event_msg_->set_type(audioproc::Event::CONFIG); + event_msg_->mutable_config()->CopyFrom(config); + + RETURN_ON_ERR(WriteMessageToDebugFile()); return kNoError; } #endif // WEBRTC_AUDIOPROC_DEBUG_DUMP diff --git a/webrtc/modules/audio_processing/audio_processing_impl.h b/webrtc/modules/audio_processing/audio_processing_impl.h index eeab34f874..bf29bf3633 100644 --- a/webrtc/modules/audio_processing/audio_processing_impl.h +++ b/webrtc/modules/audio_processing/audio_processing_impl.h @@ -162,9 +162,18 @@ class AudioProcessingImpl : public AudioProcessing { // out into a separate class with an "enabled" and "disabled" implementation. int WriteMessageToDebugFile(); int WriteInitMessage(); + + // Writes Config message. If not |forced|, only writes the current config if + // it is different from the last saved one; if |forced|, writes the config + // regardless of the last saved. + int WriteConfigMessage(bool forced); + rtc::scoped_ptr debug_file_; rtc::scoped_ptr event_msg_; // Protobuf message. std::string event_str_; // Memory for protobuf serialization. + + // Serialized string of last saved APM configuration. + std::string last_serialized_config_; #endif // Format of processing streams at input/output call sites. diff --git a/webrtc/modules/audio_processing/debug.proto b/webrtc/modules/audio_processing/debug.proto index dce2f79209..227271298c 100644 --- a/webrtc/modules/audio_processing/debug.proto +++ b/webrtc/modules/audio_processing/debug.proto @@ -2,6 +2,8 @@ syntax = "proto2"; option optimize_for = LITE_RUNTIME; package webrtc.audioproc; +// Contains the format of input/output/reverse audio. An Init message is added +// when any of the fields are changed. message Init { optional int32 sample_rate = 1; optional int32 device_sample_rate = 2 [deprecated=true]; @@ -39,11 +41,41 @@ message Stream { repeated bytes output_channel = 8; } +// Contains the configurations of various APM component. A Config message is +// added when any of the fields are changed. +message Config { + // Next field number 17. + // Acoustic echo canceler. + optional bool aec_enabled = 1; + optional bool aec_delay_agnostic_enabled = 2; + optional bool aec_drift_compensation_enabled = 3; + optional bool aec_extended_filter_enabled = 4; + optional int32 aec_suppression_level = 5; + // Mobile AEC. + optional bool aecm_enabled = 6; + optional bool aecm_comfort_noise_enabled = 7; + optional int32 aecm_routing_mode = 8; + // Automatic gain controller. + optional bool agc_enabled = 9; + optional int32 agc_mode = 10; + optional bool agc_limiter_enabled = 11; + optional bool noise_robust_agc_enabled = 12; + // High pass filter. + optional bool hpf_enabled = 13; + // Noise suppression. + optional bool ns_enabled = 14; + optional int32 ns_level = 15; + // Transient suppression. + optional bool transient_suppression_enabled = 16; +} + message Event { enum Type { INIT = 0; REVERSE_STREAM = 1; STREAM = 2; + CONFIG = 3; + UNKNOWN_EVENT = 4; } required Type type = 1; @@ -51,4 +83,5 @@ message Event { optional Init init = 2; optional ReverseStream reverse_stream = 3; optional Stream stream = 4; + optional Config config = 5; } diff --git a/webrtc/modules/audio_processing/echo_cancellation_impl.cc b/webrtc/modules/audio_processing/echo_cancellation_impl.cc index 86ed9234c7..567d9a47f8 100644 --- a/webrtc/modules/audio_processing/echo_cancellation_impl.cc +++ b/webrtc/modules/audio_processing/echo_cancellation_impl.cc @@ -280,6 +280,14 @@ bool EchoCancellationImpl::is_delay_logging_enabled() const { return delay_logging_enabled_; } +bool EchoCancellationImpl::is_delay_agnostic_enabled() const { + return delay_agnostic_enabled_; +} + +bool EchoCancellationImpl::is_extended_filter_enabled() const { + return extended_filter_enabled_; +} + // TODO(bjornv): How should we handle the multi-channel case? int EchoCancellationImpl::GetDelayMetrics(int* median, int* std) { float fraction_poor_delays = 0; diff --git a/webrtc/modules/audio_processing/echo_cancellation_impl.h b/webrtc/modules/audio_processing/echo_cancellation_impl.h index 9c2b32c473..070dcabc5d 100644 --- a/webrtc/modules/audio_processing/echo_cancellation_impl.h +++ b/webrtc/modules/audio_processing/echo_cancellation_impl.h @@ -32,19 +32,22 @@ class EchoCancellationImpl : public EchoCancellation, // EchoCancellation implementation. bool is_enabled() const override; int stream_drift_samples() const override; + SuppressionLevel suppression_level() const override; + bool is_drift_compensation_enabled() const override; // ProcessingComponent implementation. int Initialize() override; void SetExtraOptions(const Config& config) override; + bool is_delay_agnostic_enabled() const; + bool is_extended_filter_enabled() const; + private: // EchoCancellation implementation. int Enable(bool enable) override; int enable_drift_compensation(bool enable) override; - bool is_drift_compensation_enabled() const override; void set_stream_drift_samples(int drift) override; int set_suppression_level(SuppressionLevel level) override; - SuppressionLevel suppression_level() const override; int enable_metrics(bool enable) override; bool are_metrics_enabled() const override; bool stream_has_echo() const override; diff --git a/webrtc/modules/audio_processing/echo_control_mobile_impl.h b/webrtc/modules/audio_processing/echo_control_mobile_impl.h index f399f480b2..da7022545f 100644 --- a/webrtc/modules/audio_processing/echo_control_mobile_impl.h +++ b/webrtc/modules/audio_processing/echo_control_mobile_impl.h @@ -31,6 +31,8 @@ class EchoControlMobileImpl : public EchoControlMobile, // EchoControlMobile implementation. bool is_enabled() const override; + RoutingMode routing_mode() const override; + bool is_comfort_noise_enabled() const override; // ProcessingComponent implementation. int Initialize() override; @@ -39,9 +41,7 @@ class EchoControlMobileImpl : public EchoControlMobile, // EchoControlMobile implementation. int Enable(bool enable) override; int set_routing_mode(RoutingMode mode) override; - RoutingMode routing_mode() const override; int enable_comfort_noise(bool enable) override; - bool is_comfort_noise_enabled() const override; int SetEchoPath(const void* echo_path, size_t size_bytes) override; int GetEchoPath(void* echo_path, size_t size_bytes) const override; diff --git a/webrtc/modules/audio_processing/gain_control_impl.h b/webrtc/modules/audio_processing/gain_control_impl.h index d64894367c..f24d200cf2 100644 --- a/webrtc/modules/audio_processing/gain_control_impl.h +++ b/webrtc/modules/audio_processing/gain_control_impl.h @@ -38,19 +38,19 @@ class GainControlImpl : public GainControl, // GainControl implementation. bool is_enabled() const override; int stream_analog_level() override; + bool is_limiter_enabled() const override; + Mode mode() const override; private: // GainControl implementation. int Enable(bool enable) override; int set_stream_analog_level(int level) override; int set_mode(Mode mode) override; - Mode mode() const override; int set_target_level_dbfs(int level) override; int target_level_dbfs() const override; int set_compression_gain_db(int gain) override; int compression_gain_db() const override; int enable_limiter(bool enable) override; - bool is_limiter_enabled() const override; int set_analog_level_limits(int minimum, int maximum) override; int analog_level_minimum() const override; int analog_level_maximum() const override; diff --git a/webrtc/modules/audio_processing/noise_suppression_impl.h b/webrtc/modules/audio_processing/noise_suppression_impl.h index 33a0e060a6..76a39b8e09 100644 --- a/webrtc/modules/audio_processing/noise_suppression_impl.h +++ b/webrtc/modules/audio_processing/noise_suppression_impl.h @@ -32,12 +32,12 @@ class NoiseSuppressionImpl : public NoiseSuppression, // NoiseSuppression implementation. bool is_enabled() const override; float speech_probability() const override; + Level level() const override; private: // NoiseSuppression implementation. int Enable(bool enable) override; int set_level(Level level) override; - Level level() const override; // ProcessingComponent implementation. void* CreateHandle() const override; diff --git a/webrtc/modules/audio_processing/test/unpack.cc b/webrtc/modules/audio_processing/test/unpack.cc index 2484828bd1..24578e240c 100644 --- a/webrtc/modules/audio_processing/test/unpack.cc +++ b/webrtc/modules/audio_processing/test/unpack.cc @@ -40,6 +40,11 @@ DEFINE_bool(text, false, "Write non-audio files as text files instead of binary files."); +#define PRINT_CONFIG(field_name) \ + if (msg.has_##field_name()) { \ + fprintf(settings_file, " " #field_name ": %d\n", msg.field_name()); \ + } + namespace webrtc { using audioproc::Event; @@ -83,6 +88,9 @@ int do_main(int argc, char* argv[]) { rtc::scoped_ptr reverse_raw_file; rtc::scoped_ptr input_raw_file; rtc::scoped_ptr output_raw_file; + + FILE* settings_file = OpenFile(FLAGS_settings_file, "wb"); + while (ReadMessageFromFile(debug_file, &event_msg)) { if (event_msg.type() == Event::REVERSE_STREAM) { if (!event_msg.has_reverse_stream()) { @@ -217,13 +225,37 @@ int do_main(int argc, char* argv[]) { } } } + } else if (event_msg.type() == Event::CONFIG) { + if (!event_msg.has_config()) { + printf("Corrupt input file: Config missing.\n"); + return 1; + } + const audioproc::Config msg = event_msg.config(); + + fprintf(settings_file, "APM re-config at frame: %d\n", frame_count); + + PRINT_CONFIG(aec_enabled); + PRINT_CONFIG(aec_delay_agnostic_enabled); + PRINT_CONFIG(aec_drift_compensation_enabled); + PRINT_CONFIG(aec_extended_filter_enabled); + PRINT_CONFIG(aec_suppression_level); + PRINT_CONFIG(aecm_enabled); + PRINT_CONFIG(aecm_comfort_noise_enabled); + PRINT_CONFIG(aecm_routing_mode); + PRINT_CONFIG(agc_enabled); + PRINT_CONFIG(agc_mode); + PRINT_CONFIG(agc_limiter_enabled); + PRINT_CONFIG(noise_robust_agc_enabled); + PRINT_CONFIG(hpf_enabled); + PRINT_CONFIG(ns_enabled); + PRINT_CONFIG(ns_level); + PRINT_CONFIG(transient_suppression_enabled); } else if (event_msg.type() == Event::INIT) { if (!event_msg.has_init()) { printf("Corrupt input file: Init missing.\n"); return 1; } - static FILE* settings_file = OpenFile(FLAGS_settings_file, "wb"); const Init msg = event_msg.init(); // These should print out zeros if they're missing. fprintf(settings_file, "Init at frame: %d\n", frame_count);