blob: 27c704bd2039863b575a6e76a76481aeb1cfda45 [file] [log] [blame]
andrew@webrtc.org08df9b22014-12-16 20:57:15 +00001/*
2 * Copyright (c) 2014 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#include <stdio.h>
andrewbdafe312015-10-29 23:42:54 -070012#include <iostream>
mgraczyk@chromium.org4ddde2e2015-01-29 22:39:44 +000013#include <sstream>
mgraczyk@chromium.org5a92b782015-01-15 01:28:36 +000014#include <string>
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000015
16#include "gflags/gflags.h"
17#include "webrtc/base/checks.h"
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +000018#include "webrtc/base/scoped_ptr.h"
kjellander@webrtc.org035e9122015-01-28 19:57:00 +000019#include "webrtc/common_audio/channel_buffer.h"
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000020#include "webrtc/common_audio/wav_file.h"
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000021#include "webrtc/modules/audio_processing/include/audio_processing.h"
andrewbdafe312015-10-29 23:42:54 -070022#include "webrtc/modules/audio_processing/test/audio_file_processor.h"
Andrew MacDonaldcb05b722015-05-07 22:17:51 -070023#include "webrtc/modules/audio_processing/test/protobuf_utils.h"
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000024#include "webrtc/modules/audio_processing/test/test_utils.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010025#include "webrtc/system_wrappers/include/tick_util.h"
Andrew MacDonaldb444b3f2015-05-27 17:26:03 -070026#include "webrtc/test/testsupport/trace_to_stderr.h"
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000027
andrewbdafe312015-10-29 23:42:54 -070028DEFINE_string(dump, "", "Name of the aecdump debug file to read from.");
29DEFINE_string(i, "", "Name of the capture input stream file to read from.");
30DEFINE_string(
31 o,
32 "out.wav",
33 "Name of the output file to write the processed capture stream to.");
34DEFINE_int32(out_channels, 1, "Number of output channels.");
35DEFINE_int32(out_sample_rate, 48000, "Output sample rate in Hz.");
mgraczyk@chromium.org4ddde2e2015-01-29 22:39:44 +000036DEFINE_string(mic_positions, "",
37 "Space delimited cartesian coordinates of microphones in meters. "
38 "The coordinates of each point are contiguous. "
39 "For a two element array: \"x1 y1 z1 x2 y2 z2\"");
andrewbdafe312015-10-29 23:42:54 -070040DEFINE_double(
41 target_angle_degrees,
42 90,
43 "The azimuth of the target in degrees. Only applies to beamforming.");
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000044
45DEFINE_bool(aec, false, "Enable echo cancellation.");
46DEFINE_bool(agc, false, "Enable automatic gain control.");
47DEFINE_bool(hpf, false, "Enable high-pass filtering.");
48DEFINE_bool(ns, false, "Enable noise suppression.");
49DEFINE_bool(ts, false, "Enable transient suppression.");
mgraczyk@chromium.org5a92b782015-01-15 01:28:36 +000050DEFINE_bool(bf, false, "Enable beamforming.");
ekmeyerson60d9b332015-08-14 10:35:55 -070051DEFINE_bool(ie, false, "Enable intelligibility enhancer.");
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000052DEFINE_bool(all, false, "Enable all components.");
53
54DEFINE_int32(ns_level, -1, "Noise suppression level [0 - 3].");
55
Alejandro Luebs5d22c002015-04-15 11:26:40 -070056DEFINE_bool(perf, false, "Enable performance tests.");
57
Andrew MacDonaldcb05b722015-05-07 22:17:51 -070058namespace webrtc {
59namespace {
60
61const int kChunksPerSecond = 100;
62const char kUsage[] =
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000063 "Command-line tool to run audio processing on WAV files. Accepts either\n"
64 "an input capture WAV file or protobuf debug dump and writes to an output\n"
65 "WAV file.\n"
66 "\n"
67 "All components are disabled by default. If any bi-directional components\n"
68 "are enabled, only debug dump files are permitted.";
69
mgraczyk@chromium.org4ddde2e2015-01-29 22:39:44 +000070} // namespace
71
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000072int main(int argc, char* argv[]) {
Andrew MacDonaldcb05b722015-05-07 22:17:51 -070073 google::SetUsageMessage(kUsage);
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000074 google::ParseCommandLineFlags(&argc, &argv, true);
75
pbosbb36fdf2015-07-09 07:48:14 -070076 if (!((FLAGS_i.empty()) ^ (FLAGS_dump.empty()))) {
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000077 fprintf(stderr,
Andrew MacDonaldcb05b722015-05-07 22:17:51 -070078 "An input file must be specified with either -i or -dump.\n");
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000079 return 1;
80 }
andrewbdafe312015-10-29 23:42:54 -070081 if (FLAGS_dump.empty() && (FLAGS_aec || FLAGS_ie)) {
82 fprintf(stderr, "-aec and -ie require a -dump file.\n");
83 return 1;
84 }
85 if (FLAGS_ie) {
86 fprintf(stderr,
87 "FIXME(ajm): The intelligibility enhancer output is not dumped.\n");
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000088 return 1;
89 }
90
Andrew MacDonaldb444b3f2015-05-27 17:26:03 -070091 test::TraceToStderr trace_to_stderr(true);
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000092 Config config;
mgraczyk@chromium.org5a92b782015-01-15 01:28:36 +000093 if (FLAGS_bf || FLAGS_all) {
andrewbdafe312015-10-29 23:42:54 -070094 if (FLAGS_mic_positions.empty()) {
95 fprintf(stderr, "-mic_positions must be specified when -bf is used.\n");
96 return 1;
97 }
Alejandro Luebscb3f9bd2015-10-29 18:21:34 -070098 config.Set<Beamforming>(new Beamforming(
andrewbdafe312015-10-29 23:42:54 -070099 true, ParseArrayGeometry(FLAGS_mic_positions),
Alejandro Luebscb3f9bd2015-10-29 18:21:34 -0700100 SphericalPointf(DegreesToRadians(FLAGS_target_angle_degrees), 0.f,
101 1.f)));
mgraczyk@chromium.org5a92b782015-01-15 01:28:36 +0000102 }
andrewbdafe312015-10-29 23:42:54 -0700103 config.Set<ExperimentalNs>(new ExperimentalNs(FLAGS_ts || FLAGS_all));
104 config.Set<Intelligibility>(new Intelligibility(FLAGS_ie || FLAGS_all));
mgraczyk@chromium.org5a92b782015-01-15 01:28:36 +0000105
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000106 rtc::scoped_ptr<AudioProcessing> ap(AudioProcessing::Create(config));
andrewbdafe312015-10-29 23:42:54 -0700107 RTC_CHECK_EQ(kNoErr, ap->echo_cancellation()->Enable(FLAGS_aec || FLAGS_all));
henrikg91d6ede2015-09-17 00:24:34 -0700108 RTC_CHECK_EQ(kNoErr, ap->gain_control()->Enable(FLAGS_agc || FLAGS_all));
henrikg91d6ede2015-09-17 00:24:34 -0700109 RTC_CHECK_EQ(kNoErr, ap->high_pass_filter()->Enable(FLAGS_hpf || FLAGS_all));
110 RTC_CHECK_EQ(kNoErr, ap->noise_suppression()->Enable(FLAGS_ns || FLAGS_all));
andrewbdafe312015-10-29 23:42:54 -0700111 if (FLAGS_ns_level != -1) {
henrikg91d6ede2015-09-17 00:24:34 -0700112 RTC_CHECK_EQ(kNoErr,
113 ap->noise_suppression()->set_level(
114 static_cast<NoiseSuppression::Level>(FLAGS_ns_level)));
ekmeyerson60d9b332015-08-14 10:35:55 -0700115 }
116
andrewbdafe312015-10-29 23:42:54 -0700117 rtc::scoped_ptr<AudioFileProcessor> processor;
118 auto out_file = rtc_make_scoped_ptr(
119 new WavWriter(FLAGS_o, FLAGS_out_sample_rate, FLAGS_out_channels));
120 std::cout << FLAGS_o << ": " << out_file->FormatAsString() << std::endl;
121 if (FLAGS_dump.empty()) {
122 auto in_file = rtc_make_scoped_ptr(new WavReader(FLAGS_i));
123 std::cout << FLAGS_i << ": " << in_file->FormatAsString() << std::endl;
124 processor.reset(
125 new WavFileProcessor(ap.Pass(), in_file.Pass(), out_file.Pass()));
126
127 } else {
128 processor.reset(new AecDumpFileProcessor(
129 ap.Pass(), fopen(FLAGS_dump.c_str(), "rb"), out_file.Pass()));
130 }
131
Alejandro Luebs5d22c002015-04-15 11:26:40 -0700132 int num_chunks = 0;
andrewbdafe312015-10-29 23:42:54 -0700133 while (processor->ProcessChunk()) {
Andrew MacDonaldb444b3f2015-05-27 17:26:03 -0700134 trace_to_stderr.SetTimeSeconds(num_chunks * 1.f / kChunksPerSecond);
andrewbdafe312015-10-29 23:42:54 -0700135 ++num_chunks;
andrew@webrtc.org08df9b22014-12-16 20:57:15 +0000136 }
andrewbdafe312015-10-29 23:42:54 -0700137
Alejandro Luebs5d22c002015-04-15 11:26:40 -0700138 if (FLAGS_perf) {
andrewbdafe312015-10-29 23:42:54 -0700139 const auto& proc_time = processor->proc_time();
140 int64_t exec_time_us = proc_time.sum.Microseconds();
141 printf(
142 "\nExecution time: %.3f s, File time: %.2f s\n"
143 "Time per chunk (mean, max, min):\n%.0f us, %.0f us, %.0f us\n",
144 exec_time_us * 1e-6, num_chunks * 1.f / kChunksPerSecond,
145 exec_time_us * 1.f / num_chunks, 1.f * proc_time.max.Microseconds(),
146 1.f * proc_time.min.Microseconds());
Alejandro Luebs5d22c002015-04-15 11:26:40 -0700147 }
andrewbdafe312015-10-29 23:42:54 -0700148
andrew@webrtc.org08df9b22014-12-16 20:57:15 +0000149 return 0;
150}
151
152} // namespace webrtc
153
154int main(int argc, char* argv[]) {
155 return webrtc::main(argc, argv);
156}