From 3be9da37bb433129bd04b63588c3a415427c079b Mon Sep 17 00:00:00 2001 From: Fredrik Hernqvist Date: Tue, 21 May 2019 12:23:31 +0200 Subject: [PATCH] Make unpack_aecdump unpack RuntimeSettings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When running unpack_aecdump --full, unpack RuntimeSettings into files, on the format that can be imported into Audacity. Output one file for each RuntimeSetting present in the aecdump. If outputting several WAV files, output file for each WAV file with corresponding time stamps. Bug: webrtc:10643 Change-Id: If147e509d36207f5f838457354e2451df65549d7 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/137426 Commit-Queue: Fredrik Hernqvist Reviewed-by: Mirko Bonadei Reviewed-by: Alessio Bazzica Reviewed-by: Per Ã…hgren Cr-Commit-Position: refs/heads/master@{#28007} --- rtc_tools/BUILD.gn | 1 + rtc_tools/unpack_aecdump/unpack.cc | 121 +++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) diff --git a/rtc_tools/BUILD.gn b/rtc_tools/BUILD.gn index 6f1b855150..dbbed49c1c 100644 --- a/rtc_tools/BUILD.gn +++ b/rtc_tools/BUILD.gn @@ -473,6 +473,7 @@ if (rtc_include_tests) { ] deps = [ + "../api:function_view", "../common_audio", "../modules/audio_processing", "../modules/audio_processing:audioproc_debug_proto", diff --git a/rtc_tools/unpack_aecdump/unpack.cc b/rtc_tools/unpack_aecdump/unpack.cc index 78d8a118e1..88593fb44f 100644 --- a/rtc_tools/unpack_aecdump/unpack.cc +++ b/rtc_tools/unpack_aecdump/unpack.cc @@ -19,7 +19,9 @@ #include #include #include +#include +#include "api/function_view.h" #include "common_audio/wav_file.h" #include "modules/audio_processing/test/protobuf_utils.h" #include "modules/audio_processing/test/test_utils.h" @@ -103,6 +105,108 @@ bool WritingCallOrderFile() { return FLAG_full; } +bool WritingRuntimeSettingFiles() { + return FLAG_full; +} + +// Exports RuntimeSetting AEC dump events to Audacity-readable files. +// This class is not RAII compliant. +class RuntimeSettingWriter { + public: + RuntimeSettingWriter( + std::string name, + rtc::FunctionView is_exporter_for, + rtc::FunctionView get_timeline_label) + : setting_name_(std::move(name)), + is_exporter_for_(is_exporter_for), + get_timeline_label_(get_timeline_label) {} + ~RuntimeSettingWriter() { Flush(); } + + bool IsExporterFor(const Event& event) const { + return is_exporter_for_(event); + } + + // Writes to file the payload of |event| using |frame_count| to calculate + // timestamp. + void WriteEvent(const Event& event, int frame_count) { + RTC_DCHECK(is_exporter_for_(event)); + if (file_ == nullptr) { + rtc::StringBuilder file_name; + file_name << setting_name_ << frame_offset_ << ".txt"; + file_ = OpenFile(file_name.str(), "wb"); + } + + // Time in the current WAV file, in seconds. + double time = (frame_count - frame_offset_) / 100.0; + std::string label = get_timeline_label_(event); + // In Audacity, all annotations are encoded as intervals. + fprintf(file_, "%.6f\t%.6f\t%s \n", time, time, label.c_str()); + } + + // Handles an AEC dump initialization event, occurring at frame + // |frame_offset|. + void HandleInitEvent(int frame_offset) { + Flush(); + frame_offset_ = frame_offset; + } + + private: + void Flush() { + if (file_ != nullptr) { + fclose(file_); + file_ = nullptr; + } + } + + FILE* file_ = nullptr; + int frame_offset_ = 0; + const std::string setting_name_; + const rtc::FunctionView is_exporter_for_; + const rtc::FunctionView get_timeline_label_; +}; + +// Returns RuntimeSetting exporters for runtime setting types defined in +// debug.proto. +std::vector RuntimeSettingWriters() { + return { + RuntimeSettingWriter( + "CapturePreGain", + [](const Event& event) -> bool { + return event.runtime_setting().has_capture_pre_gain(); + }, + [](const Event& event) -> std::string { + return std::to_string(event.runtime_setting().capture_pre_gain()); + }), + RuntimeSettingWriter( + "CustomRenderProcessingRuntimeSetting", + [](const Event& event) -> bool { + return event.runtime_setting() + .has_custom_render_processing_setting(); + }, + [](const Event& event) -> std::string { + return std::to_string( + event.runtime_setting().custom_render_processing_setting()); + }), + RuntimeSettingWriter( + "CaptureFixedPostGain", + [](const Event& event) -> bool { + return event.runtime_setting().has_capture_fixed_post_gain(); + }, + [](const Event& event) -> std::string { + return std::to_string( + event.runtime_setting().capture_fixed_post_gain()); + }), + RuntimeSettingWriter( + "PlayoutVolumeChange", + [](const Event& event) -> bool { + return event.runtime_setting().has_playout_volume_change(); + }, + [](const Event& event) -> std::string { + return std::to_string( + event.runtime_setting().playout_volume_change()); + })}; +} + } // namespace int do_main(int argc, char* argv[]) { @@ -146,6 +250,9 @@ int do_main(int argc, char* argv[]) { : nullptr; FILE* settings_file = OpenFile(FLAG_settings_file, "wb"); + std::vector runtime_setting_writers = + RuntimeSettingWriters(); + while (ReadMessageFromFile(debug_file, &event_msg)) { if (event_msg.type() == Event::REVERSE_STREAM) { if (!event_msg.has_reverse_stream()) { @@ -386,6 +493,20 @@ int do_main(int argc, char* argv[]) { callorder_name << FLAG_callorder_file << frame_count << ".char"; callorder_char_file = OpenFile(callorder_name.str(), "wb"); } + + if (WritingRuntimeSettingFiles()) { + for (RuntimeSettingWriter& writer : runtime_setting_writers) { + writer.HandleInitEvent(frame_count); + } + } + } + } else if (event_msg.type() == Event::RUNTIME_SETTING) { + if (WritingRuntimeSettingFiles()) { + for (RuntimeSettingWriter& writer : runtime_setting_writers) { + if (writer.IsExporterFor(event_msg)) { + writer.WriteEvent(event_msg, frame_count); + } + } } } }