blob: 9c2ac3be5d2d93fe69e12216c1bf2294680d3bfb [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>
Alessio Bazzica4bc60452018-11-20 12:44:15 +010016#include <string.h>
peahb46083e2016-05-03 07:01:18 -070017
Alessio Bazzica4bc60452018-11-20 12:44:15 +010018#include <string>
Per Åhgrenf0c449e2018-10-23 20:17:18 +020019#if WEBRTC_APM_DEBUG_DUMP == 1
Jesús de Vicente Peñae5ccf5f2019-01-29 10:37:27 +010020#include <memory>
Per Åhgrenf0c449e2018-10-23 20:17:18 +020021#include <unordered_map>
22#endif
23
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"
Per Åhgrenf0c449e2018-10-23 20:17:18 +020029#endif
peahb46083e2016-05-03 07:01:18 -070030
31// Check to verify that the define is properly set.
peahf28a3892016-09-01 08:58:21 -070032#if !defined(WEBRTC_APM_DEBUG_DUMP) || \
33 (WEBRTC_APM_DEBUG_DUMP != 0 && WEBRTC_APM_DEBUG_DUMP != 1)
34#error "Set WEBRTC_APM_DEBUG_DUMP to either 0 or 1"
peahb46083e2016-05-03 07:01:18 -070035#endif
36
37namespace webrtc {
38
peahf28a3892016-09-01 08:58:21 -070039#if WEBRTC_APM_DEBUG_DUMP == 1
peahb46083e2016-05-03 07:01:18 -070040// Functor used to use as a custom deleter in the map of file pointers to raw
41// files.
42struct RawFileCloseFunctor {
43 void operator()(FILE* f) const { fclose(f); }
44};
45#endif
46
47// Class that handles dumping of variables into files.
48class ApmDataDumper {
49 public:
peahf8f754a2016-08-30 10:31:45 -070050 // Constructor that takes an instance index that may
51 // be used to distinguish data dumped from different
52 // instances of the code.
53 explicit ApmDataDumper(int instance_index);
54
Niels Möllerde953292020-09-29 09:46:21 +020055 ApmDataDumper() = delete;
56 ApmDataDumper(const ApmDataDumper&) = delete;
57 ApmDataDumper& operator=(const ApmDataDumper&) = delete;
58
peahf8f754a2016-08-30 10:31:45 -070059 ~ApmDataDumper();
peahb46083e2016-05-03 07:01:18 -070060
Per Åhgren7a95e0f2018-10-25 09:56:49 +020061 // Activates or deactivate the dumping functionality.
62 static void SetActivated(bool activated) {
63#if WEBRTC_APM_DEBUG_DUMP == 1
64 recording_activated_ = activated;
65#endif
66 }
67
Per Åhgren91a892f2021-05-07 23:28:42 +000068 // Returns whether dumping functionality is enabled/available.
69 static bool IsAvailable() {
70#if WEBRTC_APM_DEBUG_DUMP == 1
71 return true;
72#else
73 return false;
74#endif
75 }
76
Per Åhgrenc2ae4c82021-01-20 15:42:13 +010077 // Default dump set.
78 static constexpr size_t kDefaultDumpSet = 0;
79
80 // Specifies what dump set to use. All dump commands with a different dump set
81 // than the one specified will be discarded. If not specificed, all dump sets
82 // will be used.
83 static void SetDumpSetToUse(int dump_set_to_use) {
84#if WEBRTC_APM_DEBUG_DUMP == 1
85 dump_set_to_use_ = dump_set_to_use;
86#endif
87 }
88
Alessio Bazzica4bc60452018-11-20 12:44:15 +010089 // Set an optional output directory.
90 static void SetOutputDirectory(const std::string& output_dir) {
91#if WEBRTC_APM_DEBUG_DUMP == 1
92 RTC_CHECK_LT(output_dir.size(), kOutputDirMaxLength);
93 strncpy(output_dir_, output_dir.c_str(), output_dir.size());
94#endif
95 }
96
peahb46083e2016-05-03 07:01:18 -070097 // Reinitializes the data dumping such that new versions
98 // of all files being dumped to are created.
99 void InitiateNewSetOfRecordings() {
peahf28a3892016-09-01 08:58:21 -0700100#if WEBRTC_APM_DEBUG_DUMP == 1
peahb46083e2016-05-03 07:01:18 -0700101 ++recording_set_index_;
102#endif
103 }
104
105 // Methods for performing dumping of data of various types into
106 // various formats.
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100107 void DumpRaw(const char* name, double v, int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800108#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100109 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
110 return;
111
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200112 if (recording_activated_) {
113 FILE* file = GetRawFile(name);
114 fwrite(&v, sizeof(v), 1, file);
115 }
peah69221db2017-01-27 03:28:19 -0800116#endif
117 }
118
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100119 void DumpRaw(const char* name,
120 size_t v_length,
121 const double* v,
122 int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800123#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100124 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
125 return;
126
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200127 if (recording_activated_) {
128 FILE* file = GetRawFile(name);
129 fwrite(v, sizeof(v[0]), v_length, file);
130 }
peah69221db2017-01-27 03:28:19 -0800131#endif
132 }
133
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100134 void DumpRaw(const char* name,
135 rtc::ArrayView<const double> v,
136 int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800137#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100138 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
139 return;
140
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200141 if (recording_activated_) {
142 DumpRaw(name, v.size(), v.data());
143 }
peah69221db2017-01-27 03:28:19 -0800144#endif
145 }
146
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100147 void DumpRaw(const char* name, float v, int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800148#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100149 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
150 return;
151
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200152 if (recording_activated_) {
153 FILE* file = GetRawFile(name);
154 fwrite(&v, sizeof(v), 1, file);
155 }
peah69221db2017-01-27 03:28:19 -0800156#endif
157 }
158
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100159 void DumpRaw(const char* name,
160 size_t v_length,
161 const float* v,
162 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700163#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100164 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
165 return;
166
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200167 if (recording_activated_) {
168 FILE* file = GetRawFile(name);
169 fwrite(v, sizeof(v[0]), v_length, file);
170 }
peahb46083e2016-05-03 07:01:18 -0700171#endif
172 }
173
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100174 void DumpRaw(const char* name,
175 rtc::ArrayView<const float> v,
176 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700177#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100178 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
179 return;
180
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200181 if (recording_activated_) {
182 DumpRaw(name, v.size(), v.data());
183 }
peahb46083e2016-05-03 07:01:18 -0700184#endif
185 }
186
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100187 void DumpRaw(const char* name, bool v, int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800188#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100189 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
190 return;
191
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200192 if (recording_activated_) {
193 DumpRaw(name, static_cast<int16_t>(v));
194 }
peah69221db2017-01-27 03:28:19 -0800195#endif
196 }
197
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100198 void DumpRaw(const char* name,
199 size_t v_length,
200 const bool* v,
201 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700202#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100203 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
204 return;
205
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200206 if (recording_activated_) {
207 FILE* file = GetRawFile(name);
208 for (size_t k = 0; k < v_length; ++k) {
209 int16_t value = static_cast<int16_t>(v[k]);
210 fwrite(&value, sizeof(value), 1, file);
211 }
peahca4cac72016-06-29 15:26:12 -0700212 }
213#endif
214 }
215
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100216 void DumpRaw(const char* name,
217 rtc::ArrayView<const bool> v,
218 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700219#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100220 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
221 return;
222
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200223 if (recording_activated_) {
224 DumpRaw(name, v.size(), v.data());
225 }
peahca4cac72016-06-29 15:26:12 -0700226#endif
227 }
228
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100229 void DumpRaw(const char* name, int16_t v, int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800230#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100231 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
232 return;
233
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200234 if (recording_activated_) {
235 FILE* file = GetRawFile(name);
236 fwrite(&v, sizeof(v), 1, file);
237 }
peah69221db2017-01-27 03:28:19 -0800238#endif
239 }
240
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100241 void DumpRaw(const char* name,
242 size_t v_length,
243 const int16_t* v,
244 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700245#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100246 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
247 return;
248
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200249 if (recording_activated_) {
250 FILE* file = GetRawFile(name);
251 fwrite(v, sizeof(v[0]), v_length, file);
252 }
peah3f08dc62016-05-05 03:03:55 -0700253#endif
254 }
255
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100256 void DumpRaw(const char* name,
257 rtc::ArrayView<const int16_t> v,
258 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700259#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100260 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
261 return;
262
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200263 if (recording_activated_) {
264 DumpRaw(name, v.size(), v.data());
265 }
peah3f08dc62016-05-05 03:03:55 -0700266#endif
267 }
268
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100269 void DumpRaw(const char* name, int32_t v, int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800270#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100271 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
272 return;
273
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200274 if (recording_activated_) {
275 FILE* file = GetRawFile(name);
276 fwrite(&v, sizeof(v), 1, file);
277 }
peah69221db2017-01-27 03:28:19 -0800278#endif
279 }
280
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100281 void DumpRaw(const char* name,
282 size_t v_length,
283 const int32_t* v,
284 int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800285#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100286 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
287 return;
288
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200289 if (recording_activated_) {
290 FILE* file = GetRawFile(name);
291 fwrite(v, sizeof(v[0]), v_length, file);
292 }
peah69221db2017-01-27 03:28:19 -0800293#endif
294 }
295
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100296 void DumpRaw(const char* name, size_t v, int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800297#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100298 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
299 return;
300
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200301 if (recording_activated_) {
302 FILE* file = GetRawFile(name);
303 fwrite(&v, sizeof(v), 1, file);
304 }
peah69221db2017-01-27 03:28:19 -0800305#endif
306 }
307
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100308 void DumpRaw(const char* name,
309 size_t v_length,
310 const size_t* v,
311 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700312#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100313 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
314 return;
315
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200316 if (recording_activated_) {
317 FILE* file = GetRawFile(name);
318 fwrite(v, sizeof(v[0]), v_length, file);
319 }
peah3f08dc62016-05-05 03:03:55 -0700320#endif
321 }
322
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100323 void DumpRaw(const char* name,
324 rtc::ArrayView<const int32_t> v,
325 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700326#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100327 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
328 return;
329
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200330 if (recording_activated_) {
331 DumpRaw(name, v.size(), v.data());
332 }
peah3f08dc62016-05-05 03:03:55 -0700333#endif
334 }
335
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100336 void DumpRaw(const char* name,
337 rtc::ArrayView<const size_t> v,
338 int dump_set = kDefaultDumpSet) {
Jesús de Vicente Peña44974e12018-11-20 12:54:23 +0100339#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100340 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
341 return;
342
Jesús de Vicente Peña44974e12018-11-20 12:54:23 +0100343 DumpRaw(name, v.size(), v.data());
344#endif
345 }
346
peahb46083e2016-05-03 07:01:18 -0700347 void DumpWav(const char* name,
peah69221db2017-01-27 03:28:19 -0800348 size_t v_length,
peahb46083e2016-05-03 07:01:18 -0700349 const float* v,
350 int sample_rate_hz,
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100351 int num_channels,
352 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700353#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100354 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
355 return;
356
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200357 if (recording_activated_) {
Per Åhgren5dca3f12020-01-28 09:08:11 +0100358 WavWriter* file = GetWavFile(name, sample_rate_hz, num_channels,
359 WavFile::SampleFormat::kFloat);
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200360 file->WriteSamples(v, v_length);
361 }
peahb46083e2016-05-03 07:01:18 -0700362#endif
363 }
364
peahca4cac72016-06-29 15:26:12 -0700365 void DumpWav(const char* name,
366 rtc::ArrayView<const float> v,
367 int sample_rate_hz,
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100368 int num_channels,
369 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700370#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100371 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
372 return;
373
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200374 if (recording_activated_) {
375 DumpWav(name, v.size(), v.data(), sample_rate_hz, num_channels);
376 }
peahca4cac72016-06-29 15:26:12 -0700377#endif
378 }
379
peahb46083e2016-05-03 07:01:18 -0700380 private:
peahf28a3892016-09-01 08:58:21 -0700381#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200382 static bool recording_activated_;
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100383 static absl::optional<int> dump_set_to_use_;
Alessio Bazzica4bc60452018-11-20 12:44:15 +0100384 static constexpr size_t kOutputDirMaxLength = 1024;
385 static char output_dir_[kOutputDirMaxLength];
peahb46083e2016-05-03 07:01:18 -0700386 const int instance_index_;
387 int recording_set_index_ = 0;
388 std::unordered_map<std::string, std::unique_ptr<FILE, RawFileCloseFunctor>>
389 raw_files_;
390 std::unordered_map<std::string, std::unique_ptr<WavWriter>> wav_files_;
391
392 FILE* GetRawFile(const char* name);
Per Åhgren5dca3f12020-01-28 09:08:11 +0100393 WavWriter* GetWavFile(const char* name,
394 int sample_rate_hz,
395 int num_channels,
396 WavFile::SampleFormat format);
peahb46083e2016-05-03 07:01:18 -0700397#endif
peahb46083e2016-05-03 07:01:18 -0700398};
399
400} // namespace webrtc
401
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200402#endif // MODULES_AUDIO_PROCESSING_LOGGING_APM_DATA_DUMPER_H_