• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
11 #ifndef MODULES_AUDIO_PROCESSING_LOGGING_APM_DATA_DUMPER_H_
12 #define MODULES_AUDIO_PROCESSING_LOGGING_APM_DATA_DUMPER_H_
13 
14 #include <stdint.h>
15 #include <stdio.h>
16 #include <string.h>
17 
18 #include <string>
19 #if WEBRTC_APM_DEBUG_DUMP == 1
20 #include <memory>
21 #include <unordered_map>
22 #endif
23 
24 #include "api/array_view.h"
25 #if WEBRTC_APM_DEBUG_DUMP == 1
26 #include "common_audio/wav_file.h"
27 #include "rtc_base/checks.h"
28 #endif
29 #include "rtc_base/constructor_magic.h"
30 
31 // Check to verify that the define is properly set.
32 #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"
35 #endif
36 
37 namespace webrtc {
38 
39 #if WEBRTC_APM_DEBUG_DUMP == 1
40 // Functor used to use as a custom deleter in the map of file pointers to raw
41 // files.
42 struct RawFileCloseFunctor {
operatorRawFileCloseFunctor43   void operator()(FILE* f) const { fclose(f); }
44 };
45 #endif
46 
47 // Class that handles dumping of variables into files.
48 class ApmDataDumper {
49  public:
50   // 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();
56 
57   // Activates or deactivate the dumping functionality.
SetActivated(bool activated)58   static void SetActivated(bool activated) {
59 #if WEBRTC_APM_DEBUG_DUMP == 1
60     recording_activated_ = activated;
61 #endif
62   }
63 
64   // Set an optional output directory.
SetOutputDirectory(const std::string & output_dir)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 
72   // Reinitializes the data dumping such that new versions
73   // of all files being dumped to are created.
InitiateNewSetOfRecordings()74   void InitiateNewSetOfRecordings() {
75 #if WEBRTC_APM_DEBUG_DUMP == 1
76     ++recording_set_index_;
77 #endif
78   }
79 
80   // Methods for performing dumping of data of various types into
81   // various formats.
DumpRaw(const char * name,double v)82   void DumpRaw(const char* name, double v) {
83 #if WEBRTC_APM_DEBUG_DUMP == 1
84     if (recording_activated_) {
85       FILE* file = GetRawFile(name);
86       fwrite(&v, sizeof(v), 1, file);
87     }
88 #endif
89   }
90 
DumpRaw(const char * name,size_t v_length,const double * v)91   void DumpRaw(const char* name, size_t v_length, const double* v) {
92 #if WEBRTC_APM_DEBUG_DUMP == 1
93     if (recording_activated_) {
94       FILE* file = GetRawFile(name);
95       fwrite(v, sizeof(v[0]), v_length, file);
96     }
97 #endif
98   }
99 
DumpRaw(const char * name,rtc::ArrayView<const double> v)100   void DumpRaw(const char* name, rtc::ArrayView<const double> v) {
101 #if WEBRTC_APM_DEBUG_DUMP == 1
102     if (recording_activated_) {
103       DumpRaw(name, v.size(), v.data());
104     }
105 #endif
106   }
107 
DumpRaw(const char * name,float v)108   void DumpRaw(const char* name, float v) {
109 #if WEBRTC_APM_DEBUG_DUMP == 1
110     if (recording_activated_) {
111       FILE* file = GetRawFile(name);
112       fwrite(&v, sizeof(v), 1, file);
113     }
114 #endif
115   }
116 
DumpRaw(const char * name,size_t v_length,const float * v)117   void DumpRaw(const char* name, size_t v_length, const float* v) {
118 #if WEBRTC_APM_DEBUG_DUMP == 1
119     if (recording_activated_) {
120       FILE* file = GetRawFile(name);
121       fwrite(v, sizeof(v[0]), v_length, file);
122     }
123 #endif
124   }
125 
DumpRaw(const char * name,rtc::ArrayView<const float> v)126   void DumpRaw(const char* name, rtc::ArrayView<const float> v) {
127 #if WEBRTC_APM_DEBUG_DUMP == 1
128     if (recording_activated_) {
129       DumpRaw(name, v.size(), v.data());
130     }
131 #endif
132   }
133 
DumpRaw(const char * name,bool v)134   void DumpRaw(const char* name, bool v) {
135 #if WEBRTC_APM_DEBUG_DUMP == 1
136     if (recording_activated_) {
137       DumpRaw(name, static_cast<int16_t>(v));
138     }
139 #endif
140   }
141 
DumpRaw(const char * name,size_t v_length,const bool * v)142   void DumpRaw(const char* name, size_t v_length, const bool* v) {
143 #if WEBRTC_APM_DEBUG_DUMP == 1
144     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       }
150     }
151 #endif
152   }
153 
DumpRaw(const char * name,rtc::ArrayView<const bool> v)154   void DumpRaw(const char* name, rtc::ArrayView<const bool> v) {
155 #if WEBRTC_APM_DEBUG_DUMP == 1
156     if (recording_activated_) {
157       DumpRaw(name, v.size(), v.data());
158     }
159 #endif
160   }
161 
DumpRaw(const char * name,int16_t v)162   void DumpRaw(const char* name, int16_t v) {
163 #if WEBRTC_APM_DEBUG_DUMP == 1
164     if (recording_activated_) {
165       FILE* file = GetRawFile(name);
166       fwrite(&v, sizeof(v), 1, file);
167     }
168 #endif
169   }
170 
DumpRaw(const char * name,size_t v_length,const int16_t * v)171   void DumpRaw(const char* name, size_t v_length, const int16_t* v) {
172 #if WEBRTC_APM_DEBUG_DUMP == 1
173     if (recording_activated_) {
174       FILE* file = GetRawFile(name);
175       fwrite(v, sizeof(v[0]), v_length, file);
176     }
177 #endif
178   }
179 
DumpRaw(const char * name,rtc::ArrayView<const int16_t> v)180   void DumpRaw(const char* name, rtc::ArrayView<const int16_t> v) {
181 #if WEBRTC_APM_DEBUG_DUMP == 1
182     if (recording_activated_) {
183       DumpRaw(name, v.size(), v.data());
184     }
185 #endif
186   }
187 
DumpRaw(const char * name,int32_t v)188   void DumpRaw(const char* name, int32_t v) {
189 #if WEBRTC_APM_DEBUG_DUMP == 1
190     if (recording_activated_) {
191       FILE* file = GetRawFile(name);
192       fwrite(&v, sizeof(v), 1, file);
193     }
194 #endif
195   }
196 
DumpRaw(const char * name,size_t v_length,const int32_t * v)197   void DumpRaw(const char* name, size_t v_length, const int32_t* v) {
198 #if WEBRTC_APM_DEBUG_DUMP == 1
199     if (recording_activated_) {
200       FILE* file = GetRawFile(name);
201       fwrite(v, sizeof(v[0]), v_length, file);
202     }
203 #endif
204   }
205 
DumpRaw(const char * name,size_t v)206   void DumpRaw(const char* name, size_t v) {
207 #if WEBRTC_APM_DEBUG_DUMP == 1
208     if (recording_activated_) {
209       FILE* file = GetRawFile(name);
210       fwrite(&v, sizeof(v), 1, file);
211     }
212 #endif
213   }
214 
DumpRaw(const char * name,size_t v_length,const size_t * v)215   void DumpRaw(const char* name, size_t v_length, const size_t* v) {
216 #if WEBRTC_APM_DEBUG_DUMP == 1
217     if (recording_activated_) {
218       FILE* file = GetRawFile(name);
219       fwrite(v, sizeof(v[0]), v_length, file);
220     }
221 #endif
222   }
223 
DumpRaw(const char * name,rtc::ArrayView<const int32_t> v)224   void DumpRaw(const char* name, rtc::ArrayView<const int32_t> v) {
225 #if WEBRTC_APM_DEBUG_DUMP == 1
226     if (recording_activated_) {
227       DumpRaw(name, v.size(), v.data());
228     }
229 #endif
230   }
231 
DumpRaw(const char * name,rtc::ArrayView<const size_t> v)232   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 
DumpWav(const char * name,size_t v_length,const float * v,int sample_rate_hz,int num_channels)238   void DumpWav(const char* name,
239                size_t v_length,
240                const float* v,
241                int sample_rate_hz,
242                int num_channels) {
243 #if WEBRTC_APM_DEBUG_DUMP == 1
244     if (recording_activated_) {
245       WavWriter* file = GetWavFile(name, sample_rate_hz, num_channels,
246                                    WavFile::SampleFormat::kFloat);
247       file->WriteSamples(v, v_length);
248     }
249 #endif
250   }
251 
DumpWav(const char * name,rtc::ArrayView<const float> v,int sample_rate_hz,int num_channels)252   void DumpWav(const char* name,
253                rtc::ArrayView<const float> v,
254                int sample_rate_hz,
255                int num_channels) {
256 #if WEBRTC_APM_DEBUG_DUMP == 1
257     if (recording_activated_) {
258       DumpWav(name, v.size(), v.data(), sample_rate_hz, num_channels);
259     }
260 #endif
261   }
262 
263  private:
264 #if WEBRTC_APM_DEBUG_DUMP == 1
265   static bool recording_activated_;
266   static constexpr size_t kOutputDirMaxLength = 1024;
267   static char output_dir_[kOutputDirMaxLength];
268   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);
275   WavWriter* GetWavFile(const char* name,
276                         int sample_rate_hz,
277                         int num_channels,
278                         WavFile::SampleFormat format);
279 #endif
280   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ApmDataDumper);
281 };
282 
283 }  // namespace webrtc
284 
285 #endif  // MODULES_AUDIO_PROCESSING_LOGGING_APM_DATA_DUMPER_H_
286