Make unpack_aecdump unpack RuntimeSettings

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 <fhernqvist@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Alessio Bazzica <alessiob@webrtc.org>
Reviewed-by: Per Åhgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28007}
This commit is contained in:
Fredrik Hernqvist
2019-05-21 12:23:31 +02:00
committed by Commit Bot
parent b0ac94307e
commit 3be9da37bb
2 changed files with 122 additions and 0 deletions

View File

@ -473,6 +473,7 @@ if (rtc_include_tests) {
] ]
deps = [ deps = [
"../api:function_view",
"../common_audio", "../common_audio",
"../modules/audio_processing", "../modules/audio_processing",
"../modules/audio_processing:audioproc_debug_proto", "../modules/audio_processing:audioproc_debug_proto",

View File

@ -19,7 +19,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector>
#include "api/function_view.h"
#include "common_audio/wav_file.h" #include "common_audio/wav_file.h"
#include "modules/audio_processing/test/protobuf_utils.h" #include "modules/audio_processing/test/protobuf_utils.h"
#include "modules/audio_processing/test/test_utils.h" #include "modules/audio_processing/test/test_utils.h"
@ -103,6 +105,108 @@ bool WritingCallOrderFile() {
return FLAG_full; 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<bool(const Event)> is_exporter_for,
rtc::FunctionView<std::string(const Event)> 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<bool(Event)> is_exporter_for_;
const rtc::FunctionView<std::string(Event)> get_timeline_label_;
};
// Returns RuntimeSetting exporters for runtime setting types defined in
// debug.proto.
std::vector<RuntimeSettingWriter> 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 } // namespace
int do_main(int argc, char* argv[]) { int do_main(int argc, char* argv[]) {
@ -146,6 +250,9 @@ int do_main(int argc, char* argv[]) {
: nullptr; : nullptr;
FILE* settings_file = OpenFile(FLAG_settings_file, "wb"); FILE* settings_file = OpenFile(FLAG_settings_file, "wb");
std::vector<RuntimeSettingWriter> runtime_setting_writers =
RuntimeSettingWriters();
while (ReadMessageFromFile(debug_file, &event_msg)) { while (ReadMessageFromFile(debug_file, &event_msg)) {
if (event_msg.type() == Event::REVERSE_STREAM) { if (event_msg.type() == Event::REVERSE_STREAM) {
if (!event_msg.has_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_name << FLAG_callorder_file << frame_count << ".char";
callorder_char_file = OpenFile(callorder_name.str(), "wb"); 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);
}
}
} }
} }
} }