xref: /aosp_15_r20/external/webrtc/rtc_tools/unpack_aecdump/unpack.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker // Commandline tool to unpack audioproc debug files.
12*d9f75844SAndroid Build Coastguard Worker //
13*d9f75844SAndroid Build Coastguard Worker // The debug files are dumped as protobuf blobs. For analysis, it's necessary
14*d9f75844SAndroid Build Coastguard Worker // to unpack the file into its component parts: audio and other data.
15*d9f75844SAndroid Build Coastguard Worker 
16*d9f75844SAndroid Build Coastguard Worker #include <inttypes.h>
17*d9f75844SAndroid Build Coastguard Worker #include <stdint.h>
18*d9f75844SAndroid Build Coastguard Worker #include <stdio.h>
19*d9f75844SAndroid Build Coastguard Worker #include <stdlib.h>
20*d9f75844SAndroid Build Coastguard Worker 
21*d9f75844SAndroid Build Coastguard Worker #include <memory>
22*d9f75844SAndroid Build Coastguard Worker #include <string>
23*d9f75844SAndroid Build Coastguard Worker #include <vector>
24*d9f75844SAndroid Build Coastguard Worker 
25*d9f75844SAndroid Build Coastguard Worker #include "absl/flags/flag.h"
26*d9f75844SAndroid Build Coastguard Worker #include "absl/flags/parse.h"
27*d9f75844SAndroid Build Coastguard Worker #include "api/function_view.h"
28*d9f75844SAndroid Build Coastguard Worker #include "common_audio/include/audio_util.h"
29*d9f75844SAndroid Build Coastguard Worker #include "common_audio/wav_file.h"
30*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_processing/test/protobuf_utils.h"
31*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
32*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/ignore_wundef.h"
33*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/strings/string_builder.h"
34*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/system/arch.h"
35*d9f75844SAndroid Build Coastguard Worker 
36*d9f75844SAndroid Build Coastguard Worker RTC_PUSH_IGNORING_WUNDEF()
37*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_processing/debug.pb.h"
38*d9f75844SAndroid Build Coastguard Worker RTC_POP_IGNORING_WUNDEF()
39*d9f75844SAndroid Build Coastguard Worker 
40*d9f75844SAndroid Build Coastguard Worker ABSL_FLAG(std::string,
41*d9f75844SAndroid Build Coastguard Worker           input_file,
42*d9f75844SAndroid Build Coastguard Worker           "input",
43*d9f75844SAndroid Build Coastguard Worker           "The name of the input stream file.");
44*d9f75844SAndroid Build Coastguard Worker ABSL_FLAG(std::string,
45*d9f75844SAndroid Build Coastguard Worker           output_file,
46*d9f75844SAndroid Build Coastguard Worker           "ref_out",
47*d9f75844SAndroid Build Coastguard Worker           "The name of the reference output stream file.");
48*d9f75844SAndroid Build Coastguard Worker ABSL_FLAG(std::string,
49*d9f75844SAndroid Build Coastguard Worker           reverse_file,
50*d9f75844SAndroid Build Coastguard Worker           "reverse",
51*d9f75844SAndroid Build Coastguard Worker           "The name of the reverse input stream file.");
52*d9f75844SAndroid Build Coastguard Worker ABSL_FLAG(std::string,
53*d9f75844SAndroid Build Coastguard Worker           delay_file,
54*d9f75844SAndroid Build Coastguard Worker           "delay.int32",
55*d9f75844SAndroid Build Coastguard Worker           "The name of the delay file.");
56*d9f75844SAndroid Build Coastguard Worker ABSL_FLAG(std::string,
57*d9f75844SAndroid Build Coastguard Worker           drift_file,
58*d9f75844SAndroid Build Coastguard Worker           "drift.int32",
59*d9f75844SAndroid Build Coastguard Worker           "The name of the drift file.");
60*d9f75844SAndroid Build Coastguard Worker ABSL_FLAG(std::string,
61*d9f75844SAndroid Build Coastguard Worker           level_file,
62*d9f75844SAndroid Build Coastguard Worker           "level.int32",
63*d9f75844SAndroid Build Coastguard Worker           "The name of the applied input volume file.");
64*d9f75844SAndroid Build Coastguard Worker ABSL_FLAG(std::string,
65*d9f75844SAndroid Build Coastguard Worker           keypress_file,
66*d9f75844SAndroid Build Coastguard Worker           "keypress.bool",
67*d9f75844SAndroid Build Coastguard Worker           "The name of the keypress file.");
68*d9f75844SAndroid Build Coastguard Worker ABSL_FLAG(std::string,
69*d9f75844SAndroid Build Coastguard Worker           callorder_file,
70*d9f75844SAndroid Build Coastguard Worker           "callorder",
71*d9f75844SAndroid Build Coastguard Worker           "The name of the render/capture call order file.");
72*d9f75844SAndroid Build Coastguard Worker ABSL_FLAG(std::string,
73*d9f75844SAndroid Build Coastguard Worker           settings_file,
74*d9f75844SAndroid Build Coastguard Worker           "settings.txt",
75*d9f75844SAndroid Build Coastguard Worker           "The name of the settings file.");
76*d9f75844SAndroid Build Coastguard Worker ABSL_FLAG(bool,
77*d9f75844SAndroid Build Coastguard Worker           full,
78*d9f75844SAndroid Build Coastguard Worker           false,
79*d9f75844SAndroid Build Coastguard Worker           "Unpack the full set of files (normally not needed).");
80*d9f75844SAndroid Build Coastguard Worker ABSL_FLAG(bool, raw, false, "Write raw data instead of a WAV file.");
81*d9f75844SAndroid Build Coastguard Worker ABSL_FLAG(bool,
82*d9f75844SAndroid Build Coastguard Worker           text,
83*d9f75844SAndroid Build Coastguard Worker           false,
84*d9f75844SAndroid Build Coastguard Worker           "Write non-audio files as text files instead of binary files.");
85*d9f75844SAndroid Build Coastguard Worker ABSL_FLAG(bool,
86*d9f75844SAndroid Build Coastguard Worker           use_init_suffix,
87*d9f75844SAndroid Build Coastguard Worker           false,
88*d9f75844SAndroid Build Coastguard Worker           "Use init index instead of capture frame count as file name suffix.");
89*d9f75844SAndroid Build Coastguard Worker 
90*d9f75844SAndroid Build Coastguard Worker #define PRINT_CONFIG(field_name)                                         \
91*d9f75844SAndroid Build Coastguard Worker   if (msg.has_##field_name()) {                                          \
92*d9f75844SAndroid Build Coastguard Worker     fprintf(settings_file, "  " #field_name ": %d\n", msg.field_name()); \
93*d9f75844SAndroid Build Coastguard Worker   }
94*d9f75844SAndroid Build Coastguard Worker 
95*d9f75844SAndroid Build Coastguard Worker #define PRINT_CONFIG_FLOAT(field_name)                                   \
96*d9f75844SAndroid Build Coastguard Worker   if (msg.has_##field_name()) {                                          \
97*d9f75844SAndroid Build Coastguard Worker     fprintf(settings_file, "  " #field_name ": %f\n", msg.field_name()); \
98*d9f75844SAndroid Build Coastguard Worker   }
99*d9f75844SAndroid Build Coastguard Worker 
100*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
101*d9f75844SAndroid Build Coastguard Worker 
102*d9f75844SAndroid Build Coastguard Worker using audioproc::Event;
103*d9f75844SAndroid Build Coastguard Worker using audioproc::Init;
104*d9f75844SAndroid Build Coastguard Worker using audioproc::ReverseStream;
105*d9f75844SAndroid Build Coastguard Worker using audioproc::Stream;
106*d9f75844SAndroid Build Coastguard Worker 
107*d9f75844SAndroid Build Coastguard Worker namespace {
108*d9f75844SAndroid Build Coastguard Worker class RawFile final {
109*d9f75844SAndroid Build Coastguard Worker  public:
RawFile(const std::string & filename)110*d9f75844SAndroid Build Coastguard Worker   explicit RawFile(const std::string& filename)
111*d9f75844SAndroid Build Coastguard Worker       : file_handle_(fopen(filename.c_str(), "wb")) {}
~RawFile()112*d9f75844SAndroid Build Coastguard Worker   ~RawFile() { fclose(file_handle_); }
113*d9f75844SAndroid Build Coastguard Worker 
114*d9f75844SAndroid Build Coastguard Worker   RawFile(const RawFile&) = delete;
115*d9f75844SAndroid Build Coastguard Worker   RawFile& operator=(const RawFile&) = delete;
116*d9f75844SAndroid Build Coastguard Worker 
WriteSamples(const int16_t * samples,size_t num_samples)117*d9f75844SAndroid Build Coastguard Worker   void WriteSamples(const int16_t* samples, size_t num_samples) {
118*d9f75844SAndroid Build Coastguard Worker #ifndef WEBRTC_ARCH_LITTLE_ENDIAN
119*d9f75844SAndroid Build Coastguard Worker #error "Need to convert samples to little-endian when writing to PCM file"
120*d9f75844SAndroid Build Coastguard Worker #endif
121*d9f75844SAndroid Build Coastguard Worker     fwrite(samples, sizeof(*samples), num_samples, file_handle_);
122*d9f75844SAndroid Build Coastguard Worker   }
123*d9f75844SAndroid Build Coastguard Worker 
WriteSamples(const float * samples,size_t num_samples)124*d9f75844SAndroid Build Coastguard Worker   void WriteSamples(const float* samples, size_t num_samples) {
125*d9f75844SAndroid Build Coastguard Worker     fwrite(samples, sizeof(*samples), num_samples, file_handle_);
126*d9f75844SAndroid Build Coastguard Worker   }
127*d9f75844SAndroid Build Coastguard Worker 
128*d9f75844SAndroid Build Coastguard Worker  private:
129*d9f75844SAndroid Build Coastguard Worker   FILE* file_handle_;
130*d9f75844SAndroid Build Coastguard Worker };
131*d9f75844SAndroid Build Coastguard Worker 
WriteIntData(const int16_t * data,size_t length,WavWriter * wav_file,RawFile * raw_file)132*d9f75844SAndroid Build Coastguard Worker void WriteIntData(const int16_t* data,
133*d9f75844SAndroid Build Coastguard Worker                   size_t length,
134*d9f75844SAndroid Build Coastguard Worker                   WavWriter* wav_file,
135*d9f75844SAndroid Build Coastguard Worker                   RawFile* raw_file) {
136*d9f75844SAndroid Build Coastguard Worker   if (wav_file) {
137*d9f75844SAndroid Build Coastguard Worker     wav_file->WriteSamples(data, length);
138*d9f75844SAndroid Build Coastguard Worker   }
139*d9f75844SAndroid Build Coastguard Worker   if (raw_file) {
140*d9f75844SAndroid Build Coastguard Worker     raw_file->WriteSamples(data, length);
141*d9f75844SAndroid Build Coastguard Worker   }
142*d9f75844SAndroid Build Coastguard Worker }
143*d9f75844SAndroid Build Coastguard Worker 
WriteFloatData(const float * const * data,size_t samples_per_channel,size_t num_channels,WavWriter * wav_file,RawFile * raw_file)144*d9f75844SAndroid Build Coastguard Worker void WriteFloatData(const float* const* data,
145*d9f75844SAndroid Build Coastguard Worker                     size_t samples_per_channel,
146*d9f75844SAndroid Build Coastguard Worker                     size_t num_channels,
147*d9f75844SAndroid Build Coastguard Worker                     WavWriter* wav_file,
148*d9f75844SAndroid Build Coastguard Worker                     RawFile* raw_file) {
149*d9f75844SAndroid Build Coastguard Worker   size_t length = num_channels * samples_per_channel;
150*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<float[]> buffer(new float[length]);
151*d9f75844SAndroid Build Coastguard Worker   Interleave(data, samples_per_channel, num_channels, buffer.get());
152*d9f75844SAndroid Build Coastguard Worker   if (raw_file) {
153*d9f75844SAndroid Build Coastguard Worker     raw_file->WriteSamples(buffer.get(), length);
154*d9f75844SAndroid Build Coastguard Worker   }
155*d9f75844SAndroid Build Coastguard Worker   // TODO(aluebs): Use ScaleToInt16Range() from audio_util
156*d9f75844SAndroid Build Coastguard Worker   for (size_t i = 0; i < length; ++i) {
157*d9f75844SAndroid Build Coastguard Worker     buffer[i] = buffer[i] > 0
158*d9f75844SAndroid Build Coastguard Worker                     ? buffer[i] * std::numeric_limits<int16_t>::max()
159*d9f75844SAndroid Build Coastguard Worker                     : -buffer[i] * std::numeric_limits<int16_t>::min();
160*d9f75844SAndroid Build Coastguard Worker   }
161*d9f75844SAndroid Build Coastguard Worker   if (wav_file) {
162*d9f75844SAndroid Build Coastguard Worker     wav_file->WriteSamples(buffer.get(), length);
163*d9f75844SAndroid Build Coastguard Worker   }
164*d9f75844SAndroid Build Coastguard Worker }
165*d9f75844SAndroid Build Coastguard Worker 
166*d9f75844SAndroid Build Coastguard Worker // Exits on failure; do not use in unit tests.
OpenFile(const std::string & filename,const char * mode)167*d9f75844SAndroid Build Coastguard Worker FILE* OpenFile(const std::string& filename, const char* mode) {
168*d9f75844SAndroid Build Coastguard Worker   FILE* file = fopen(filename.c_str(), mode);
169*d9f75844SAndroid Build Coastguard Worker   RTC_CHECK(file) << "Unable to open file " << filename;
170*d9f75844SAndroid Build Coastguard Worker   return file;
171*d9f75844SAndroid Build Coastguard Worker }
172*d9f75844SAndroid Build Coastguard Worker 
WriteData(const void * data,size_t size,FILE * file,const std::string & filename)173*d9f75844SAndroid Build Coastguard Worker void WriteData(const void* data,
174*d9f75844SAndroid Build Coastguard Worker                size_t size,
175*d9f75844SAndroid Build Coastguard Worker                FILE* file,
176*d9f75844SAndroid Build Coastguard Worker                const std::string& filename) {
177*d9f75844SAndroid Build Coastguard Worker   RTC_CHECK_EQ(fwrite(data, size, 1, file), 1)
178*d9f75844SAndroid Build Coastguard Worker       << "Error when writing to " << filename.c_str();
179*d9f75844SAndroid Build Coastguard Worker }
180*d9f75844SAndroid Build Coastguard Worker 
WriteCallOrderData(const bool render_call,FILE * file,const std::string & filename)181*d9f75844SAndroid Build Coastguard Worker void WriteCallOrderData(const bool render_call,
182*d9f75844SAndroid Build Coastguard Worker                         FILE* file,
183*d9f75844SAndroid Build Coastguard Worker                         const std::string& filename) {
184*d9f75844SAndroid Build Coastguard Worker   const char call_type = render_call ? 'r' : 'c';
185*d9f75844SAndroid Build Coastguard Worker   WriteData(&call_type, sizeof(call_type), file, filename.c_str());
186*d9f75844SAndroid Build Coastguard Worker }
187*d9f75844SAndroid Build Coastguard Worker 
WritingCallOrderFile()188*d9f75844SAndroid Build Coastguard Worker bool WritingCallOrderFile() {
189*d9f75844SAndroid Build Coastguard Worker   return absl::GetFlag(FLAGS_full);
190*d9f75844SAndroid Build Coastguard Worker }
191*d9f75844SAndroid Build Coastguard Worker 
WritingRuntimeSettingFiles()192*d9f75844SAndroid Build Coastguard Worker bool WritingRuntimeSettingFiles() {
193*d9f75844SAndroid Build Coastguard Worker   return absl::GetFlag(FLAGS_full);
194*d9f75844SAndroid Build Coastguard Worker }
195*d9f75844SAndroid Build Coastguard Worker 
196*d9f75844SAndroid Build Coastguard Worker // Exports RuntimeSetting AEC dump events to Audacity-readable files.
197*d9f75844SAndroid Build Coastguard Worker // This class is not RAII compliant.
198*d9f75844SAndroid Build Coastguard Worker class RuntimeSettingWriter {
199*d9f75844SAndroid Build Coastguard Worker  public:
RuntimeSettingWriter(std::string name,rtc::FunctionView<bool (const Event)> is_exporter_for,rtc::FunctionView<std::string (const Event)> get_timeline_label)200*d9f75844SAndroid Build Coastguard Worker   RuntimeSettingWriter(
201*d9f75844SAndroid Build Coastguard Worker       std::string name,
202*d9f75844SAndroid Build Coastguard Worker       rtc::FunctionView<bool(const Event)> is_exporter_for,
203*d9f75844SAndroid Build Coastguard Worker       rtc::FunctionView<std::string(const Event)> get_timeline_label)
204*d9f75844SAndroid Build Coastguard Worker       : setting_name_(std::move(name)),
205*d9f75844SAndroid Build Coastguard Worker         is_exporter_for_(is_exporter_for),
206*d9f75844SAndroid Build Coastguard Worker         get_timeline_label_(get_timeline_label) {}
~RuntimeSettingWriter()207*d9f75844SAndroid Build Coastguard Worker   ~RuntimeSettingWriter() { Flush(); }
208*d9f75844SAndroid Build Coastguard Worker 
IsExporterFor(const Event & event) const209*d9f75844SAndroid Build Coastguard Worker   bool IsExporterFor(const Event& event) const {
210*d9f75844SAndroid Build Coastguard Worker     return is_exporter_for_(event);
211*d9f75844SAndroid Build Coastguard Worker   }
212*d9f75844SAndroid Build Coastguard Worker 
213*d9f75844SAndroid Build Coastguard Worker   // Writes to file the payload of `event` using `frame_count` to calculate
214*d9f75844SAndroid Build Coastguard Worker   // timestamp.
WriteEvent(const Event & event,int frame_count)215*d9f75844SAndroid Build Coastguard Worker   void WriteEvent(const Event& event, int frame_count) {
216*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(is_exporter_for_(event));
217*d9f75844SAndroid Build Coastguard Worker     if (file_ == nullptr) {
218*d9f75844SAndroid Build Coastguard Worker       rtc::StringBuilder file_name;
219*d9f75844SAndroid Build Coastguard Worker       file_name << setting_name_ << frame_offset_ << ".txt";
220*d9f75844SAndroid Build Coastguard Worker       file_ = OpenFile(file_name.str(), "wb");
221*d9f75844SAndroid Build Coastguard Worker     }
222*d9f75844SAndroid Build Coastguard Worker 
223*d9f75844SAndroid Build Coastguard Worker     // Time in the current WAV file, in seconds.
224*d9f75844SAndroid Build Coastguard Worker     double time = (frame_count - frame_offset_) / 100.0;
225*d9f75844SAndroid Build Coastguard Worker     std::string label = get_timeline_label_(event);
226*d9f75844SAndroid Build Coastguard Worker     // In Audacity, all annotations are encoded as intervals.
227*d9f75844SAndroid Build Coastguard Worker     fprintf(file_, "%.6f\t%.6f\t%s \n", time, time, label.c_str());
228*d9f75844SAndroid Build Coastguard Worker   }
229*d9f75844SAndroid Build Coastguard Worker 
230*d9f75844SAndroid Build Coastguard Worker   // Handles an AEC dump initialization event, occurring at frame
231*d9f75844SAndroid Build Coastguard Worker   // `frame_offset`.
HandleInitEvent(int frame_offset)232*d9f75844SAndroid Build Coastguard Worker   void HandleInitEvent(int frame_offset) {
233*d9f75844SAndroid Build Coastguard Worker     Flush();
234*d9f75844SAndroid Build Coastguard Worker     frame_offset_ = frame_offset;
235*d9f75844SAndroid Build Coastguard Worker   }
236*d9f75844SAndroid Build Coastguard Worker 
237*d9f75844SAndroid Build Coastguard Worker  private:
Flush()238*d9f75844SAndroid Build Coastguard Worker   void Flush() {
239*d9f75844SAndroid Build Coastguard Worker     if (file_ != nullptr) {
240*d9f75844SAndroid Build Coastguard Worker       fclose(file_);
241*d9f75844SAndroid Build Coastguard Worker       file_ = nullptr;
242*d9f75844SAndroid Build Coastguard Worker     }
243*d9f75844SAndroid Build Coastguard Worker   }
244*d9f75844SAndroid Build Coastguard Worker 
245*d9f75844SAndroid Build Coastguard Worker   FILE* file_ = nullptr;
246*d9f75844SAndroid Build Coastguard Worker   int frame_offset_ = 0;
247*d9f75844SAndroid Build Coastguard Worker   const std::string setting_name_;
248*d9f75844SAndroid Build Coastguard Worker   const rtc::FunctionView<bool(Event)> is_exporter_for_;
249*d9f75844SAndroid Build Coastguard Worker   const rtc::FunctionView<std::string(Event)> get_timeline_label_;
250*d9f75844SAndroid Build Coastguard Worker };
251*d9f75844SAndroid Build Coastguard Worker 
252*d9f75844SAndroid Build Coastguard Worker // Returns RuntimeSetting exporters for runtime setting types defined in
253*d9f75844SAndroid Build Coastguard Worker // debug.proto.
RuntimeSettingWriters()254*d9f75844SAndroid Build Coastguard Worker std::vector<RuntimeSettingWriter> RuntimeSettingWriters() {
255*d9f75844SAndroid Build Coastguard Worker   return {
256*d9f75844SAndroid Build Coastguard Worker       RuntimeSettingWriter(
257*d9f75844SAndroid Build Coastguard Worker           "CapturePreGain",
258*d9f75844SAndroid Build Coastguard Worker           [](const Event& event) -> bool {
259*d9f75844SAndroid Build Coastguard Worker             return event.runtime_setting().has_capture_pre_gain();
260*d9f75844SAndroid Build Coastguard Worker           },
261*d9f75844SAndroid Build Coastguard Worker           [](const Event& event) -> std::string {
262*d9f75844SAndroid Build Coastguard Worker             return std::to_string(event.runtime_setting().capture_pre_gain());
263*d9f75844SAndroid Build Coastguard Worker           }),
264*d9f75844SAndroid Build Coastguard Worker       RuntimeSettingWriter(
265*d9f75844SAndroid Build Coastguard Worker           "CustomRenderProcessingRuntimeSetting",
266*d9f75844SAndroid Build Coastguard Worker           [](const Event& event) -> bool {
267*d9f75844SAndroid Build Coastguard Worker             return event.runtime_setting()
268*d9f75844SAndroid Build Coastguard Worker                 .has_custom_render_processing_setting();
269*d9f75844SAndroid Build Coastguard Worker           },
270*d9f75844SAndroid Build Coastguard Worker           [](const Event& event) -> std::string {
271*d9f75844SAndroid Build Coastguard Worker             return std::to_string(
272*d9f75844SAndroid Build Coastguard Worker                 event.runtime_setting().custom_render_processing_setting());
273*d9f75844SAndroid Build Coastguard Worker           }),
274*d9f75844SAndroid Build Coastguard Worker       RuntimeSettingWriter(
275*d9f75844SAndroid Build Coastguard Worker           "CaptureFixedPostGain",
276*d9f75844SAndroid Build Coastguard Worker           [](const Event& event) -> bool {
277*d9f75844SAndroid Build Coastguard Worker             return event.runtime_setting().has_capture_fixed_post_gain();
278*d9f75844SAndroid Build Coastguard Worker           },
279*d9f75844SAndroid Build Coastguard Worker           [](const Event& event) -> std::string {
280*d9f75844SAndroid Build Coastguard Worker             return std::to_string(
281*d9f75844SAndroid Build Coastguard Worker                 event.runtime_setting().capture_fixed_post_gain());
282*d9f75844SAndroid Build Coastguard Worker           }),
283*d9f75844SAndroid Build Coastguard Worker       RuntimeSettingWriter(
284*d9f75844SAndroid Build Coastguard Worker           "PlayoutVolumeChange",
285*d9f75844SAndroid Build Coastguard Worker           [](const Event& event) -> bool {
286*d9f75844SAndroid Build Coastguard Worker             return event.runtime_setting().has_playout_volume_change();
287*d9f75844SAndroid Build Coastguard Worker           },
288*d9f75844SAndroid Build Coastguard Worker           [](const Event& event) -> std::string {
289*d9f75844SAndroid Build Coastguard Worker             return std::to_string(
290*d9f75844SAndroid Build Coastguard Worker                 event.runtime_setting().playout_volume_change());
291*d9f75844SAndroid Build Coastguard Worker           })};
292*d9f75844SAndroid Build Coastguard Worker }
293*d9f75844SAndroid Build Coastguard Worker 
GetWavFileIndex(int init_index,int frame_count)294*d9f75844SAndroid Build Coastguard Worker std::string GetWavFileIndex(int init_index, int frame_count) {
295*d9f75844SAndroid Build Coastguard Worker   rtc::StringBuilder suffix;
296*d9f75844SAndroid Build Coastguard Worker   if (absl::GetFlag(FLAGS_use_init_suffix)) {
297*d9f75844SAndroid Build Coastguard Worker     suffix << "_" << init_index;
298*d9f75844SAndroid Build Coastguard Worker   } else {
299*d9f75844SAndroid Build Coastguard Worker     suffix << frame_count;
300*d9f75844SAndroid Build Coastguard Worker   }
301*d9f75844SAndroid Build Coastguard Worker   return suffix.str();
302*d9f75844SAndroid Build Coastguard Worker }
303*d9f75844SAndroid Build Coastguard Worker 
304*d9f75844SAndroid Build Coastguard Worker }  // namespace
305*d9f75844SAndroid Build Coastguard Worker 
do_main(int argc,char * argv[])306*d9f75844SAndroid Build Coastguard Worker int do_main(int argc, char* argv[]) {
307*d9f75844SAndroid Build Coastguard Worker   std::vector<char*> args = absl::ParseCommandLine(argc, argv);
308*d9f75844SAndroid Build Coastguard Worker   std::string program_name = args[0];
309*d9f75844SAndroid Build Coastguard Worker   std::string usage =
310*d9f75844SAndroid Build Coastguard Worker       "Commandline tool to unpack audioproc debug files.\n"
311*d9f75844SAndroid Build Coastguard Worker       "Example usage:\n" +
312*d9f75844SAndroid Build Coastguard Worker       program_name + " debug_dump.pb\n";
313*d9f75844SAndroid Build Coastguard Worker 
314*d9f75844SAndroid Build Coastguard Worker   if (args.size() < 2) {
315*d9f75844SAndroid Build Coastguard Worker     printf("%s", usage.c_str());
316*d9f75844SAndroid Build Coastguard Worker     return 1;
317*d9f75844SAndroid Build Coastguard Worker   }
318*d9f75844SAndroid Build Coastguard Worker 
319*d9f75844SAndroid Build Coastguard Worker   FILE* debug_file = OpenFile(args[1], "rb");
320*d9f75844SAndroid Build Coastguard Worker 
321*d9f75844SAndroid Build Coastguard Worker   Event event_msg;
322*d9f75844SAndroid Build Coastguard Worker   int frame_count = 0;
323*d9f75844SAndroid Build Coastguard Worker   int init_count = 0;
324*d9f75844SAndroid Build Coastguard Worker   size_t reverse_samples_per_channel = 0;
325*d9f75844SAndroid Build Coastguard Worker   size_t input_samples_per_channel = 0;
326*d9f75844SAndroid Build Coastguard Worker   size_t output_samples_per_channel = 0;
327*d9f75844SAndroid Build Coastguard Worker   size_t num_reverse_channels = 0;
328*d9f75844SAndroid Build Coastguard Worker   size_t num_input_channels = 0;
329*d9f75844SAndroid Build Coastguard Worker   size_t num_output_channels = 0;
330*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<WavWriter> reverse_wav_file;
331*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<WavWriter> input_wav_file;
332*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<WavWriter> output_wav_file;
333*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<RawFile> reverse_raw_file;
334*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<RawFile> input_raw_file;
335*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<RawFile> output_raw_file;
336*d9f75844SAndroid Build Coastguard Worker 
337*d9f75844SAndroid Build Coastguard Worker   rtc::StringBuilder callorder_raw_name;
338*d9f75844SAndroid Build Coastguard Worker   callorder_raw_name << absl::GetFlag(FLAGS_callorder_file) << ".char";
339*d9f75844SAndroid Build Coastguard Worker   FILE* callorder_char_file = WritingCallOrderFile()
340*d9f75844SAndroid Build Coastguard Worker                                   ? OpenFile(callorder_raw_name.str(), "wb")
341*d9f75844SAndroid Build Coastguard Worker                                   : nullptr;
342*d9f75844SAndroid Build Coastguard Worker   FILE* settings_file = OpenFile(absl::GetFlag(FLAGS_settings_file), "wb");
343*d9f75844SAndroid Build Coastguard Worker 
344*d9f75844SAndroid Build Coastguard Worker   std::vector<RuntimeSettingWriter> runtime_setting_writers =
345*d9f75844SAndroid Build Coastguard Worker       RuntimeSettingWriters();
346*d9f75844SAndroid Build Coastguard Worker 
347*d9f75844SAndroid Build Coastguard Worker   while (ReadMessageFromFile(debug_file, &event_msg)) {
348*d9f75844SAndroid Build Coastguard Worker     if (event_msg.type() == Event::REVERSE_STREAM) {
349*d9f75844SAndroid Build Coastguard Worker       if (!event_msg.has_reverse_stream()) {
350*d9f75844SAndroid Build Coastguard Worker         printf("Corrupt input file: ReverseStream missing.\n");
351*d9f75844SAndroid Build Coastguard Worker         return 1;
352*d9f75844SAndroid Build Coastguard Worker       }
353*d9f75844SAndroid Build Coastguard Worker 
354*d9f75844SAndroid Build Coastguard Worker       const ReverseStream msg = event_msg.reverse_stream();
355*d9f75844SAndroid Build Coastguard Worker       if (msg.has_data()) {
356*d9f75844SAndroid Build Coastguard Worker         if (absl::GetFlag(FLAGS_raw) && !reverse_raw_file) {
357*d9f75844SAndroid Build Coastguard Worker           reverse_raw_file.reset(
358*d9f75844SAndroid Build Coastguard Worker               new RawFile(absl::GetFlag(FLAGS_reverse_file) + ".pcm"));
359*d9f75844SAndroid Build Coastguard Worker         }
360*d9f75844SAndroid Build Coastguard Worker         // TODO(aluebs): Replace "num_reverse_channels *
361*d9f75844SAndroid Build Coastguard Worker         // reverse_samples_per_channel" with "msg.data().size() /
362*d9f75844SAndroid Build Coastguard Worker         // sizeof(int16_t)" and so on when this fix in audio_processing has made
363*d9f75844SAndroid Build Coastguard Worker         // it into stable: https://webrtc-codereview.appspot.com/15299004/
364*d9f75844SAndroid Build Coastguard Worker         WriteIntData(reinterpret_cast<const int16_t*>(msg.data().data()),
365*d9f75844SAndroid Build Coastguard Worker                      num_reverse_channels * reverse_samples_per_channel,
366*d9f75844SAndroid Build Coastguard Worker                      reverse_wav_file.get(), reverse_raw_file.get());
367*d9f75844SAndroid Build Coastguard Worker       } else if (msg.channel_size() > 0) {
368*d9f75844SAndroid Build Coastguard Worker         if (absl::GetFlag(FLAGS_raw) && !reverse_raw_file) {
369*d9f75844SAndroid Build Coastguard Worker           reverse_raw_file.reset(
370*d9f75844SAndroid Build Coastguard Worker               new RawFile(absl::GetFlag(FLAGS_reverse_file) + ".float"));
371*d9f75844SAndroid Build Coastguard Worker         }
372*d9f75844SAndroid Build Coastguard Worker         std::unique_ptr<const float*[]> data(
373*d9f75844SAndroid Build Coastguard Worker             new const float*[num_reverse_channels]);
374*d9f75844SAndroid Build Coastguard Worker         for (size_t i = 0; i < num_reverse_channels; ++i) {
375*d9f75844SAndroid Build Coastguard Worker           data[i] = reinterpret_cast<const float*>(msg.channel(i).data());
376*d9f75844SAndroid Build Coastguard Worker         }
377*d9f75844SAndroid Build Coastguard Worker         WriteFloatData(data.get(), reverse_samples_per_channel,
378*d9f75844SAndroid Build Coastguard Worker                        num_reverse_channels, reverse_wav_file.get(),
379*d9f75844SAndroid Build Coastguard Worker                        reverse_raw_file.get());
380*d9f75844SAndroid Build Coastguard Worker       }
381*d9f75844SAndroid Build Coastguard Worker       if (absl::GetFlag(FLAGS_full)) {
382*d9f75844SAndroid Build Coastguard Worker         if (WritingCallOrderFile()) {
383*d9f75844SAndroid Build Coastguard Worker           WriteCallOrderData(true /* render_call */, callorder_char_file,
384*d9f75844SAndroid Build Coastguard Worker                              absl::GetFlag(FLAGS_callorder_file));
385*d9f75844SAndroid Build Coastguard Worker         }
386*d9f75844SAndroid Build Coastguard Worker       }
387*d9f75844SAndroid Build Coastguard Worker     } else if (event_msg.type() == Event::STREAM) {
388*d9f75844SAndroid Build Coastguard Worker       frame_count++;
389*d9f75844SAndroid Build Coastguard Worker       if (!event_msg.has_stream()) {
390*d9f75844SAndroid Build Coastguard Worker         printf("Corrupt input file: Stream missing.\n");
391*d9f75844SAndroid Build Coastguard Worker         return 1;
392*d9f75844SAndroid Build Coastguard Worker       }
393*d9f75844SAndroid Build Coastguard Worker 
394*d9f75844SAndroid Build Coastguard Worker       const Stream msg = event_msg.stream();
395*d9f75844SAndroid Build Coastguard Worker       if (msg.has_input_data()) {
396*d9f75844SAndroid Build Coastguard Worker         if (absl::GetFlag(FLAGS_raw) && !input_raw_file) {
397*d9f75844SAndroid Build Coastguard Worker           input_raw_file.reset(
398*d9f75844SAndroid Build Coastguard Worker               new RawFile(absl::GetFlag(FLAGS_input_file) + ".pcm"));
399*d9f75844SAndroid Build Coastguard Worker         }
400*d9f75844SAndroid Build Coastguard Worker         WriteIntData(reinterpret_cast<const int16_t*>(msg.input_data().data()),
401*d9f75844SAndroid Build Coastguard Worker                      num_input_channels * input_samples_per_channel,
402*d9f75844SAndroid Build Coastguard Worker                      input_wav_file.get(), input_raw_file.get());
403*d9f75844SAndroid Build Coastguard Worker       } else if (msg.input_channel_size() > 0) {
404*d9f75844SAndroid Build Coastguard Worker         if (absl::GetFlag(FLAGS_raw) && !input_raw_file) {
405*d9f75844SAndroid Build Coastguard Worker           input_raw_file.reset(
406*d9f75844SAndroid Build Coastguard Worker               new RawFile(absl::GetFlag(FLAGS_input_file) + ".float"));
407*d9f75844SAndroid Build Coastguard Worker         }
408*d9f75844SAndroid Build Coastguard Worker         std::unique_ptr<const float*[]> data(
409*d9f75844SAndroid Build Coastguard Worker             new const float*[num_input_channels]);
410*d9f75844SAndroid Build Coastguard Worker         for (size_t i = 0; i < num_input_channels; ++i) {
411*d9f75844SAndroid Build Coastguard Worker           data[i] = reinterpret_cast<const float*>(msg.input_channel(i).data());
412*d9f75844SAndroid Build Coastguard Worker         }
413*d9f75844SAndroid Build Coastguard Worker         WriteFloatData(data.get(), input_samples_per_channel,
414*d9f75844SAndroid Build Coastguard Worker                        num_input_channels, input_wav_file.get(),
415*d9f75844SAndroid Build Coastguard Worker                        input_raw_file.get());
416*d9f75844SAndroid Build Coastguard Worker       }
417*d9f75844SAndroid Build Coastguard Worker 
418*d9f75844SAndroid Build Coastguard Worker       if (msg.has_output_data()) {
419*d9f75844SAndroid Build Coastguard Worker         if (absl::GetFlag(FLAGS_raw) && !output_raw_file) {
420*d9f75844SAndroid Build Coastguard Worker           output_raw_file.reset(
421*d9f75844SAndroid Build Coastguard Worker               new RawFile(absl::GetFlag(FLAGS_output_file) + ".pcm"));
422*d9f75844SAndroid Build Coastguard Worker         }
423*d9f75844SAndroid Build Coastguard Worker         WriteIntData(reinterpret_cast<const int16_t*>(msg.output_data().data()),
424*d9f75844SAndroid Build Coastguard Worker                      num_output_channels * output_samples_per_channel,
425*d9f75844SAndroid Build Coastguard Worker                      output_wav_file.get(), output_raw_file.get());
426*d9f75844SAndroid Build Coastguard Worker       } else if (msg.output_channel_size() > 0) {
427*d9f75844SAndroid Build Coastguard Worker         if (absl::GetFlag(FLAGS_raw) && !output_raw_file) {
428*d9f75844SAndroid Build Coastguard Worker           output_raw_file.reset(
429*d9f75844SAndroid Build Coastguard Worker               new RawFile(absl::GetFlag(FLAGS_output_file) + ".float"));
430*d9f75844SAndroid Build Coastguard Worker         }
431*d9f75844SAndroid Build Coastguard Worker         std::unique_ptr<const float*[]> data(
432*d9f75844SAndroid Build Coastguard Worker             new const float*[num_output_channels]);
433*d9f75844SAndroid Build Coastguard Worker         for (size_t i = 0; i < num_output_channels; ++i) {
434*d9f75844SAndroid Build Coastguard Worker           data[i] =
435*d9f75844SAndroid Build Coastguard Worker               reinterpret_cast<const float*>(msg.output_channel(i).data());
436*d9f75844SAndroid Build Coastguard Worker         }
437*d9f75844SAndroid Build Coastguard Worker         WriteFloatData(data.get(), output_samples_per_channel,
438*d9f75844SAndroid Build Coastguard Worker                        num_output_channels, output_wav_file.get(),
439*d9f75844SAndroid Build Coastguard Worker                        output_raw_file.get());
440*d9f75844SAndroid Build Coastguard Worker       }
441*d9f75844SAndroid Build Coastguard Worker 
442*d9f75844SAndroid Build Coastguard Worker       if (absl::GetFlag(FLAGS_full)) {
443*d9f75844SAndroid Build Coastguard Worker         if (WritingCallOrderFile()) {
444*d9f75844SAndroid Build Coastguard Worker           WriteCallOrderData(false /* render_call */, callorder_char_file,
445*d9f75844SAndroid Build Coastguard Worker                              absl::GetFlag(FLAGS_callorder_file));
446*d9f75844SAndroid Build Coastguard Worker         }
447*d9f75844SAndroid Build Coastguard Worker         if (msg.has_delay()) {
448*d9f75844SAndroid Build Coastguard Worker           static FILE* delay_file =
449*d9f75844SAndroid Build Coastguard Worker               OpenFile(absl::GetFlag(FLAGS_delay_file), "wb");
450*d9f75844SAndroid Build Coastguard Worker           int32_t delay = msg.delay();
451*d9f75844SAndroid Build Coastguard Worker           if (absl::GetFlag(FLAGS_text)) {
452*d9f75844SAndroid Build Coastguard Worker             fprintf(delay_file, "%d\n", delay);
453*d9f75844SAndroid Build Coastguard Worker           } else {
454*d9f75844SAndroid Build Coastguard Worker             WriteData(&delay, sizeof(delay), delay_file,
455*d9f75844SAndroid Build Coastguard Worker                       absl::GetFlag(FLAGS_delay_file));
456*d9f75844SAndroid Build Coastguard Worker           }
457*d9f75844SAndroid Build Coastguard Worker         }
458*d9f75844SAndroid Build Coastguard Worker 
459*d9f75844SAndroid Build Coastguard Worker         if (msg.has_drift()) {
460*d9f75844SAndroid Build Coastguard Worker           static FILE* drift_file =
461*d9f75844SAndroid Build Coastguard Worker               OpenFile(absl::GetFlag(FLAGS_drift_file), "wb");
462*d9f75844SAndroid Build Coastguard Worker           int32_t drift = msg.drift();
463*d9f75844SAndroid Build Coastguard Worker           if (absl::GetFlag(FLAGS_text)) {
464*d9f75844SAndroid Build Coastguard Worker             fprintf(drift_file, "%d\n", drift);
465*d9f75844SAndroid Build Coastguard Worker           } else {
466*d9f75844SAndroid Build Coastguard Worker             WriteData(&drift, sizeof(drift), drift_file,
467*d9f75844SAndroid Build Coastguard Worker                       absl::GetFlag(FLAGS_drift_file));
468*d9f75844SAndroid Build Coastguard Worker           }
469*d9f75844SAndroid Build Coastguard Worker         }
470*d9f75844SAndroid Build Coastguard Worker 
471*d9f75844SAndroid Build Coastguard Worker         if (msg.has_applied_input_volume()) {
472*d9f75844SAndroid Build Coastguard Worker           static FILE* level_file =
473*d9f75844SAndroid Build Coastguard Worker               OpenFile(absl::GetFlag(FLAGS_level_file), "wb");
474*d9f75844SAndroid Build Coastguard Worker           int32_t level = msg.applied_input_volume();
475*d9f75844SAndroid Build Coastguard Worker           if (absl::GetFlag(FLAGS_text)) {
476*d9f75844SAndroid Build Coastguard Worker             fprintf(level_file, "%d\n", level);
477*d9f75844SAndroid Build Coastguard Worker           } else {
478*d9f75844SAndroid Build Coastguard Worker             WriteData(&level, sizeof(level), level_file,
479*d9f75844SAndroid Build Coastguard Worker                       absl::GetFlag(FLAGS_level_file));
480*d9f75844SAndroid Build Coastguard Worker           }
481*d9f75844SAndroid Build Coastguard Worker         }
482*d9f75844SAndroid Build Coastguard Worker 
483*d9f75844SAndroid Build Coastguard Worker         if (msg.has_keypress()) {
484*d9f75844SAndroid Build Coastguard Worker           static FILE* keypress_file =
485*d9f75844SAndroid Build Coastguard Worker               OpenFile(absl::GetFlag(FLAGS_keypress_file), "wb");
486*d9f75844SAndroid Build Coastguard Worker           bool keypress = msg.keypress();
487*d9f75844SAndroid Build Coastguard Worker           if (absl::GetFlag(FLAGS_text)) {
488*d9f75844SAndroid Build Coastguard Worker             fprintf(keypress_file, "%d\n", keypress);
489*d9f75844SAndroid Build Coastguard Worker           } else {
490*d9f75844SAndroid Build Coastguard Worker             WriteData(&keypress, sizeof(keypress), keypress_file,
491*d9f75844SAndroid Build Coastguard Worker                       absl::GetFlag(FLAGS_keypress_file));
492*d9f75844SAndroid Build Coastguard Worker           }
493*d9f75844SAndroid Build Coastguard Worker         }
494*d9f75844SAndroid Build Coastguard Worker       }
495*d9f75844SAndroid Build Coastguard Worker     } else if (event_msg.type() == Event::CONFIG) {
496*d9f75844SAndroid Build Coastguard Worker       if (!event_msg.has_config()) {
497*d9f75844SAndroid Build Coastguard Worker         printf("Corrupt input file: Config missing.\n");
498*d9f75844SAndroid Build Coastguard Worker         return 1;
499*d9f75844SAndroid Build Coastguard Worker       }
500*d9f75844SAndroid Build Coastguard Worker       const audioproc::Config msg = event_msg.config();
501*d9f75844SAndroid Build Coastguard Worker 
502*d9f75844SAndroid Build Coastguard Worker       fprintf(settings_file, "APM re-config at frame: %d\n", frame_count);
503*d9f75844SAndroid Build Coastguard Worker 
504*d9f75844SAndroid Build Coastguard Worker       PRINT_CONFIG(aec_enabled);
505*d9f75844SAndroid Build Coastguard Worker       PRINT_CONFIG(aec_delay_agnostic_enabled);
506*d9f75844SAndroid Build Coastguard Worker       PRINT_CONFIG(aec_drift_compensation_enabled);
507*d9f75844SAndroid Build Coastguard Worker       PRINT_CONFIG(aec_extended_filter_enabled);
508*d9f75844SAndroid Build Coastguard Worker       PRINT_CONFIG(aec_suppression_level);
509*d9f75844SAndroid Build Coastguard Worker       PRINT_CONFIG(aecm_enabled);
510*d9f75844SAndroid Build Coastguard Worker       PRINT_CONFIG(aecm_comfort_noise_enabled);
511*d9f75844SAndroid Build Coastguard Worker       PRINT_CONFIG(aecm_routing_mode);
512*d9f75844SAndroid Build Coastguard Worker       PRINT_CONFIG(agc_enabled);
513*d9f75844SAndroid Build Coastguard Worker       PRINT_CONFIG(agc_mode);
514*d9f75844SAndroid Build Coastguard Worker       PRINT_CONFIG(agc_limiter_enabled);
515*d9f75844SAndroid Build Coastguard Worker       PRINT_CONFIG(noise_robust_agc_enabled);
516*d9f75844SAndroid Build Coastguard Worker       PRINT_CONFIG(hpf_enabled);
517*d9f75844SAndroid Build Coastguard Worker       PRINT_CONFIG(ns_enabled);
518*d9f75844SAndroid Build Coastguard Worker       PRINT_CONFIG(ns_level);
519*d9f75844SAndroid Build Coastguard Worker       PRINT_CONFIG(transient_suppression_enabled);
520*d9f75844SAndroid Build Coastguard Worker       PRINT_CONFIG(pre_amplifier_enabled);
521*d9f75844SAndroid Build Coastguard Worker       PRINT_CONFIG_FLOAT(pre_amplifier_fixed_gain_factor);
522*d9f75844SAndroid Build Coastguard Worker 
523*d9f75844SAndroid Build Coastguard Worker       if (msg.has_experiments_description()) {
524*d9f75844SAndroid Build Coastguard Worker         fprintf(settings_file, "  experiments_description: %s\n",
525*d9f75844SAndroid Build Coastguard Worker                 msg.experiments_description().c_str());
526*d9f75844SAndroid Build Coastguard Worker       }
527*d9f75844SAndroid Build Coastguard Worker     } else if (event_msg.type() == Event::INIT) {
528*d9f75844SAndroid Build Coastguard Worker       if (!event_msg.has_init()) {
529*d9f75844SAndroid Build Coastguard Worker         printf("Corrupt input file: Init missing.\n");
530*d9f75844SAndroid Build Coastguard Worker         return 1;
531*d9f75844SAndroid Build Coastguard Worker       }
532*d9f75844SAndroid Build Coastguard Worker 
533*d9f75844SAndroid Build Coastguard Worker       ++init_count;
534*d9f75844SAndroid Build Coastguard Worker       const Init msg = event_msg.init();
535*d9f75844SAndroid Build Coastguard Worker       // These should print out zeros if they're missing.
536*d9f75844SAndroid Build Coastguard Worker       fprintf(settings_file, "Init #%d at frame: %d\n", init_count,
537*d9f75844SAndroid Build Coastguard Worker               frame_count);
538*d9f75844SAndroid Build Coastguard Worker       int input_sample_rate = msg.sample_rate();
539*d9f75844SAndroid Build Coastguard Worker       fprintf(settings_file, "  Input sample rate: %d\n", input_sample_rate);
540*d9f75844SAndroid Build Coastguard Worker       int output_sample_rate = msg.output_sample_rate();
541*d9f75844SAndroid Build Coastguard Worker       fprintf(settings_file, "  Output sample rate: %d\n", output_sample_rate);
542*d9f75844SAndroid Build Coastguard Worker       int reverse_sample_rate = msg.reverse_sample_rate();
543*d9f75844SAndroid Build Coastguard Worker       fprintf(settings_file, "  Reverse sample rate: %d\n",
544*d9f75844SAndroid Build Coastguard Worker               reverse_sample_rate);
545*d9f75844SAndroid Build Coastguard Worker       num_input_channels = msg.num_input_channels();
546*d9f75844SAndroid Build Coastguard Worker       fprintf(settings_file, "  Input channels: %zu\n", num_input_channels);
547*d9f75844SAndroid Build Coastguard Worker       num_output_channels = msg.num_output_channels();
548*d9f75844SAndroid Build Coastguard Worker       fprintf(settings_file, "  Output channels: %zu\n", num_output_channels);
549*d9f75844SAndroid Build Coastguard Worker       num_reverse_channels = msg.num_reverse_channels();
550*d9f75844SAndroid Build Coastguard Worker       fprintf(settings_file, "  Reverse channels: %zu\n", num_reverse_channels);
551*d9f75844SAndroid Build Coastguard Worker       if (msg.has_timestamp_ms()) {
552*d9f75844SAndroid Build Coastguard Worker         const int64_t timestamp = msg.timestamp_ms();
553*d9f75844SAndroid Build Coastguard Worker         fprintf(settings_file, "  Timestamp in millisecond: %" PRId64 "\n",
554*d9f75844SAndroid Build Coastguard Worker                 timestamp);
555*d9f75844SAndroid Build Coastguard Worker       }
556*d9f75844SAndroid Build Coastguard Worker 
557*d9f75844SAndroid Build Coastguard Worker       fprintf(settings_file, "\n");
558*d9f75844SAndroid Build Coastguard Worker 
559*d9f75844SAndroid Build Coastguard Worker       if (reverse_sample_rate == 0) {
560*d9f75844SAndroid Build Coastguard Worker         reverse_sample_rate = input_sample_rate;
561*d9f75844SAndroid Build Coastguard Worker       }
562*d9f75844SAndroid Build Coastguard Worker       if (output_sample_rate == 0) {
563*d9f75844SAndroid Build Coastguard Worker         output_sample_rate = input_sample_rate;
564*d9f75844SAndroid Build Coastguard Worker       }
565*d9f75844SAndroid Build Coastguard Worker 
566*d9f75844SAndroid Build Coastguard Worker       reverse_samples_per_channel =
567*d9f75844SAndroid Build Coastguard Worker           static_cast<size_t>(reverse_sample_rate / 100);
568*d9f75844SAndroid Build Coastguard Worker       input_samples_per_channel = static_cast<size_t>(input_sample_rate / 100);
569*d9f75844SAndroid Build Coastguard Worker       output_samples_per_channel =
570*d9f75844SAndroid Build Coastguard Worker           static_cast<size_t>(output_sample_rate / 100);
571*d9f75844SAndroid Build Coastguard Worker 
572*d9f75844SAndroid Build Coastguard Worker       if (!absl::GetFlag(FLAGS_raw)) {
573*d9f75844SAndroid Build Coastguard Worker         // The WAV files need to be reset every time, because they cant change
574*d9f75844SAndroid Build Coastguard Worker         // their sample rate or number of channels.
575*d9f75844SAndroid Build Coastguard Worker 
576*d9f75844SAndroid Build Coastguard Worker         std::string suffix = GetWavFileIndex(init_count, frame_count);
577*d9f75844SAndroid Build Coastguard Worker         rtc::StringBuilder reverse_name;
578*d9f75844SAndroid Build Coastguard Worker         reverse_name << absl::GetFlag(FLAGS_reverse_file) << suffix << ".wav";
579*d9f75844SAndroid Build Coastguard Worker         reverse_wav_file.reset(new WavWriter(
580*d9f75844SAndroid Build Coastguard Worker             reverse_name.str(), reverse_sample_rate, num_reverse_channels));
581*d9f75844SAndroid Build Coastguard Worker         rtc::StringBuilder input_name;
582*d9f75844SAndroid Build Coastguard Worker         input_name << absl::GetFlag(FLAGS_input_file) << suffix << ".wav";
583*d9f75844SAndroid Build Coastguard Worker         input_wav_file.reset(new WavWriter(input_name.str(), input_sample_rate,
584*d9f75844SAndroid Build Coastguard Worker                                            num_input_channels));
585*d9f75844SAndroid Build Coastguard Worker         rtc::StringBuilder output_name;
586*d9f75844SAndroid Build Coastguard Worker         output_name << absl::GetFlag(FLAGS_output_file) << suffix << ".wav";
587*d9f75844SAndroid Build Coastguard Worker         output_wav_file.reset(new WavWriter(
588*d9f75844SAndroid Build Coastguard Worker             output_name.str(), output_sample_rate, num_output_channels));
589*d9f75844SAndroid Build Coastguard Worker 
590*d9f75844SAndroid Build Coastguard Worker         if (WritingCallOrderFile()) {
591*d9f75844SAndroid Build Coastguard Worker           rtc::StringBuilder callorder_name;
592*d9f75844SAndroid Build Coastguard Worker           callorder_name << absl::GetFlag(FLAGS_callorder_file) << suffix
593*d9f75844SAndroid Build Coastguard Worker                          << ".char";
594*d9f75844SAndroid Build Coastguard Worker           callorder_char_file = OpenFile(callorder_name.str(), "wb");
595*d9f75844SAndroid Build Coastguard Worker         }
596*d9f75844SAndroid Build Coastguard Worker 
597*d9f75844SAndroid Build Coastguard Worker         if (WritingRuntimeSettingFiles()) {
598*d9f75844SAndroid Build Coastguard Worker           for (RuntimeSettingWriter& writer : runtime_setting_writers) {
599*d9f75844SAndroid Build Coastguard Worker             writer.HandleInitEvent(frame_count);
600*d9f75844SAndroid Build Coastguard Worker           }
601*d9f75844SAndroid Build Coastguard Worker         }
602*d9f75844SAndroid Build Coastguard Worker       }
603*d9f75844SAndroid Build Coastguard Worker     } else if (event_msg.type() == Event::RUNTIME_SETTING) {
604*d9f75844SAndroid Build Coastguard Worker       if (WritingRuntimeSettingFiles()) {
605*d9f75844SAndroid Build Coastguard Worker         for (RuntimeSettingWriter& writer : runtime_setting_writers) {
606*d9f75844SAndroid Build Coastguard Worker           if (writer.IsExporterFor(event_msg)) {
607*d9f75844SAndroid Build Coastguard Worker             writer.WriteEvent(event_msg, frame_count);
608*d9f75844SAndroid Build Coastguard Worker           }
609*d9f75844SAndroid Build Coastguard Worker         }
610*d9f75844SAndroid Build Coastguard Worker       }
611*d9f75844SAndroid Build Coastguard Worker     }
612*d9f75844SAndroid Build Coastguard Worker   }
613*d9f75844SAndroid Build Coastguard Worker 
614*d9f75844SAndroid Build Coastguard Worker   return 0;
615*d9f75844SAndroid Build Coastguard Worker }
616*d9f75844SAndroid Build Coastguard Worker 
617*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
618*d9f75844SAndroid Build Coastguard Worker 
main(int argc,char * argv[])619*d9f75844SAndroid Build Coastguard Worker int main(int argc, char* argv[]) {
620*d9f75844SAndroid Build Coastguard Worker   return webrtc::do_main(argc, argv);
621*d9f75844SAndroid Build Coastguard Worker }
622