blob: d64b006b8e740fe4cfd2625c47db914a18a41473 [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>
aluebsb0ad43b2015-11-20 00:11:53 -080012#include <iostream>
mgraczyk@chromium.org4ddde2e2015-01-29 22:39:44 +000013#include <sstream>
mgraczyk@chromium.org5a92b782015-01-15 01:28:36 +000014#include <string>
kwiberg0eb15ed2015-12-17 03:04:15 -080015#include <utility>
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000016
17#include "gflags/gflags.h"
18#include "webrtc/base/checks.h"
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +000019#include "webrtc/base/scoped_ptr.h"
kjellander@webrtc.org035e9122015-01-28 19:57:00 +000020#include "webrtc/common_audio/channel_buffer.h"
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000021#include "webrtc/common_audio/wav_file.h"
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000022#include "webrtc/modules/audio_processing/include/audio_processing.h"
aluebsb0ad43b2015-11-20 00:11:53 -080023#include "webrtc/modules/audio_processing/test/audio_file_processor.h"
Andrew MacDonaldcb05b722015-05-07 22:17:51 -070024#include "webrtc/modules/audio_processing/test/protobuf_utils.h"
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000025#include "webrtc/modules/audio_processing/test/test_utils.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010026#include "webrtc/system_wrappers/include/tick_util.h"
Andrew MacDonaldb444b3f2015-05-27 17:26:03 -070027#include "webrtc/test/testsupport/trace_to_stderr.h"
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000028
aluebsb0ad43b2015-11-20 00:11:53 -080029DEFINE_string(dump, "", "Name of the aecdump debug file to read from.");
30DEFINE_string(i, "", "Name of the capture input stream file to read from.");
31DEFINE_string(
32 o,
33 "out.wav",
34 "Name of the output file to write the processed capture stream to.");
35DEFINE_int32(out_channels, 1, "Number of output channels.");
36DEFINE_int32(out_sample_rate, 48000, "Output sample rate in Hz.");
mgraczyk@chromium.org4ddde2e2015-01-29 22:39:44 +000037DEFINE_string(mic_positions, "",
38 "Space delimited cartesian coordinates of microphones in meters. "
39 "The coordinates of each point are contiguous. "
40 "For a two element array: \"x1 y1 z1 x2 y2 z2\"");
aluebsb0ad43b2015-11-20 00:11:53 -080041DEFINE_double(
42 target_angle_degrees,
43 90,
44 "The azimuth of the target in degrees. Only applies to beamforming.");
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000045
46DEFINE_bool(aec, false, "Enable echo cancellation.");
47DEFINE_bool(agc, false, "Enable automatic gain control.");
48DEFINE_bool(hpf, false, "Enable high-pass filtering.");
49DEFINE_bool(ns, false, "Enable noise suppression.");
50DEFINE_bool(ts, false, "Enable transient suppression.");
mgraczyk@chromium.org5a92b782015-01-15 01:28:36 +000051DEFINE_bool(bf, false, "Enable beamforming.");
ekmeyerson60d9b332015-08-14 10:35:55 -070052DEFINE_bool(ie, false, "Enable intelligibility enhancer.");
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000053DEFINE_bool(all, false, "Enable all components.");
54
55DEFINE_int32(ns_level, -1, "Noise suppression level [0 - 3].");
56
Alejandro Luebs5d22c002015-04-15 11:26:40 -070057DEFINE_bool(perf, false, "Enable performance tests.");
58
Andrew MacDonaldcb05b722015-05-07 22:17:51 -070059namespace webrtc {
60namespace {
61
62const int kChunksPerSecond = 100;
63const char kUsage[] =
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000064 "Command-line tool to run audio processing on WAV files. Accepts either\n"
65 "an input capture WAV file or protobuf debug dump and writes to an output\n"
66 "WAV file.\n"
67 "\n"
68 "All components are disabled by default. If any bi-directional components\n"
69 "are enabled, only debug dump files are permitted.";
70
mgraczyk@chromium.org4ddde2e2015-01-29 22:39:44 +000071} // namespace
72
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000073int main(int argc, char* argv[]) {
Andrew MacDonaldcb05b722015-05-07 22:17:51 -070074 google::SetUsageMessage(kUsage);
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000075 google::ParseCommandLineFlags(&argc, &argv, true);
76
pbosbb36fdf2015-07-09 07:48:14 -070077 if (!((FLAGS_i.empty()) ^ (FLAGS_dump.empty()))) {
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000078 fprintf(stderr,
Andrew MacDonaldcb05b722015-05-07 22:17:51 -070079 "An input file must be specified with either -i or -dump.\n");
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000080 return 1;
81 }
aluebsb0ad43b2015-11-20 00:11:53 -080082 if (FLAGS_dump.empty() && (FLAGS_aec || FLAGS_ie)) {
83 fprintf(stderr, "-aec and -ie require a -dump file.\n");
84 return 1;
85 }
86 if (FLAGS_ie) {
87 fprintf(stderr,
88 "FIXME(ajm): The intelligibility enhancer output is not dumped.\n");
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000089 return 1;
90 }
91
Andrew MacDonaldb444b3f2015-05-27 17:26:03 -070092 test::TraceToStderr trace_to_stderr(true);
andrew@webrtc.org08df9b22014-12-16 20:57:15 +000093 Config config;
kjellanderb7a5c162015-11-05 12:33:18 -080094 if (FLAGS_bf || FLAGS_all) {
aluebsb0ad43b2015-11-20 00:11:53 -080095 if (FLAGS_mic_positions.empty()) {
96 fprintf(stderr, "-mic_positions must be specified when -bf is used.\n");
97 return 1;
98 }
kjellanderb7a5c162015-11-05 12:33:18 -080099 config.Set<Beamforming>(new Beamforming(
aluebsb0ad43b2015-11-20 00:11:53 -0800100 true, ParseArrayGeometry(FLAGS_mic_positions),
kjellanderb7a5c162015-11-05 12:33:18 -0800101 SphericalPointf(DegreesToRadians(FLAGS_target_angle_degrees), 0.f,
102 1.f)));
103 }
aluebsb0ad43b2015-11-20 00:11:53 -0800104 config.Set<ExperimentalNs>(new ExperimentalNs(FLAGS_ts || FLAGS_all));
105 config.Set<Intelligibility>(new Intelligibility(FLAGS_ie || FLAGS_all));
kjellanderb7a5c162015-11-05 12:33:18 -0800106
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000107 rtc::scoped_ptr<AudioProcessing> ap(AudioProcessing::Create(config));
aluebsb0ad43b2015-11-20 00:11:53 -0800108 RTC_CHECK_EQ(kNoErr, ap->echo_cancellation()->Enable(FLAGS_aec || FLAGS_all));
henrikg91d6ede2015-09-17 00:24:34 -0700109 RTC_CHECK_EQ(kNoErr, ap->gain_control()->Enable(FLAGS_agc || FLAGS_all));
henrikg91d6ede2015-09-17 00:24:34 -0700110 RTC_CHECK_EQ(kNoErr, ap->high_pass_filter()->Enable(FLAGS_hpf || FLAGS_all));
111 RTC_CHECK_EQ(kNoErr, ap->noise_suppression()->Enable(FLAGS_ns || FLAGS_all));
kjellander86b40502015-11-05 06:23:02 -0800112 if (FLAGS_ns_level != -1) {
henrikg91d6ede2015-09-17 00:24:34 -0700113 RTC_CHECK_EQ(kNoErr,
114 ap->noise_suppression()->set_level(
115 static_cast<NoiseSuppression::Level>(FLAGS_ns_level)));
ekmeyerson60d9b332015-08-14 10:35:55 -0700116 }
aluebs8e1809f2015-10-30 15:29:17 -0700117 ap->set_stream_key_pressed(FLAGS_ts);
ekmeyerson60d9b332015-08-14 10:35:55 -0700118
aluebsb0ad43b2015-11-20 00:11:53 -0800119 rtc::scoped_ptr<AudioFileProcessor> processor;
120 auto out_file = rtc_make_scoped_ptr(
121 new WavWriter(FLAGS_o, FLAGS_out_sample_rate, FLAGS_out_channels));
122 std::cout << FLAGS_o << ": " << out_file->FormatAsString() << std::endl;
123 if (FLAGS_dump.empty()) {
124 auto in_file = rtc_make_scoped_ptr(new WavReader(FLAGS_i));
125 std::cout << FLAGS_i << ": " << in_file->FormatAsString() << std::endl;
kwiberg0eb15ed2015-12-17 03:04:15 -0800126 processor.reset(new WavFileProcessor(std::move(ap), std::move(in_file),
127 std::move(out_file)));
andrewbdafe312015-10-29 23:42:54 -0700128
aluebsb0ad43b2015-11-20 00:11:53 -0800129 } else {
130 processor.reset(new AecDumpFileProcessor(
kwiberg0eb15ed2015-12-17 03:04:15 -0800131 std::move(ap), fopen(FLAGS_dump.c_str(), "rb"), std::move(out_file)));
andrewbdafe312015-10-29 23:42:54 -0700132 }
133
Alejandro Luebs5d22c002015-04-15 11:26:40 -0700134 int num_chunks = 0;
aluebsb0ad43b2015-11-20 00:11:53 -0800135 while (processor->ProcessChunk()) {
Andrew MacDonaldb444b3f2015-05-27 17:26:03 -0700136 trace_to_stderr.SetTimeSeconds(num_chunks * 1.f / kChunksPerSecond);
aluebsb0ad43b2015-11-20 00:11:53 -0800137 ++num_chunks;
kjellanderb7a5c162015-11-05 12:33:18 -0800138 }
aluebsb0ad43b2015-11-20 00:11:53 -0800139
Alejandro Luebs5d22c002015-04-15 11:26:40 -0700140 if (FLAGS_perf) {
aluebsb0ad43b2015-11-20 00:11:53 -0800141 const auto& proc_time = processor->proc_time();
142 int64_t exec_time_us = proc_time.sum.Microseconds();
143 printf(
144 "\nExecution time: %.3f s, File time: %.2f s\n"
145 "Time per chunk (mean, max, min):\n%.0f us, %.0f us, %.0f us\n",
146 exec_time_us * 1e-6, num_chunks * 1.f / kChunksPerSecond,
147 exec_time_us * 1.f / num_chunks, 1.f * proc_time.max.Microseconds(),
148 1.f * proc_time.min.Microseconds());
Alejandro Luebs5d22c002015-04-15 11:26:40 -0700149 }
aluebsb0ad43b2015-11-20 00:11:53 -0800150
andrew@webrtc.org08df9b22014-12-16 20:57:15 +0000151 return 0;
152}
153
154} // namespace webrtc
155
156int main(int argc, char* argv[]) {
157 return webrtc::main(argc, argv);
158}