blob: 6d32b32ab5dda054acc4e67fb9804c5899eda2b2 [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 Åhgrenc2ae4c82021-01-20 15:42:13 +010068 // Default dump set.
69 static constexpr size_t kDefaultDumpSet = 0;
70
71 // Specifies what dump set to use. All dump commands with a different dump set
72 // than the one specified will be discarded. If not specificed, all dump sets
73 // will be used.
74 static void SetDumpSetToUse(int dump_set_to_use) {
75#if WEBRTC_APM_DEBUG_DUMP == 1
76 dump_set_to_use_ = dump_set_to_use;
77#endif
78 }
79
Alessio Bazzica4bc60452018-11-20 12:44:15 +010080 // Set an optional output directory.
81 static void SetOutputDirectory(const std::string& output_dir) {
82#if WEBRTC_APM_DEBUG_DUMP == 1
83 RTC_CHECK_LT(output_dir.size(), kOutputDirMaxLength);
84 strncpy(output_dir_, output_dir.c_str(), output_dir.size());
85#endif
86 }
87
peahb46083e2016-05-03 07:01:18 -070088 // Reinitializes the data dumping such that new versions
89 // of all files being dumped to are created.
90 void InitiateNewSetOfRecordings() {
peahf28a3892016-09-01 08:58:21 -070091#if WEBRTC_APM_DEBUG_DUMP == 1
peahb46083e2016-05-03 07:01:18 -070092 ++recording_set_index_;
93#endif
94 }
95
96 // Methods for performing dumping of data of various types into
97 // various formats.
Per Åhgrenc2ae4c82021-01-20 15:42:13 +010098 void DumpRaw(const char* name, double v, int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -080099#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100100 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
101 return;
102
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200103 if (recording_activated_) {
104 FILE* file = GetRawFile(name);
105 fwrite(&v, sizeof(v), 1, file);
106 }
peah69221db2017-01-27 03:28:19 -0800107#endif
108 }
109
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100110 void DumpRaw(const char* name,
111 size_t v_length,
112 const double* v,
113 int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800114#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100115 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
116 return;
117
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200118 if (recording_activated_) {
119 FILE* file = GetRawFile(name);
120 fwrite(v, sizeof(v[0]), v_length, file);
121 }
peah69221db2017-01-27 03:28:19 -0800122#endif
123 }
124
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100125 void DumpRaw(const char* name,
126 rtc::ArrayView<const double> v,
127 int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800128#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100129 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
130 return;
131
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200132 if (recording_activated_) {
133 DumpRaw(name, v.size(), v.data());
134 }
peah69221db2017-01-27 03:28:19 -0800135#endif
136 }
137
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100138 void DumpRaw(const char* name, float v, int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800139#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100140 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
141 return;
142
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200143 if (recording_activated_) {
144 FILE* file = GetRawFile(name);
145 fwrite(&v, sizeof(v), 1, file);
146 }
peah69221db2017-01-27 03:28:19 -0800147#endif
148 }
149
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100150 void DumpRaw(const char* name,
151 size_t v_length,
152 const float* v,
153 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700154#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100155 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
156 return;
157
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200158 if (recording_activated_) {
159 FILE* file = GetRawFile(name);
160 fwrite(v, sizeof(v[0]), v_length, file);
161 }
peahb46083e2016-05-03 07:01:18 -0700162#endif
163 }
164
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100165 void DumpRaw(const char* name,
166 rtc::ArrayView<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 DumpRaw(name, v.size(), v.data());
174 }
peahb46083e2016-05-03 07:01:18 -0700175#endif
176 }
177
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100178 void DumpRaw(const char* name, bool v, int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800179#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100180 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
181 return;
182
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200183 if (recording_activated_) {
184 DumpRaw(name, static_cast<int16_t>(v));
185 }
peah69221db2017-01-27 03:28:19 -0800186#endif
187 }
188
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100189 void DumpRaw(const char* name,
190 size_t v_length,
191 const bool* v,
192 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700193#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 FILE* file = GetRawFile(name);
199 for (size_t k = 0; k < v_length; ++k) {
200 int16_t value = static_cast<int16_t>(v[k]);
201 fwrite(&value, sizeof(value), 1, file);
202 }
peahca4cac72016-06-29 15:26:12 -0700203 }
204#endif
205 }
206
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100207 void DumpRaw(const char* name,
208 rtc::ArrayView<const bool> v,
209 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700210#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100211 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
212 return;
213
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200214 if (recording_activated_) {
215 DumpRaw(name, v.size(), v.data());
216 }
peahca4cac72016-06-29 15:26:12 -0700217#endif
218 }
219
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100220 void DumpRaw(const char* name, int16_t v, int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800221#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100222 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
223 return;
224
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200225 if (recording_activated_) {
226 FILE* file = GetRawFile(name);
227 fwrite(&v, sizeof(v), 1, file);
228 }
peah69221db2017-01-27 03:28:19 -0800229#endif
230 }
231
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100232 void DumpRaw(const char* name,
233 size_t v_length,
234 const int16_t* v,
235 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700236#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100237 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
238 return;
239
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200240 if (recording_activated_) {
241 FILE* file = GetRawFile(name);
242 fwrite(v, sizeof(v[0]), v_length, file);
243 }
peah3f08dc62016-05-05 03:03:55 -0700244#endif
245 }
246
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100247 void DumpRaw(const char* name,
248 rtc::ArrayView<const int16_t> v,
249 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700250#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100251 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
252 return;
253
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200254 if (recording_activated_) {
255 DumpRaw(name, v.size(), v.data());
256 }
peah3f08dc62016-05-05 03:03:55 -0700257#endif
258 }
259
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100260 void DumpRaw(const char* name, int32_t v, int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800261#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100262 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
263 return;
264
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200265 if (recording_activated_) {
266 FILE* file = GetRawFile(name);
267 fwrite(&v, sizeof(v), 1, file);
268 }
peah69221db2017-01-27 03:28:19 -0800269#endif
270 }
271
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100272 void DumpRaw(const char* name,
273 size_t v_length,
274 const int32_t* v,
275 int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800276#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100277 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
278 return;
279
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200280 if (recording_activated_) {
281 FILE* file = GetRawFile(name);
282 fwrite(v, sizeof(v[0]), v_length, file);
283 }
peah69221db2017-01-27 03:28:19 -0800284#endif
285 }
286
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100287 void DumpRaw(const char* name, size_t v, int dump_set = kDefaultDumpSet) {
peah69221db2017-01-27 03:28:19 -0800288#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100289 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
290 return;
291
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200292 if (recording_activated_) {
293 FILE* file = GetRawFile(name);
294 fwrite(&v, sizeof(v), 1, file);
295 }
peah69221db2017-01-27 03:28:19 -0800296#endif
297 }
298
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100299 void DumpRaw(const char* name,
300 size_t v_length,
301 const size_t* v,
302 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700303#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100304 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
305 return;
306
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200307 if (recording_activated_) {
308 FILE* file = GetRawFile(name);
309 fwrite(v, sizeof(v[0]), v_length, file);
310 }
peah3f08dc62016-05-05 03:03:55 -0700311#endif
312 }
313
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100314 void DumpRaw(const char* name,
315 rtc::ArrayView<const int32_t> v,
316 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700317#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100318 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
319 return;
320
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200321 if (recording_activated_) {
322 DumpRaw(name, v.size(), v.data());
323 }
peah3f08dc62016-05-05 03:03:55 -0700324#endif
325 }
326
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100327 void DumpRaw(const char* name,
328 rtc::ArrayView<const size_t> v,
329 int dump_set = kDefaultDumpSet) {
Jesús de Vicente Peña44974e12018-11-20 12:54:23 +0100330#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100331 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
332 return;
333
Jesús de Vicente Peña44974e12018-11-20 12:54:23 +0100334 DumpRaw(name, v.size(), v.data());
335#endif
336 }
337
peahb46083e2016-05-03 07:01:18 -0700338 void DumpWav(const char* name,
peah69221db2017-01-27 03:28:19 -0800339 size_t v_length,
peahb46083e2016-05-03 07:01:18 -0700340 const float* v,
341 int sample_rate_hz,
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100342 int num_channels,
343 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700344#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100345 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
346 return;
347
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200348 if (recording_activated_) {
Per Åhgren5dca3f12020-01-28 09:08:11 +0100349 WavWriter* file = GetWavFile(name, sample_rate_hz, num_channels,
350 WavFile::SampleFormat::kFloat);
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200351 file->WriteSamples(v, v_length);
352 }
peahb46083e2016-05-03 07:01:18 -0700353#endif
354 }
355
peahca4cac72016-06-29 15:26:12 -0700356 void DumpWav(const char* name,
357 rtc::ArrayView<const float> v,
358 int sample_rate_hz,
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100359 int num_channels,
360 int dump_set = kDefaultDumpSet) {
peahf28a3892016-09-01 08:58:21 -0700361#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100362 if (dump_set_to_use_ && *dump_set_to_use_ != dump_set)
363 return;
364
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200365 if (recording_activated_) {
366 DumpWav(name, v.size(), v.data(), sample_rate_hz, num_channels);
367 }
peahca4cac72016-06-29 15:26:12 -0700368#endif
369 }
370
peahb46083e2016-05-03 07:01:18 -0700371 private:
peahf28a3892016-09-01 08:58:21 -0700372#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200373 static bool recording_activated_;
Per Åhgrenc2ae4c82021-01-20 15:42:13 +0100374 static absl::optional<int> dump_set_to_use_;
Alessio Bazzica4bc60452018-11-20 12:44:15 +0100375 static constexpr size_t kOutputDirMaxLength = 1024;
376 static char output_dir_[kOutputDirMaxLength];
peahb46083e2016-05-03 07:01:18 -0700377 const int instance_index_;
378 int recording_set_index_ = 0;
379 std::unordered_map<std::string, std::unique_ptr<FILE, RawFileCloseFunctor>>
380 raw_files_;
381 std::unordered_map<std::string, std::unique_ptr<WavWriter>> wav_files_;
382
383 FILE* GetRawFile(const char* name);
Per Åhgren5dca3f12020-01-28 09:08:11 +0100384 WavWriter* GetWavFile(const char* name,
385 int sample_rate_hz,
386 int num_channels,
387 WavFile::SampleFormat format);
peahb46083e2016-05-03 07:01:18 -0700388#endif
peahb46083e2016-05-03 07:01:18 -0700389};
390
391} // namespace webrtc
392
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200393#endif // MODULES_AUDIO_PROCESSING_LOGGING_APM_DATA_DUMPER_H_