1c55a96383497a772a307b346368133960b02ad03Eric Laurent/* 2c55a96383497a772a307b346368133960b02ad03Eric Laurent * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3c55a96383497a772a307b346368133960b02ad03Eric Laurent * 4c55a96383497a772a307b346368133960b02ad03Eric Laurent * Use of this source code is governed by a BSD-style license 5c55a96383497a772a307b346368133960b02ad03Eric Laurent * that can be found in the LICENSE file in the root of the source 6c55a96383497a772a307b346368133960b02ad03Eric Laurent * tree. An additional intellectual property rights grant can be found 7c55a96383497a772a307b346368133960b02ad03Eric Laurent * in the file PATENTS. All contributing project authors may 8c55a96383497a772a307b346368133960b02ad03Eric Laurent * be found in the AUTHORS file in the root of the source tree. 9c55a96383497a772a307b346368133960b02ad03Eric Laurent */ 10c55a96383497a772a307b346368133960b02ad03Eric Laurent 11c55a96383497a772a307b346368133960b02ad03Eric Laurent// Commandline tool to unpack audioproc debug files. 12c55a96383497a772a307b346368133960b02ad03Eric Laurent// 13c55a96383497a772a307b346368133960b02ad03Eric Laurent// The debug files are dumped as protobuf blobs. For analysis, it's necessary 14c55a96383497a772a307b346368133960b02ad03Eric Laurent// to unpack the file into its component parts: audio and other data. 15c55a96383497a772a307b346368133960b02ad03Eric Laurent 16c55a96383497a772a307b346368133960b02ad03Eric Laurent#include <stdio.h> 17c55a96383497a772a307b346368133960b02ad03Eric Laurent 18c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "google/gflags.h" 19c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "scoped_ptr.h" 20c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "typedefs.h" 21c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "webrtc/audio_processing/debug.pb.h" 22c55a96383497a772a307b346368133960b02ad03Eric Laurent 23c55a96383497a772a307b346368133960b02ad03Eric Laurentusing webrtc::scoped_array; 24c55a96383497a772a307b346368133960b02ad03Eric Laurent 25c55a96383497a772a307b346368133960b02ad03Eric Laurentusing webrtc::audioproc::Event; 26c55a96383497a772a307b346368133960b02ad03Eric Laurentusing webrtc::audioproc::ReverseStream; 27c55a96383497a772a307b346368133960b02ad03Eric Laurentusing webrtc::audioproc::Stream; 28c55a96383497a772a307b346368133960b02ad03Eric Laurentusing webrtc::audioproc::Init; 29c55a96383497a772a307b346368133960b02ad03Eric Laurent 30c55a96383497a772a307b346368133960b02ad03Eric Laurent// TODO(andrew): unpack more of the data. 31c55a96383497a772a307b346368133960b02ad03Eric LaurentDEFINE_string(input_file, "input.pcm", "The name of the input stream file."); 32c55a96383497a772a307b346368133960b02ad03Eric LaurentDEFINE_string(output_file, "ref_out.pcm", 33c55a96383497a772a307b346368133960b02ad03Eric Laurent "The name of the reference output stream file."); 34c55a96383497a772a307b346368133960b02ad03Eric LaurentDEFINE_string(reverse_file, "reverse.pcm", 35c55a96383497a772a307b346368133960b02ad03Eric Laurent "The name of the reverse input stream file."); 36c55a96383497a772a307b346368133960b02ad03Eric LaurentDEFINE_string(delay_file, "delay.int32", "The name of the delay file."); 37c55a96383497a772a307b346368133960b02ad03Eric LaurentDEFINE_string(drift_file, "drift.int32", "The name of the drift file."); 38c55a96383497a772a307b346368133960b02ad03Eric LaurentDEFINE_string(level_file, "level.int32", "The name of the level file."); 39c55a96383497a772a307b346368133960b02ad03Eric LaurentDEFINE_string(settings_file, "settings.txt", "The name of the settings file."); 40c55a96383497a772a307b346368133960b02ad03Eric LaurentDEFINE_bool(full, false, 41c55a96383497a772a307b346368133960b02ad03Eric Laurent "Unpack the full set of files (normally not needed)."); 42c55a96383497a772a307b346368133960b02ad03Eric Laurent 43c55a96383497a772a307b346368133960b02ad03Eric Laurent// TODO(andrew): move this to a helper class to share with process_test.cc? 44c55a96383497a772a307b346368133960b02ad03Eric Laurent// Returns true on success, false on error or end-of-file. 45c55a96383497a772a307b346368133960b02ad03Eric Laurentbool ReadMessageFromFile(FILE* file, 46c55a96383497a772a307b346368133960b02ad03Eric Laurent ::google::protobuf::MessageLite* msg) { 47c55a96383497a772a307b346368133960b02ad03Eric Laurent // The "wire format" for the size is little-endian. 48c55a96383497a772a307b346368133960b02ad03Eric Laurent // Assume process_test is running on a little-endian machine. 49c55a96383497a772a307b346368133960b02ad03Eric Laurent int32_t size = 0; 50c55a96383497a772a307b346368133960b02ad03Eric Laurent if (fread(&size, sizeof(int32_t), 1, file) != 1) { 51c55a96383497a772a307b346368133960b02ad03Eric Laurent return false; 52c55a96383497a772a307b346368133960b02ad03Eric Laurent } 53c55a96383497a772a307b346368133960b02ad03Eric Laurent if (size <= 0) { 54c55a96383497a772a307b346368133960b02ad03Eric Laurent return false; 55c55a96383497a772a307b346368133960b02ad03Eric Laurent } 56c55a96383497a772a307b346368133960b02ad03Eric Laurent const size_t usize = static_cast<size_t>(size); 57c55a96383497a772a307b346368133960b02ad03Eric Laurent 58c55a96383497a772a307b346368133960b02ad03Eric Laurent scoped_array<char> array(new char[usize]); 59c55a96383497a772a307b346368133960b02ad03Eric Laurent if (fread(array.get(), sizeof(char), usize, file) != usize) { 60c55a96383497a772a307b346368133960b02ad03Eric Laurent return false; 61c55a96383497a772a307b346368133960b02ad03Eric Laurent } 62c55a96383497a772a307b346368133960b02ad03Eric Laurent 63c55a96383497a772a307b346368133960b02ad03Eric Laurent msg->Clear(); 64c55a96383497a772a307b346368133960b02ad03Eric Laurent return msg->ParseFromArray(array.get(), usize); 65c55a96383497a772a307b346368133960b02ad03Eric Laurent} 66c55a96383497a772a307b346368133960b02ad03Eric Laurent 67c55a96383497a772a307b346368133960b02ad03Eric Laurentint main(int argc, char* argv[]) { 68c55a96383497a772a307b346368133960b02ad03Eric Laurent std::string program_name = argv[0]; 69c55a96383497a772a307b346368133960b02ad03Eric Laurent std::string usage = "Commandline tool to unpack audioproc debug files.\n" 70c55a96383497a772a307b346368133960b02ad03Eric Laurent "Example usage:\n" + program_name + " debug_dump.pb\n"; 71c55a96383497a772a307b346368133960b02ad03Eric Laurent google::SetUsageMessage(usage); 72c55a96383497a772a307b346368133960b02ad03Eric Laurent google::ParseCommandLineFlags(&argc, &argv, true); 73c55a96383497a772a307b346368133960b02ad03Eric Laurent 74c55a96383497a772a307b346368133960b02ad03Eric Laurent if (argc < 2) { 75c55a96383497a772a307b346368133960b02ad03Eric Laurent printf("%s", google::ProgramUsage()); 76c55a96383497a772a307b346368133960b02ad03Eric Laurent return 1; 77c55a96383497a772a307b346368133960b02ad03Eric Laurent } 78c55a96383497a772a307b346368133960b02ad03Eric Laurent 79c55a96383497a772a307b346368133960b02ad03Eric Laurent FILE* debug_file = fopen(argv[1], "rb"); 80c55a96383497a772a307b346368133960b02ad03Eric Laurent if (debug_file == NULL) { 81c55a96383497a772a307b346368133960b02ad03Eric Laurent printf("Unable to open %s\n", argv[1]); 82c55a96383497a772a307b346368133960b02ad03Eric Laurent return 1; 83c55a96383497a772a307b346368133960b02ad03Eric Laurent } 84c55a96383497a772a307b346368133960b02ad03Eric Laurent FILE* input_file = fopen(FLAGS_input_file.c_str(), "wb"); 85c55a96383497a772a307b346368133960b02ad03Eric Laurent if (input_file == NULL) { 86c55a96383497a772a307b346368133960b02ad03Eric Laurent printf("Unable to open %s\n", FLAGS_input_file.c_str()); 87c55a96383497a772a307b346368133960b02ad03Eric Laurent return 1; 88c55a96383497a772a307b346368133960b02ad03Eric Laurent } 89c55a96383497a772a307b346368133960b02ad03Eric Laurent FILE* output_file = fopen(FLAGS_output_file.c_str(), "wb"); 90c55a96383497a772a307b346368133960b02ad03Eric Laurent if (output_file == NULL) { 91c55a96383497a772a307b346368133960b02ad03Eric Laurent printf("Unable to open %s\n", FLAGS_output_file.c_str()); 92c55a96383497a772a307b346368133960b02ad03Eric Laurent return 1; 93c55a96383497a772a307b346368133960b02ad03Eric Laurent } 94c55a96383497a772a307b346368133960b02ad03Eric Laurent FILE* reverse_file = fopen(FLAGS_reverse_file.c_str(), "wb"); 95c55a96383497a772a307b346368133960b02ad03Eric Laurent if (reverse_file == NULL) { 96c55a96383497a772a307b346368133960b02ad03Eric Laurent printf("Unable to open %s\n", FLAGS_reverse_file.c_str()); 97c55a96383497a772a307b346368133960b02ad03Eric Laurent return 1; 98c55a96383497a772a307b346368133960b02ad03Eric Laurent } 99c55a96383497a772a307b346368133960b02ad03Eric Laurent FILE* settings_file = fopen(FLAGS_settings_file.c_str(), "wb"); 100c55a96383497a772a307b346368133960b02ad03Eric Laurent if (settings_file == NULL) { 101c55a96383497a772a307b346368133960b02ad03Eric Laurent printf("Unable to open %s\n", FLAGS_settings_file.c_str()); 102c55a96383497a772a307b346368133960b02ad03Eric Laurent return 1; 103c55a96383497a772a307b346368133960b02ad03Eric Laurent } 104c55a96383497a772a307b346368133960b02ad03Eric Laurent 105c55a96383497a772a307b346368133960b02ad03Eric Laurent FILE* delay_file = NULL; 106c55a96383497a772a307b346368133960b02ad03Eric Laurent FILE* drift_file = NULL; 107c55a96383497a772a307b346368133960b02ad03Eric Laurent FILE* level_file = NULL; 108c55a96383497a772a307b346368133960b02ad03Eric Laurent if (FLAGS_full) { 109c55a96383497a772a307b346368133960b02ad03Eric Laurent delay_file = fopen(FLAGS_delay_file.c_str(), "wb"); 110c55a96383497a772a307b346368133960b02ad03Eric Laurent if (delay_file == NULL) { 111c55a96383497a772a307b346368133960b02ad03Eric Laurent printf("Unable to open %s\n", FLAGS_delay_file.c_str()); 112c55a96383497a772a307b346368133960b02ad03Eric Laurent return 1; 113c55a96383497a772a307b346368133960b02ad03Eric Laurent } 114c55a96383497a772a307b346368133960b02ad03Eric Laurent drift_file = fopen(FLAGS_drift_file.c_str(), "wb"); 115c55a96383497a772a307b346368133960b02ad03Eric Laurent if (drift_file == NULL) { 116c55a96383497a772a307b346368133960b02ad03Eric Laurent printf("Unable to open %s\n", FLAGS_drift_file.c_str()); 117c55a96383497a772a307b346368133960b02ad03Eric Laurent return 1; 118c55a96383497a772a307b346368133960b02ad03Eric Laurent } 119c55a96383497a772a307b346368133960b02ad03Eric Laurent level_file = fopen(FLAGS_level_file.c_str(), "wb"); 120c55a96383497a772a307b346368133960b02ad03Eric Laurent if (level_file == NULL) { 121c55a96383497a772a307b346368133960b02ad03Eric Laurent printf("Unable to open %s\n", FLAGS_level_file.c_str()); 122c55a96383497a772a307b346368133960b02ad03Eric Laurent return 1; 123c55a96383497a772a307b346368133960b02ad03Eric Laurent } 124c55a96383497a772a307b346368133960b02ad03Eric Laurent } 125c55a96383497a772a307b346368133960b02ad03Eric Laurent 126c55a96383497a772a307b346368133960b02ad03Eric Laurent Event event_msg; 127c55a96383497a772a307b346368133960b02ad03Eric Laurent int frame_count = 0; 128c55a96383497a772a307b346368133960b02ad03Eric Laurent while (ReadMessageFromFile(debug_file, &event_msg)) { 129c55a96383497a772a307b346368133960b02ad03Eric Laurent if (event_msg.type() == Event::REVERSE_STREAM) { 130c55a96383497a772a307b346368133960b02ad03Eric Laurent if (!event_msg.has_reverse_stream()) { 131c55a96383497a772a307b346368133960b02ad03Eric Laurent printf("Corrupted input file: ReverseStream missing.\n"); 132c55a96383497a772a307b346368133960b02ad03Eric Laurent return 1; 133c55a96383497a772a307b346368133960b02ad03Eric Laurent } 134c55a96383497a772a307b346368133960b02ad03Eric Laurent 135c55a96383497a772a307b346368133960b02ad03Eric Laurent const ReverseStream msg = event_msg.reverse_stream(); 136c55a96383497a772a307b346368133960b02ad03Eric Laurent if (msg.has_data()) { 137c55a96383497a772a307b346368133960b02ad03Eric Laurent if (fwrite(msg.data().data(), msg.data().size(), 1, reverse_file) != 138c55a96383497a772a307b346368133960b02ad03Eric Laurent 1) { 139c55a96383497a772a307b346368133960b02ad03Eric Laurent printf("Error when writing to %s\n", FLAGS_reverse_file.c_str()); 140c55a96383497a772a307b346368133960b02ad03Eric Laurent return 1; 141c55a96383497a772a307b346368133960b02ad03Eric Laurent } 142c55a96383497a772a307b346368133960b02ad03Eric Laurent } 143c55a96383497a772a307b346368133960b02ad03Eric Laurent } else if (event_msg.type() == Event::STREAM) { 144c55a96383497a772a307b346368133960b02ad03Eric Laurent frame_count++; 145c55a96383497a772a307b346368133960b02ad03Eric Laurent if (!event_msg.has_stream()) { 146c55a96383497a772a307b346368133960b02ad03Eric Laurent printf("Corrupted input file: Stream missing.\n"); 147c55a96383497a772a307b346368133960b02ad03Eric Laurent return 1; 148c55a96383497a772a307b346368133960b02ad03Eric Laurent } 149c55a96383497a772a307b346368133960b02ad03Eric Laurent 150c55a96383497a772a307b346368133960b02ad03Eric Laurent const Stream msg = event_msg.stream(); 151c55a96383497a772a307b346368133960b02ad03Eric Laurent if (msg.has_input_data()) { 152c55a96383497a772a307b346368133960b02ad03Eric Laurent if (fwrite(msg.input_data().data(), msg.input_data().size(), 1, 153c55a96383497a772a307b346368133960b02ad03Eric Laurent input_file) != 1) { 154c55a96383497a772a307b346368133960b02ad03Eric Laurent printf("Error when writing to %s\n", FLAGS_input_file.c_str()); 155c55a96383497a772a307b346368133960b02ad03Eric Laurent return 1; 156c55a96383497a772a307b346368133960b02ad03Eric Laurent } 157c55a96383497a772a307b346368133960b02ad03Eric Laurent } 158c55a96383497a772a307b346368133960b02ad03Eric Laurent 159c55a96383497a772a307b346368133960b02ad03Eric Laurent if (msg.has_output_data()) { 160c55a96383497a772a307b346368133960b02ad03Eric Laurent if (fwrite(msg.output_data().data(), msg.output_data().size(), 1, 161c55a96383497a772a307b346368133960b02ad03Eric Laurent output_file) != 1) { 162c55a96383497a772a307b346368133960b02ad03Eric Laurent printf("Error when writing to %s\n", FLAGS_output_file.c_str()); 163c55a96383497a772a307b346368133960b02ad03Eric Laurent return 1; 164c55a96383497a772a307b346368133960b02ad03Eric Laurent } 165c55a96383497a772a307b346368133960b02ad03Eric Laurent } 166c55a96383497a772a307b346368133960b02ad03Eric Laurent 167c55a96383497a772a307b346368133960b02ad03Eric Laurent if (FLAGS_full) { 168c55a96383497a772a307b346368133960b02ad03Eric Laurent if (msg.has_delay()) { 169c55a96383497a772a307b346368133960b02ad03Eric Laurent int32_t delay = msg.delay(); 170c55a96383497a772a307b346368133960b02ad03Eric Laurent if (fwrite(&delay, sizeof(int32_t), 1, delay_file) != 1) { 171c55a96383497a772a307b346368133960b02ad03Eric Laurent printf("Error when writing to %s\n", FLAGS_delay_file.c_str()); 172c55a96383497a772a307b346368133960b02ad03Eric Laurent return 1; 173c55a96383497a772a307b346368133960b02ad03Eric Laurent } 174c55a96383497a772a307b346368133960b02ad03Eric Laurent } 175c55a96383497a772a307b346368133960b02ad03Eric Laurent 176c55a96383497a772a307b346368133960b02ad03Eric Laurent if (msg.has_drift()) { 177c55a96383497a772a307b346368133960b02ad03Eric Laurent int32_t drift = msg.drift(); 178c55a96383497a772a307b346368133960b02ad03Eric Laurent if (fwrite(&drift, sizeof(int32_t), 1, drift_file) != 1) { 179c55a96383497a772a307b346368133960b02ad03Eric Laurent printf("Error when writing to %s\n", FLAGS_drift_file.c_str()); 180c55a96383497a772a307b346368133960b02ad03Eric Laurent return 1; 181c55a96383497a772a307b346368133960b02ad03Eric Laurent } 182c55a96383497a772a307b346368133960b02ad03Eric Laurent } 183c55a96383497a772a307b346368133960b02ad03Eric Laurent 184c55a96383497a772a307b346368133960b02ad03Eric Laurent if (msg.has_level()) { 185c55a96383497a772a307b346368133960b02ad03Eric Laurent int32_t level = msg.level(); 186c55a96383497a772a307b346368133960b02ad03Eric Laurent if (fwrite(&level, sizeof(int32_t), 1, level_file) != 1) { 187c55a96383497a772a307b346368133960b02ad03Eric Laurent printf("Error when writing to %s\n", FLAGS_level_file.c_str()); 188c55a96383497a772a307b346368133960b02ad03Eric Laurent return 1; 189c55a96383497a772a307b346368133960b02ad03Eric Laurent } 190c55a96383497a772a307b346368133960b02ad03Eric Laurent } 191c55a96383497a772a307b346368133960b02ad03Eric Laurent } 192c55a96383497a772a307b346368133960b02ad03Eric Laurent } else if (event_msg.type() == Event::INIT) { 193c55a96383497a772a307b346368133960b02ad03Eric Laurent if (!event_msg.has_init()) { 194c55a96383497a772a307b346368133960b02ad03Eric Laurent printf("Corrupted input file: Init missing.\n"); 195c55a96383497a772a307b346368133960b02ad03Eric Laurent return 1; 196c55a96383497a772a307b346368133960b02ad03Eric Laurent } 197c55a96383497a772a307b346368133960b02ad03Eric Laurent 198c55a96383497a772a307b346368133960b02ad03Eric Laurent const Init msg = event_msg.init(); 199c55a96383497a772a307b346368133960b02ad03Eric Laurent // These should print out zeros if they're missing. 200c55a96383497a772a307b346368133960b02ad03Eric Laurent fprintf(settings_file, "Init at frame: %d\n", frame_count); 201c55a96383497a772a307b346368133960b02ad03Eric Laurent fprintf(settings_file, " Sample rate: %d\n", msg.sample_rate()); 202c55a96383497a772a307b346368133960b02ad03Eric Laurent fprintf(settings_file, " Device sample rate: %d\n", 203c55a96383497a772a307b346368133960b02ad03Eric Laurent msg.device_sample_rate()); 204c55a96383497a772a307b346368133960b02ad03Eric Laurent fprintf(settings_file, " Input channels: %d\n", 205c55a96383497a772a307b346368133960b02ad03Eric Laurent msg.num_input_channels()); 206c55a96383497a772a307b346368133960b02ad03Eric Laurent fprintf(settings_file, " Output channels: %d\n", 207c55a96383497a772a307b346368133960b02ad03Eric Laurent msg.num_output_channels()); 208c55a96383497a772a307b346368133960b02ad03Eric Laurent fprintf(settings_file, " Reverse channels: %d\n", 209c55a96383497a772a307b346368133960b02ad03Eric Laurent msg.num_reverse_channels()); 210c55a96383497a772a307b346368133960b02ad03Eric Laurent 211c55a96383497a772a307b346368133960b02ad03Eric Laurent fprintf(settings_file, "\n"); 212c55a96383497a772a307b346368133960b02ad03Eric Laurent } 213c55a96383497a772a307b346368133960b02ad03Eric Laurent } 214c55a96383497a772a307b346368133960b02ad03Eric Laurent 215c55a96383497a772a307b346368133960b02ad03Eric Laurent return 0; 216c55a96383497a772a307b346368133960b02ad03Eric Laurent} 217