blob: 4ab6baad836039d6cbb14604d6a0457caffcc839 [file] [log] [blame]
peahb46083e2016-05-03 07:01:18 -07001/*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef MODULES_AUDIO_PROCESSING_LOGGING_APM_DATA_DUMPER_H_
12#define MODULES_AUDIO_PROCESSING_LOGGING_APM_DATA_DUMPER_H_
peahb46083e2016-05-03 07:01:18 -070013
Yves Gerey988cc082018-10-23 12:03:01 +020014#include <stdint.h>
peahb46083e2016-05-03 07:01:18 -070015#include <stdio.h>
16
Per Åhgrenf0c449e2018-10-23 20:17:18 +020017#if WEBRTC_APM_DEBUG_DUMP == 1
Jesús de Vicente Peñae5ccf5f2019-01-29 10:37:27 +010018#include <memory>
Ali Tofighf3592cb2022-08-16 14:44:38 +020019#include <string>
Per Åhgrenf0c449e2018-10-23 20:17:18 +020020#include <unordered_map>
21#endif
22
Ali Tofighf3592cb2022-08-16 14:44:38 +020023#include "absl/strings/string_view.h"
Per Åhgrenc2ae4c82021-01-20 15:42:13 +010024#include "absl/types/optional.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "api/array_view.h"
Per Åhgrenf0c449e2018-10-23 20:17:18 +020026#if WEBRTC_APM_DEBUG_DUMP == 1
27#include "common_audio/wav_file.h"
Alessio Bazzica4bc60452018-11-20 12:44:15 +010028#include "rtc_base/checks.h"
Ali Tofighf3592cb2022-08-16 14:44:38 +020029#include "rtc_base/string_utils.h"
Per Åhgrenf0c449e2018-10-23 20:17:18 +020030#endif
peahb46083e2016-05-03 07:01:18 -070031
32// Check to verify that the define is properly set.
peahf28a3892016-09-01 08:58:21 -070033#if !defined(WEBRTC_APM_DEBUG_DUMP) || \
34 (WEBRTC_APM_DEBUG_DUMP != 0 && WEBRTC_APM_DEBUG_DUMP != 1)
35#error "Set WEBRTC_APM_DEBUG_DUMP to either 0 or 1"
peahb46083e2016-05-03 07:01:18 -070036#endif
37
38namespace webrtc {
39
peahf28a3892016-09-01 08:58:21 -070040#if WEBRTC_APM_DEBUG_DUMP == 1
peahb46083e2016-05-03 07:01:18 -070041// Functor used to use as a custom deleter in the map of file pointers to raw
42// files.
43struct RawFileCloseFunctor {
44 void operator()(FILE* f) const { fclose(f); }
45};
46#endif
47
48// Class that handles dumping of variables into files.
49class ApmDataDumper {
50 public:
peahf8f754a2016-08-30 10:31:45 -070051 // Constructor that takes an instance index that may
52 // be used to distinguish data dumped from different
53 // instances of the code.
54 explicit ApmDataDumper(int instance_index);
55
Niels Möllerde953292020-09-29 09:46:21 +020056 ApmDataDumper() = delete;
57 ApmDataDumper(const ApmDataDumper&) = delete;
58 ApmDataDumper& operator=(const ApmDataDumper&) = delete;
59
peahf8f754a2016-08-30 10:31:45 -070060 ~ApmDataDumper();
peahb46083e2016-05-03 07:01:18 -070061
Per Åhgren7a95e0f2018-10-25 09:56:49 +020062 // Activates or deactivate the dumping functionality.
63 static void SetActivated(bool activated) {
64#if WEBRTC_APM_DEBUG_DUMP == 1
65 recording_activated_ = activated;
66#endif
67 }
68
Per Åhgren91a892f2021-05-07 23:28:42 +000069 // Returns whether dumping functionality is enabled/available.
70 static bool IsAvailable() {
71#if WEBRTC_APM_DEBUG_DUMP == 1
72 return true;
73#else
74 return false;
75#endif
76 }
77
Per Åhgrenc2ae4c82021-01-20 15:42:13 +010078 // Default dump set.
79 static constexpr size_t kDefaultDumpSet = 0;
80
81 // Specifies what dump set to use. All dump commands with a different dump set
82 // than the one specified will be discarded. If not specificed, all dump sets
83 // will be used.
84 static void SetDumpSetToUse(int dump_set_to_use) {
85#if WEBRTC_APM_DEBUG_DUMP == 1
86 dump_set_to_use_ = dump_set_to_use;
87#endif
88 }
89
Alessio Bazzica4bc60452018-11-20 12:44:15 +010090 // Set an optional output directory.
Ali Tofighf3592cb2022-08-16 14:44:38 +020091 static void SetOutputDirectory(absl::string_view output_dir) {
Alessio Bazzica4bc60452018-11-20 12:44:15 +010092#if WEBRTC_APM_DEBUG_DUMP == 1
93 RTC_CHECK_LT(output_dir.size(), kOutputDirMaxLength);
Ali Tofighf3592cb2022-08-16 14:44:38 +020094 rtc::strcpyn(output_dir_, output_dir.size(), output_dir);
Alessio Bazzica4bc60452018-11-20 12:44:15 +010095#endif
96 }
97
peahb46083e2016-05-03 07:01:18 -070098 // Reinitializes the data dumping such that new versions
99 // of all files being dumped to are created.
100 void InitiateNewSetOfRecordings() {
peahf28a3892016-09-01 08:58:21 -0700101#if WEBRTC_APM_DEBUG_DUMP == 1
peahb46083e2016-05-03 07:01:18 -0700102 ++recording_set_index_;
103#endif
104 }
105
106 // Methods for performing dumping of data of various types into
107 // various formats.
Ali Tofighf3592cb2022-08-16 14:44:38 +0200108 void DumpRaw(absl::string_view name,
109 double v,
110 int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800111#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100112 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
113 return;
114
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200115 if (recording_activated_) {
116 FILE* file = GetRawFile(name);
117 fwrite(&v, sizeof(v), 1, file);
118 }
peah69221db2017-01-27 03:28:19 -0800119#endif
120 }
121
Ali Tofighf3592cb2022-08-16 14:44:38 +0200122 void DumpRaw(absl::string_view name,
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100123 size_t v_length,
124 const double* v,
125 int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800126#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100127 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
128 return;
129
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200130 if (recording_activated_) {
131 FILE* file = GetRawFile(name);
132 fwrite(v, sizeof(v[0]), v_length, file);
133 }
peah69221db2017-01-27 03:28:19 -0800134#endif
135 }
136
Ali Tofighf3592cb2022-08-16 14:44:38 +0200137 void DumpRaw(absl::string_view name,
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100138 rtc::ArrayView<const double> v,
139 int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800140#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100141 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
142 return;
143
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200144 if (recording_activated_) {
145 DumpRaw(name, v.size(), v.data());
146 }
peah69221db2017-01-27 03:28:19 -0800147#endif
148 }
149
Ali Tofighf3592cb2022-08-16 14:44:38 +0200150 void DumpRaw(absl::string_view name,
151 float v,
152 int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800153#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100154 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
155 return;
156
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200157 if (recording_activated_) {
158 FILE* file = GetRawFile(name);
159 fwrite(&v, sizeof(v), 1, file);
160 }
peah69221db2017-01-27 03:28:19 -0800161#endif
162 }
163
Ali Tofighf3592cb2022-08-16 14:44:38 +0200164 void DumpRaw(absl::string_view name,
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100165 size_t v_length,
166 const float* v,
167 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700168#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100169 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
170 return;
171
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200172 if (recording_activated_) {
173 FILE* file = GetRawFile(name);
174 fwrite(v, sizeof(v[0]), v_length, file);
175 }
peahb46083e2016-05-03 07:01:18 -0700176#endif
177 }
178
Ali Tofighf3592cb2022-08-16 14:44:38 +0200179 void DumpRaw(absl::string_view name,
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100180 rtc::ArrayView<const float> v,
181 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700182#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100183 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
184 return;
185
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200186 if (recording_activated_) {
187 DumpRaw(name, v.size(), v.data());
188 }
peahb46083e2016-05-03 07:01:18 -0700189#endif
190 }
191
Ali Tofighf3592cb2022-08-16 14:44:38 +0200192 void DumpRaw(absl::string_view name, bool v, int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800193#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100194 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
195 return;
196
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200197 if (recording_activated_) {
198 DumpRaw(name, static_cast<int16_t>(v));
199 }
peah69221db2017-01-27 03:28:19 -0800200#endif
201 }
202
Ali Tofighf3592cb2022-08-16 14:44:38 +0200203 void DumpRaw(absl::string_view name,
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100204 size_t v_length,
205 const bool* v,
206 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700207#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100208 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
209 return;
210
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200211 if (recording_activated_) {
212 FILE* file = GetRawFile(name);
213 for (size_t k = 0; k < v_length; ++k) {
214 int16_t value = static_cast<int16_t>(v[k]);
215 fwrite(&value, sizeof(value), 1, file);
216 }
peahca4cac72016-06-29 15:26:12 -0700217 }
218#endif
219 }
220
Ali Tofighf3592cb2022-08-16 14:44:38 +0200221 void DumpRaw(absl::string_view name,
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100222 rtc::ArrayView<const bool> v,
223 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700224#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100225 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
226 return;
227
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200228 if (recording_activated_) {
229 DumpRaw(name, v.size(), v.data());
230 }
peahca4cac72016-06-29 15:26:12 -0700231#endif
232 }
233
Ali Tofighf3592cb2022-08-16 14:44:38 +0200234 void DumpRaw(absl::string_view name,
235 int16_t v,
236 int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800237#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100238 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
239 return;
240
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200241 if (recording_activated_) {
242 FILE* file = GetRawFile(name);
243 fwrite(&v, sizeof(v), 1, file);
244 }
peah69221db2017-01-27 03:28:19 -0800245#endif
246 }
247
Ali Tofighf3592cb2022-08-16 14:44:38 +0200248 void DumpRaw(absl::string_view name,
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100249 size_t v_length,
250 const int16_t* v,
251 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700252#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100253 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
254 return;
255
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200256 if (recording_activated_) {
257 FILE* file = GetRawFile(name);
258 fwrite(v, sizeof(v[0]), v_length, file);
259 }
peah3f08dc62016-05-05 03:03:55 -0700260#endif
261 }
262
Ali Tofighf3592cb2022-08-16 14:44:38 +0200263 void DumpRaw(absl::string_view name,
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100264 rtc::ArrayView<const int16_t> v,
265 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700266#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100267 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
268 return;
269
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200270 if (recording_activated_) {
271 DumpRaw(name, v.size(), v.data());
272 }
peah3f08dc62016-05-05 03:03:55 -0700273#endif
274 }
275
Ali Tofighf3592cb2022-08-16 14:44:38 +0200276 void DumpRaw(absl::string_view name,
277 int32_t v,
278 int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800279#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100280 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
281 return;
282
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200283 if (recording_activated_) {
284 FILE* file = GetRawFile(name);
285 fwrite(&v, sizeof(v), 1, file);
286 }
peah69221db2017-01-27 03:28:19 -0800287#endif
288 }
289
Ali Tofighf3592cb2022-08-16 14:44:38 +0200290 void DumpRaw(absl::string_view name,
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100291 size_t v_length,
292 const int32_t* v,
293 int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800294#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100295 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
296 return;
297
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200298 if (recording_activated_) {
299 FILE* file = GetRawFile(name);
300 fwrite(v, sizeof(v[0]), v_length, file);
301 }
peah69221db2017-01-27 03:28:19 -0800302#endif
303 }
304
Ali Tofighf3592cb2022-08-16 14:44:38 +0200305 void DumpRaw(absl::string_view name,
306 size_t v,
307 int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800308#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100309 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
310 return;
311
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200312 if (recording_activated_) {
313 FILE* file = GetRawFile(name);
314 fwrite(&v, sizeof(v), 1, file);
315 }
peah69221db2017-01-27 03:28:19 -0800316#endif
317 }
318
Ali Tofighf3592cb2022-08-16 14:44:38 +0200319 void DumpRaw(absl::string_view name,
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100320 size_t v_length,
321 const size_t* v,
322 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700323#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100324 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
325 return;
326
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200327 if (recording_activated_) {
328 FILE* file = GetRawFile(name);
329 fwrite(v, sizeof(v[0]), v_length, file);
330 }
peah3f08dc62016-05-05 03:03:55 -0700331#endif
332 }
333
Ali Tofighf3592cb2022-08-16 14:44:38 +0200334 void DumpRaw(absl::string_view name,
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100335 rtc::ArrayView<const int32_t> v,
336 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700337#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100338 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
339 return;
340
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200341 if (recording_activated_) {
342 DumpRaw(name, v.size(), v.data());
343 }
peah3f08dc62016-05-05 03:03:55 -0700344#endif
345 }
346
Ali Tofighf3592cb2022-08-16 14:44:38 +0200347 void DumpRaw(absl::string_view name,
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100348 rtc::ArrayView<const size_t> v,
349 int dump_set = kDefaultDumpSet) {
Jesús de Vicente Peña44974e12018-11-20 12:54:23 +0100350#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100351 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
352 return;
353
Jesús de Vicente Peña44974e12018-11-20 12:54:23 +0100354 DumpRaw(name, v.size(), v.data());
355#endif
356 }
357
Ali Tofighf3592cb2022-08-16 14:44:38 +0200358 void DumpWav(absl::string_view name,
peah69221db2017-01-27 03:28:19 -0800359 size_t v_length,
peahb46083e2016-05-03 07:01:18 -0700360 const float* v,
361 int sample_rate_hz,
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100362 int num_channels,
363 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700364#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100365 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
366 return;
367
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200368 if (recording_activated_) {
Per Åhgren5dca3f12020-01-28 09:08:11 +0100369 WavWriter* file = GetWavFile(name, sample_rate_hz, num_channels,
370 WavFile::SampleFormat::kFloat);
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200371 file->WriteSamples(v, v_length);
372 }
peahb46083e2016-05-03 07:01:18 -0700373#endif
374 }
375
Ali Tofighf3592cb2022-08-16 14:44:38 +0200376 void DumpWav(absl::string_view name,
peahca4cac72016-06-29 15:26:12 -0700377 rtc::ArrayView<const float> v,
378 int sample_rate_hz,
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100379 int num_channels,
380 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700381#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100382 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
383 return;
384
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200385 if (recording_activated_) {
386 DumpWav(name, v.size(), v.data(), sample_rate_hz, num_channels);
387 }
peahca4cac72016-06-29 15:26:12 -0700388#endif
389 }
390
peahb46083e2016-05-03 07:01:18 -0700391 private:
peahf28a3892016-09-01 08:58:21 -0700392#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200393 static bool recording_activated_;
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100394 static absl::optional<int> dump_set_to_use_;
Alessio Bazzica4bc60452018-11-20 12:44:15 +0100395 static constexpr size_t kOutputDirMaxLength = 1024;
396 static char output_dir_[kOutputDirMaxLength];
peahb46083e2016-05-03 07:01:18 -0700397 const int instance_index_;
398 int recording_set_index_ = 0;
399 std::unordered_map<std::string, std::unique_ptr<FILE, RawFileCloseFunctor>>
400 raw_files_;
401 std::unordered_map<std::string, std::unique_ptr<WavWriter>> wav_files_;
402
Ali Tofighf3592cb2022-08-16 14:44:38 +0200403 FILE* GetRawFile(absl::string_view name);
404 WavWriter* GetWavFile(absl::string_view name,
Per Åhgren5dca3f12020-01-28 09:08:11 +0100405 int sample_rate_hz,
406 int num_channels,
407 WavFile::SampleFormat format);
peahb46083e2016-05-03 07:01:18 -0700408#endif
peahb46083e2016-05-03 07:01:18 -0700409};
410
411} // namespace webrtc
412
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200413#endif // MODULES_AUDIO_PROCESSING_LOGGING_APM_DATA_DUMPER_H_