summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/audio_processing/logging
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/modules/audio_processing/logging')
-rw-r--r--third_party/libwebrtc/modules/audio_processing/logging/apm_data_dumper.cc100
-rw-r--r--third_party/libwebrtc/modules/audio_processing/logging/apm_data_dumper.h452
2 files changed, 552 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/audio_processing/logging/apm_data_dumper.cc b/third_party/libwebrtc/modules/audio_processing/logging/apm_data_dumper.cc
new file mode 100644
index 0000000000..a15321ad48
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_processing/logging/apm_data_dumper.cc
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_processing/logging/apm_data_dumper.h"
+
+#include "absl/strings/string_view.h"
+#include "rtc_base/strings/string_builder.h"
+
+// Check to verify that the define is properly set.
+#if !defined(WEBRTC_APM_DEBUG_DUMP) || \
+ (WEBRTC_APM_DEBUG_DUMP != 0 && WEBRTC_APM_DEBUG_DUMP != 1)
+#error "Set WEBRTC_APM_DEBUG_DUMP to either 0 or 1"
+#endif
+
+namespace webrtc {
+namespace {
+
+#if WEBRTC_APM_DEBUG_DUMP == 1
+
+#if defined(WEBRTC_WIN)
+constexpr char kPathDelimiter = '\\';
+#else
+constexpr char kPathDelimiter = '/';
+#endif
+
+std::string FormFileName(absl::string_view output_dir,
+ absl::string_view name,
+ int instance_index,
+ int reinit_index,
+ absl::string_view suffix) {
+#ifdef WEBRTC_WIN
+ char sep = '\\';
+#else
+ char sep = '/';
+#endif
+
+ std::stringstream ss;
+ std::string base = rtc::LogMessage::aec_debug_filename();
+ ss << base;
+
+ if (base.length() && base.back() != sep) {
+ ss << sep;
+ }
+
+ ss << name << "_" << instance_index << "-" << reinit_index << suffix;
+ return ss.str();
+}
+#endif
+
+} // namespace
+
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ApmDataDumper::ApmDataDumper(int instance_index)
+ : instance_index_(instance_index)
+ , debug_written_(0) {}
+#else
+ApmDataDumper::ApmDataDumper(int instance_index) {}
+#endif
+
+ApmDataDumper::~ApmDataDumper() = default;
+
+#if WEBRTC_APM_DEBUG_DUMP == 1
+bool ApmDataDumper::recording_activated_ = false;
+absl::optional<int> ApmDataDumper::dump_set_to_use_;
+char ApmDataDumper::output_dir_[] = "";
+
+FILE* ApmDataDumper::GetRawFile(absl::string_view name) {
+ std::string filename = FormFileName(output_dir_, name, instance_index_,
+ recording_set_index_, ".dat");
+ auto& f = raw_files_[filename];
+ if (!f) {
+ f.reset(fopen(filename.c_str(), "wb"));
+ RTC_CHECK(f.get()) << "Cannot write to " << filename << ".";
+ }
+ return f.get();
+}
+
+WavWriter* ApmDataDumper::GetWavFile(absl::string_view name,
+ int sample_rate_hz,
+ int num_channels,
+ WavFile::SampleFormat format) {
+ std::string filename = FormFileName(output_dir_, name, instance_index_,
+ recording_set_index_, ".wav");
+ auto& f = wav_files_[filename];
+ if (!f) {
+ f.reset(
+ new WavWriter(filename.c_str(), sample_rate_hz, num_channels, format));
+ }
+ return f.get();
+}
+#endif
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/audio_processing/logging/apm_data_dumper.h b/third_party/libwebrtc/modules/audio_processing/logging/apm_data_dumper.h
new file mode 100644
index 0000000000..aa8496819b
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_processing/logging/apm_data_dumper.h
@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_PROCESSING_LOGGING_APM_DATA_DUMPER_H_
+#define MODULES_AUDIO_PROCESSING_LOGGING_APM_DATA_DUMPER_H_
+
+#include <stdint.h>
+#include <stdio.h>
+
+#if WEBRTC_APM_DEBUG_DUMP == 1
+#include <memory>
+#include <string>
+#include <unordered_map>
+#endif
+
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#if WEBRTC_APM_DEBUG_DUMP == 1
+#include "common_audio/wav_file.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/string_utils.h"
+#endif
+
+// Check to verify that the define is properly set.
+#if !defined(WEBRTC_APM_DEBUG_DUMP) || \
+ (WEBRTC_APM_DEBUG_DUMP != 0 && WEBRTC_APM_DEBUG_DUMP != 1)
+#error "Set WEBRTC_APM_DEBUG_DUMP to either 0 or 1"
+#endif
+
+namespace webrtc {
+
+#if WEBRTC_APM_DEBUG_DUMP == 1
+// Functor used to use as a custom deleter in the map of file pointers to raw
+// files.
+struct RawFileCloseFunctor {
+ void operator()(FILE* f) const { if (f) fclose(f); }
+};
+#endif
+
+// Class that handles dumping of variables into files.
+class ApmDataDumper {
+ public:
+ // Constructor that takes an instance index that may
+ // be used to distinguish data dumped from different
+ // instances of the code.
+ explicit ApmDataDumper(int instance_index);
+
+ ApmDataDumper() = delete;
+ ApmDataDumper(const ApmDataDumper&) = delete;
+ ApmDataDumper& operator=(const ApmDataDumper&) = delete;
+
+ ~ApmDataDumper();
+
+ // Activates or deactivate the dumping functionality.
+ static void SetActivated(bool activated) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ recording_activated_ = activated;
+#endif
+ }
+
+ // Returns whether dumping functionality is enabled/available.
+ static bool IsAvailable() {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ return true;
+#else
+ return false;
+#endif
+ }
+
+ // Default dump set.
+ static constexpr size_t kDefaultDumpSet = 0;
+
+ // Specifies what dump set to use. All dump commands with a different dump set
+ // than the one specified will be discarded. If not specificed, all dump sets
+ // will be used.
+ static void SetDumpSetToUse(int dump_set_to_use) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ dump_set_to_use_ = dump_set_to_use;
+#endif
+ }
+
+ // Set an optional output directory.
+ static void SetOutputDirectory(absl::string_view output_dir) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ RTC_CHECK_LT(output_dir.size(), kOutputDirMaxLength);
+ rtc::strcpyn(output_dir_, output_dir.size(), output_dir);
+#endif
+ }
+
+ // Reinitializes the data dumping such that new versions
+ // of all files being dumped to are created.
+ void InitiateNewSetOfRecordings() {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ ++recording_set_index_;
+ debug_written_ = 0;
+#endif
+ }
+
+ // Methods for performing dumping of data of various types into
+ // various formats.
+ void DumpRaw(absl::string_view name,
+ double v,
+ int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+ if (file) {
+ fwrite(&v, sizeof(v), 1, file);
+ }
+ }
+#endif
+ }
+
+ void DumpRaw(absl::string_view name,
+ size_t v_length,
+ const double* v,
+ int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+ if (file) {
+ fwrite(v, sizeof(v[0]), v_length, file);
+ }
+ }
+#endif
+ }
+
+ void DumpRaw(absl::string_view name,
+ rtc::ArrayView<const double> v,
+ int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ if (recording_activated_) {
+ DumpRaw(name, v.size(), v.data());
+ }
+#endif
+ }
+
+ void DumpRaw(absl::string_view name,
+ float v,
+ int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+ if (file) {
+ fwrite(&v, sizeof(v), 1, file);
+ }
+ }
+#endif
+ }
+
+ void DumpRaw(absl::string_view name,
+ size_t v_length,
+ const float* v,
+ int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+ if (file) {
+ fwrite(v, sizeof(v[0]), v_length, file);
+ }
+ }
+#endif
+ }
+
+ void DumpRaw(absl::string_view name,
+ rtc::ArrayView<const float> v,
+ int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ if (recording_activated_) {
+ DumpRaw(name, v.size(), v.data());
+ }
+#endif
+ }
+
+ void DumpRaw(absl::string_view name, bool v, int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ if (recording_activated_) {
+ DumpRaw(name, static_cast<int16_t>(v));
+ }
+#endif
+ }
+
+ void DumpRaw(absl::string_view name,
+ size_t v_length,
+ const bool* v,
+ int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+ if (file) {
+ for (size_t k = 0; k < v_length; ++k) {
+ int16_t value = static_cast<int16_t>(v[k]);
+ fwrite(&value, sizeof(value), 1, file);
+ }
+ }
+ }
+#endif
+ }
+
+ void DumpRaw(absl::string_view name,
+ rtc::ArrayView<const bool> v,
+ int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ if (recording_activated_) {
+ DumpRaw(name, v.size(), v.data());
+ }
+#endif
+ }
+
+ void DumpRaw(absl::string_view name,
+ int16_t v,
+ int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+ if (file) {
+ fwrite(&v, sizeof(v), 1, file);
+ }
+ }
+#endif
+ }
+
+ void DumpRaw(absl::string_view name,
+ size_t v_length,
+ const int16_t* v,
+ int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+ if (file) {
+ fwrite(v, sizeof(v[0]), v_length, file);
+ }
+ }
+#endif
+ }
+
+ void DumpRaw(absl::string_view name,
+ rtc::ArrayView<const int16_t> v,
+ int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ if (recording_activated_) {
+ DumpRaw(name, v.size(), v.data());
+ }
+#endif
+ }
+
+ void DumpRaw(absl::string_view name,
+ int32_t v,
+ int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+ if (file) {
+ fwrite(&v, sizeof(v), 1, file);
+ }
+ }
+#endif
+ }
+
+ void DumpRaw(absl::string_view name,
+ size_t v_length,
+ const int32_t* v,
+ int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+ if (file) {
+ fwrite(v, sizeof(v[0]), v_length, file);
+ }
+ }
+#endif
+ }
+
+ void DumpRaw(absl::string_view name,
+ size_t v,
+ int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+ if (file) {
+ fwrite(&v, sizeof(v), 1, file);
+ }
+ }
+#endif
+ }
+
+ void DumpRaw(absl::string_view name,
+ size_t v_length,
+ const size_t* v,
+ int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+ if (file) {
+ fwrite(v, sizeof(v[0]), v_length, file);
+ }
+ }
+#endif
+ }
+
+ void DumpRaw(absl::string_view name,
+ rtc::ArrayView<const int32_t> v,
+ int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ if (recording_activated_) {
+ DumpRaw(name, v.size(), v.data());
+ }
+#endif
+ }
+
+ void DumpRaw(absl::string_view name,
+ rtc::ArrayView<const size_t> v,
+ int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ DumpRaw(name, v.size(), v.data());
+#endif
+ }
+
+ void DumpWav(absl::string_view name,
+ size_t v_length,
+ const float* v,
+ int sample_rate_hz,
+ int num_channels,
+ int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ if (recording_activated_) {
+ WavWriter* file = GetWavFile(name, sample_rate_hz, num_channels,
+ WavFile::SampleFormat::kFloat);
+ file->WriteSamples(v, v_length);
+ // Cheat and use aec_near as a stand-in for "size of the largest file"
+ // in the dump. We're looking to limit the total time, and that's a
+ // reasonable stand-in.
+ if (strcmp(name, "aec_near") == 0) {
+ updateDebugWritten(v_length * sizeof(float));
+ }
+ }
+#endif
+ }
+
+ void DumpWav(absl::string_view name,
+ rtc::ArrayView<const float> v,
+ int sample_rate_hz,
+ int num_channels,
+ int dump_set = kDefaultDumpSet) {
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
+ return;
+
+ if (recording_activated_) {
+ DumpWav(name, v.size(), v.data(), sample_rate_hz, num_channels);
+ }
+#endif
+ }
+
+ private:
+#if WEBRTC_APM_DEBUG_DUMP == 1
+ static bool recording_activated_;
+ static absl::optional<int> dump_set_to_use_;
+ static constexpr size_t kOutputDirMaxLength = 1024;
+ static char output_dir_[kOutputDirMaxLength];
+ const int instance_index_;
+ int recording_set_index_ = 0;
+ std::unordered_map<std::string, std::unique_ptr<FILE, RawFileCloseFunctor>>
+ raw_files_;
+ std::unordered_map<std::string, std::unique_ptr<WavWriter>> wav_files_;
+
+ FILE* GetRawFile(absl::string_view name);
+ WavWriter* GetWavFile(absl::string_view name,
+ int sample_rate_hz,
+ int num_channels,
+ WavFile::SampleFormat format);
+
+ uint32_t debug_written_ = 0;
+
+ void updateDebugWritten(uint32_t amount) {
+ debug_written_ += amount;
+ if (debug_written_ >= webrtc::Trace::aec_debug_size()) {
+ SetActivated(false);
+ }
+ }
+
+#endif
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_PROCESSING_LOGGING_APM_DATA_DUMPER_H_