blob: 17a5c877167c623c64e4b4a25ad298655646da2f [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
Steve Anton10542f22019-01-11 09:11:00 -080029#include "rtc_base/constructor_magic.h"
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
55 ~ApmDataDumper();
peahb46083e2016-05-03 07:01:18 -070056
Per Åhgren7a95e0f2018-10-25 09:56:49 +020057 // Activates or deactivate the dumping functionality.
58 static void SetActivated(bool activated) {
59#if WEBRTC_APM_DEBUG_DUMP == 1
60 recording_activated_ = activated;
61#endif
62 }
63
Alessio Bazzica4bc60452018-11-20 12:44:15 +010064 // Set an optional output directory.
65 static void SetOutputDirectory(const std::string& output_dir) {
66#if WEBRTC_APM_DEBUG_DUMP == 1
67 RTC_CHECK_LT(output_dir.size(), kOutputDirMaxLength);
68 strncpy(output_dir_, output_dir.c_str(), output_dir.size());
69#endif
70 }
71
peahb46083e2016-05-03 07:01:18 -070072 // Reinitializes the data dumping such that new versions
73 // of all files being dumped to are created.
74 void InitiateNewSetOfRecordings() {
peahf28a3892016-09-01 08:58:21 -070075#if WEBRTC_APM_DEBUG_DUMP == 1
peahb46083e2016-05-03 07:01:18 -070076 ++recording_set_index_;
77#endif
78 }
79
80 // Methods for performing dumping of data of various types into
81 // various formats.
peah69221db2017-01-27 03:28:19 -080082 void DumpRaw(const char* name, double v) {
83#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +020084 if (recording_activated_) {
85 FILE* file = GetRawFile(name);
86 fwrite(&v, sizeof(v), 1, file);
87 }
peah69221db2017-01-27 03:28:19 -080088#endif
89 }
90
91 void DumpRaw(const char* name, size_t v_length, const double* v) {
92#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +020093 if (recording_activated_) {
94 FILE* file = GetRawFile(name);
95 fwrite(v, sizeof(v[0]), v_length, file);
96 }
peah69221db2017-01-27 03:28:19 -080097#endif
98 }
99
100 void DumpRaw(const char* name, rtc::ArrayView<const double> v) {
101#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200102 if (recording_activated_) {
103 DumpRaw(name, v.size(), v.data());
104 }
peah69221db2017-01-27 03:28:19 -0800105#endif
106 }
107
108 void DumpRaw(const char* name, float v) {
109#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200110 if (recording_activated_) {
111 FILE* file = GetRawFile(name);
112 fwrite(&v, sizeof(v), 1, file);
113 }
peah69221db2017-01-27 03:28:19 -0800114#endif
115 }
116
117 void DumpRaw(const char* name, size_t v_length, const float* v) {
peahf28a3892016-09-01 08:58:21 -0700118#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200119 if (recording_activated_) {
120 FILE* file = GetRawFile(name);
121 fwrite(v, sizeof(v[0]), v_length, file);
122 }
peahb46083e2016-05-03 07:01:18 -0700123#endif
124 }
125
126 void DumpRaw(const char* name, rtc::ArrayView<const float> v) {
peahf28a3892016-09-01 08:58:21 -0700127#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200128 if (recording_activated_) {
129 DumpRaw(name, v.size(), v.data());
130 }
peahb46083e2016-05-03 07:01:18 -0700131#endif
132 }
133
peah69221db2017-01-27 03:28:19 -0800134 void DumpRaw(const char* name, bool v) {
135#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200136 if (recording_activated_) {
137 DumpRaw(name, static_cast<int16_t>(v));
138 }
peah69221db2017-01-27 03:28:19 -0800139#endif
140 }
141
142 void DumpRaw(const char* name, size_t v_length, const bool* v) {
peahf28a3892016-09-01 08:58:21 -0700143#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200144 if (recording_activated_) {
145 FILE* file = GetRawFile(name);
146 for (size_t k = 0; k < v_length; ++k) {
147 int16_t value = static_cast<int16_t>(v[k]);
148 fwrite(&value, sizeof(value), 1, file);
149 }
peahca4cac72016-06-29 15:26:12 -0700150 }
151#endif
152 }
153
154 void DumpRaw(const char* name, rtc::ArrayView<const bool> v) {
peahf28a3892016-09-01 08:58:21 -0700155#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200156 if (recording_activated_) {
157 DumpRaw(name, v.size(), v.data());
158 }
peahca4cac72016-06-29 15:26:12 -0700159#endif
160 }
161
peah69221db2017-01-27 03:28:19 -0800162 void DumpRaw(const char* name, int16_t v) {
163#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200164 if (recording_activated_) {
165 FILE* file = GetRawFile(name);
166 fwrite(&v, sizeof(v), 1, file);
167 }
peah69221db2017-01-27 03:28:19 -0800168#endif
169 }
170
171 void DumpRaw(const char* name, size_t v_length, const int16_t* v) {
peahf28a3892016-09-01 08:58:21 -0700172#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200173 if (recording_activated_) {
174 FILE* file = GetRawFile(name);
175 fwrite(v, sizeof(v[0]), v_length, file);
176 }
peah3f08dc62016-05-05 03:03:55 -0700177#endif
178 }
179
180 void DumpRaw(const char* name, rtc::ArrayView<const int16_t> v) {
peahf28a3892016-09-01 08:58:21 -0700181#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200182 if (recording_activated_) {
183 DumpRaw(name, v.size(), v.data());
184 }
peah3f08dc62016-05-05 03:03:55 -0700185#endif
186 }
187
peah69221db2017-01-27 03:28:19 -0800188 void DumpRaw(const char* name, int32_t v) {
189#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200190 if (recording_activated_) {
191 FILE* file = GetRawFile(name);
192 fwrite(&v, sizeof(v), 1, file);
193 }
peah69221db2017-01-27 03:28:19 -0800194#endif
195 }
196
197 void DumpRaw(const char* name, size_t v_length, const int32_t* v) {
198#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200199 if (recording_activated_) {
200 FILE* file = GetRawFile(name);
201 fwrite(v, sizeof(v[0]), v_length, file);
202 }
peah69221db2017-01-27 03:28:19 -0800203#endif
204 }
205
206 void DumpRaw(const char* name, size_t v) {
207#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200208 if (recording_activated_) {
209 FILE* file = GetRawFile(name);
210 fwrite(&v, sizeof(v), 1, file);
211 }
peah69221db2017-01-27 03:28:19 -0800212#endif
213 }
214
215 void DumpRaw(const char* name, size_t v_length, const size_t* v) {
peahf28a3892016-09-01 08:58:21 -0700216#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200217 if (recording_activated_) {
218 FILE* file = GetRawFile(name);
219 fwrite(v, sizeof(v[0]), v_length, file);
220 }
peah3f08dc62016-05-05 03:03:55 -0700221#endif
222 }
223
224 void DumpRaw(const char* name, rtc::ArrayView<const int32_t> v) {
peahf28a3892016-09-01 08:58:21 -0700225#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200226 if (recording_activated_) {
227 DumpRaw(name, v.size(), v.data());
228 }
peah3f08dc62016-05-05 03:03:55 -0700229#endif
230 }
231
Jesús de Vicente Peña44974e12018-11-20 12:54:23 +0100232 void DumpRaw(const char* name, rtc::ArrayView<const size_t> v) {
233#if WEBRTC_APM_DEBUG_DUMP == 1
234 DumpRaw(name, v.size(), v.data());
235#endif
236 }
237
peahb46083e2016-05-03 07:01:18 -0700238 void DumpWav(const char* name,
peah69221db2017-01-27 03:28:19 -0800239 size_t v_length,
peahb46083e2016-05-03 07:01:18 -0700240 const float* v,
241 int sample_rate_hz,
242 int num_channels) {
peahf28a3892016-09-01 08:58:21 -0700243#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200244 if (recording_activated_) {
Per Åhgren5dca3f12020-01-28 09:08:11 +0100245 WavWriter* file = GetWavFile(name, sample_rate_hz, num_channels,
246 WavFile::SampleFormat::kFloat);
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200247 file->WriteSamples(v, v_length);
248 }
peahb46083e2016-05-03 07:01:18 -0700249#endif
250 }
251
peahca4cac72016-06-29 15:26:12 -0700252 void DumpWav(const char* name,
253 rtc::ArrayView<const float> v,
254 int sample_rate_hz,
255 int num_channels) {
peahf28a3892016-09-01 08:58:21 -0700256#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200257 if (recording_activated_) {
258 DumpWav(name, v.size(), v.data(), sample_rate_hz, num_channels);
259 }
peahca4cac72016-06-29 15:26:12 -0700260#endif
261 }
262
peahb46083e2016-05-03 07:01:18 -0700263 private:
peahf28a3892016-09-01 08:58:21 -0700264#if WEBRTC_APM_DEBUG_DUMP == 1
Per Åhgren7a95e0f2018-10-25 09:56:49 +0200265 static bool recording_activated_;
Alessio Bazzica4bc60452018-11-20 12:44:15 +0100266 static constexpr size_t kOutputDirMaxLength = 1024;
267 static char output_dir_[kOutputDirMaxLength];
peahb46083e2016-05-03 07:01:18 -0700268 const int instance_index_;
269 int recording_set_index_ = 0;
270 std::unordered_map<std::string, std::unique_ptr<FILE, RawFileCloseFunctor>>
271 raw_files_;
272 std::unordered_map<std::string, std::unique_ptr<WavWriter>> wav_files_;
273
274 FILE* GetRawFile(const char* name);
Per Åhgren5dca3f12020-01-28 09:08:11 +0100275 WavWriter* GetWavFile(const char* name,
276 int sample_rate_hz,
277 int num_channels,
278 WavFile::SampleFormat format);
peahb46083e2016-05-03 07:01:18 -0700279#endif
280 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ApmDataDumper);
281};
282
283} // namespace webrtc
284
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200285#endif // MODULES_AUDIO_PROCESSING_LOGGING_APM_DATA_DUMPER_H_