blob: 1824fdd2a9fc2ef354824ebf6af3b8b4fe290ea3 [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "api/array_view.h"
Per Åhgrenf0c449e2018-10-23 20:17:18 +020025#if WEBRTC_APM_DEBUG_DUMP == 1
26#include "common_audio/wav_file.h"
Alessio Bazzica4bc60452018-11-20 12:44:15 +010027#include "rtc_base/checks.h"
Per Åhgrenf0c449e2018-10-23 20:17:18 +020028#endif
peahb46083e2016-05-03 07:01:18 -070029
30// Check to verify that the define is properly set.
peahf28a3892016-09-01 08:58:21 -070031#if !defined(WEBRTC_APM_DEBUG_DUMP) || \
32 (WEBRTC_APM_DEBUG_DUMP != 0 && WEBRTC_APM_DEBUG_DUMP != 1)
33#error "Set WEBRTC_APM_DEBUG_DUMP to either 0 or 1"
peahb46083e2016-05-03 07:01:18 -070034#endif
35
36namespace webrtc {
37
peahf28a3892016-09-01 08:58:21 -070038#if WEBRTC_APM_DEBUG_DUMP == 1
peahb46083e2016-05-03 07:01:18 -070039// Functor used to use as a custom deleter in the map of file pointers to raw
40// files.
41struct RawFileCloseFunctor {
42 void operator()(FILE* f) const { fclose(f); }
43};
44#endif
45
46// Class that handles dumping of variables into files.
47class ApmDataDumper {
48 public:
peahf8f754a2016-08-30 10:31:45 -070049 // Constructor that takes an instance index that may
50 // be used to distinguish data dumped from different
51 // instances of the code.
52 explicit ApmDataDumper(int instance_index);
53
Niels Möllerde953292020-09-29 09:46:21 +020054 ApmDataDumper() = delete;
55 ApmDataDumper(const ApmDataDumper&) = delete;
56 ApmDataDumper& operator=(const ApmDataDumper&) = delete;
57
peahf8f754a2016-08-30 10:31:45 -070058 ~ApmDataDumper();
peahb46083e2016-05-03 07:01:18 -070059
Per Åhgren7a95e0f2018-10-25 09:56:49 +020060 // Activates or deactivate the dumping functionality.
61 static void SetActivated(bool activated) {
62#if WEBRTC_APM_DEBUG_DUMP == 1
63 recording_activated_ = activated;
64#endif
65 }
66
Alessio Bazzica4bc60452018-11-20 12:44:15 +010067 // Set an optional output directory.
68 static void SetOutputDirectory(const std::string& output_dir) {
69#if WEBRTC_APM_DEBUG_DUMP == 1
70 RTC_CHECK_LT(output_dir.size(), kOutputDirMaxLength);
71 strncpy(output_dir_, output_dir.c_str(), output_dir.size());
72#endif
73 }
74
peahb46083e2016-05-03 07:01:18 -070075 // Reinitializes the data dumping such that new versions
76 // of all files being dumped to are created.
77 void InitiateNewSetOfRecordings() {
peahf28a3892016-09-01 08:58:21 -070078#if WEBRTC_APM_DEBUG_DUMP == 1
peahb46083e2016-05-03 07:01:18 -070079 ++recording_set_index_;
80#endif
81 }
82
83 // Methods for performing dumping of data of various types into
84 // various formats.
peah69221db2017-01-27 03:28:19 -080085 void DumpRaw(const char* name, double v) {
86#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +020087 if (recording_activated_) {
88 FILE* file = GetRawFile(name);
89 fwrite(&v, sizeof(v), 1, file);
90 }
peah69221db2017-01-27 03:28:19 -080091#endif
92 }
93
94 void DumpRaw(const char* name, size_t v_length, const double* v) {
95#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +020096 if (recording_activated_) {
97 FILE* file = GetRawFile(name);
98 fwrite(v, sizeof(v[0]), v_length, file);
99 }
peah69221db2017-01-27 03:28:19 -0800100#endif
101 }
102
103 void DumpRaw(const char* name, rtc::ArrayView<const double> v) {
104#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200105 if (recording_activated_) {
106 DumpRaw(name, v.size(), v.data());
107 }
peah69221db2017-01-27 03:28:19 -0800108#endif
109 }
110
111 void DumpRaw(const char* name, float v) {
112#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200113 if (recording_activated_) {
114 FILE* file = GetRawFile(name);
115 fwrite(&v, sizeof(v), 1, file);
116 }
peah69221db2017-01-27 03:28:19 -0800117#endif
118 }
119
120 void DumpRaw(const char* name, size_t v_length, const float* v) {
peahf28a3892016-09-01 08:58:21 -0700121#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200122 if (recording_activated_) {
123 FILE* file = GetRawFile(name);
124 fwrite(v, sizeof(v[0]), v_length, file);
125 }
peahb46083e2016-05-03 07:01:18 -0700126#endif
127 }
128
129 void DumpRaw(const char* name, rtc::ArrayView<const float> v) {
peahf28a3892016-09-01 08:58:21 -0700130#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200131 if (recording_activated_) {
132 DumpRaw(name, v.size(), v.data());
133 }
peahb46083e2016-05-03 07:01:18 -0700134#endif
135 }
136
peah69221db2017-01-27 03:28:19 -0800137 void DumpRaw(const char* name, bool v) {
138#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200139 if (recording_activated_) {
140 DumpRaw(name, static_cast<int16_t>(v));
141 }
peah69221db2017-01-27 03:28:19 -0800142#endif
143 }
144
145 void DumpRaw(const char* name, size_t v_length, const bool* v) {
peahf28a3892016-09-01 08:58:21 -0700146#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200147 if (recording_activated_) {
148 FILE* file = GetRawFile(name);
149 for (size_t k = 0; k < v_length; ++k) {
150 int16_t value = static_cast<int16_t>(v[k]);
151 fwrite(&value, sizeof(value), 1, file);
152 }
peahca4cac72016-06-29 15:26:12 -0700153 }
154#endif
155 }
156
157 void DumpRaw(const char* name, rtc::ArrayView<const bool> v) {
peahf28a3892016-09-01 08:58:21 -0700158#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200159 if (recording_activated_) {
160 DumpRaw(name, v.size(), v.data());
161 }
peahca4cac72016-06-29 15:26:12 -0700162#endif
163 }
164
peah69221db2017-01-27 03:28:19 -0800165 void DumpRaw(const char* name, int16_t v) {
166#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200167 if (recording_activated_) {
168 FILE* file = GetRawFile(name);
169 fwrite(&v, sizeof(v), 1, file);
170 }
peah69221db2017-01-27 03:28:19 -0800171#endif
172 }
173
174 void DumpRaw(const char* name, size_t v_length, const int16_t* v) {
peahf28a3892016-09-01 08:58:21 -0700175#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200176 if (recording_activated_) {
177 FILE* file = GetRawFile(name);
178 fwrite(v, sizeof(v[0]), v_length, file);
179 }
peah3f08dc62016-05-05 03:03:55 -0700180#endif
181 }
182
183 void DumpRaw(const char* name, rtc::ArrayView<const int16_t> v) {
peahf28a3892016-09-01 08:58:21 -0700184#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200185 if (recording_activated_) {
186 DumpRaw(name, v.size(), v.data());
187 }
peah3f08dc62016-05-05 03:03:55 -0700188#endif
189 }
190
peah69221db2017-01-27 03:28:19 -0800191 void DumpRaw(const char* name, int32_t v) {
192#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200193 if (recording_activated_) {
194 FILE* file = GetRawFile(name);
195 fwrite(&v, sizeof(v), 1, file);
196 }
peah69221db2017-01-27 03:28:19 -0800197#endif
198 }
199
200 void DumpRaw(const char* name, size_t v_length, const int32_t* v) {
201#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200202 if (recording_activated_) {
203 FILE* file = GetRawFile(name);
204 fwrite(v, sizeof(v[0]), v_length, file);
205 }
peah69221db2017-01-27 03:28:19 -0800206#endif
207 }
208
209 void DumpRaw(const char* name, size_t v) {
210#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200211 if (recording_activated_) {
212 FILE* file = GetRawFile(name);
213 fwrite(&v, sizeof(v), 1, file);
214 }
peah69221db2017-01-27 03:28:19 -0800215#endif
216 }
217
218 void DumpRaw(const char* name, size_t v_length, const size_t* v) {
peahf28a3892016-09-01 08:58:21 -0700219#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200220 if (recording_activated_) {
221 FILE* file = GetRawFile(name);
222 fwrite(v, sizeof(v[0]), v_length, file);
223 }
peah3f08dc62016-05-05 03:03:55 -0700224#endif
225 }
226
227 void DumpRaw(const char* name, rtc::ArrayView<const int32_t> v) {
peahf28a3892016-09-01 08:58:21 -0700228#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200229 if (recording_activated_) {
230 DumpRaw(name, v.size(), v.data());
231 }
peah3f08dc62016-05-05 03:03:55 -0700232#endif
233 }
234
Jesús de Vicente Peña44974e12018-11-20 12:54:23 +0100235 void DumpRaw(const char* name, rtc::ArrayView<const size_t> v) {
236#if WEBRTC_APM_DEBUG_DUMP == 1
237 DumpRaw(name, v.size(), v.data());
238#endif
239 }
240
peahb46083e2016-05-03 07:01:18 -0700241 void DumpWav(const char* name,
peah69221db2017-01-27 03:28:19 -0800242 size_t v_length,
peahb46083e2016-05-03 07:01:18 -0700243 const float* v,
244 int sample_rate_hz,
245 int num_channels) {
peahf28a3892016-09-01 08:58:21 -0700246#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200247 if (recording_activated_) {
Per Åhgren5dca3f12020-01-28 09:08:11 +0100248 WavWriter* file = GetWavFile(name, sample_rate_hz, num_channels,
249 WavFile::SampleFormat::kFloat);
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200250 file->WriteSamples(v, v_length);
251 }
peahb46083e2016-05-03 07:01:18 -0700252#endif
253 }
254
peahca4cac72016-06-29 15:26:12 -0700255 void DumpWav(const char* name,
256 rtc::ArrayView<const float> v,
257 int sample_rate_hz,
258 int num_channels) {
peahf28a3892016-09-01 08:58:21 -0700259#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200260 if (recording_activated_) {
261 DumpWav(name, v.size(), v.data(), sample_rate_hz, num_channels);
262 }
peahca4cac72016-06-29 15:26:12 -0700263#endif
264 }
265
peahb46083e2016-05-03 07:01:18 -0700266 private:
peahf28a3892016-09-01 08:58:21 -0700267#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200268 static bool recording_activated_;
Alessio Bazzica4bc60452018-11-20 12:44:15 +0100269 static constexpr size_t kOutputDirMaxLength = 1024;
270 static char output_dir_[kOutputDirMaxLength];
peahb46083e2016-05-03 07:01:18 -0700271 const int instance_index_;
272 int recording_set_index_ = 0;
273 std::unordered_map<std::string, std::unique_ptr<FILE, RawFileCloseFunctor>>
274 raw_files_;
275 std::unordered_map<std::string, std::unique_ptr<WavWriter>> wav_files_;
276
277 FILE* GetRawFile(const char* name);
Per Åhgren5dca3f12020-01-28 09:08:11 +0100278 WavWriter* GetWavFile(const char* name,
279 int sample_rate_hz,
280 int num_channels,
281 WavFile::SampleFormat format);
peahb46083e2016-05-03 07:01:18 -0700282#endif
peahb46083e2016-05-03 07:01:18 -0700283};
284
285} // namespace webrtc
286
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200287#endif // MODULES_AUDIO_PROCESSING_LOGGING_APM_DATA_DUMPER_H_