2014-12-16 20:57:15 +00:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* Use of this source code is governed by a BSD-style license
|
|
|
|
|
* that can be found in the LICENSE file in the root of the source
|
|
|
|
|
* tree. An additional intellectual property rights grant can be found
|
|
|
|
|
* in the file PATENTS. All contributing project authors may
|
|
|
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
2015-11-20 00:11:53 -08:00
|
|
|
#include <iostream>
|
2015-01-29 22:39:44 +00:00
|
|
|
#include <sstream>
|
2015-01-15 01:28:36 +00:00
|
|
|
#include <string>
|
2015-12-17 03:04:15 -08:00
|
|
|
#include <utility>
|
2014-12-16 20:57:15 +00:00
|
|
|
|
|
|
|
|
#include "gflags/gflags.h"
|
|
|
|
|
#include "webrtc/base/checks.h"
|
Convert channel counts to size_t.
IIRC, this was originally requested by ajm during review of the other size_t conversions I did over the past year, and I agreed it made sense, but wanted to do it separately since those changes were already gargantuan.
BUG=chromium:81439
TEST=none
R=henrik.lundin@webrtc.org, henrika@webrtc.org, kjellander@webrtc.org, minyue@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1316523002 .
Cr-Commit-Position: refs/heads/master@{#11229}
2016-01-12 16:26:35 -08:00
|
|
|
#include "webrtc/base/format_macros.h"
|
2015-02-26 14:34:55 +00:00
|
|
|
#include "webrtc/base/scoped_ptr.h"
|
2015-01-28 19:57:00 +00:00
|
|
|
#include "webrtc/common_audio/channel_buffer.h"
|
2014-12-16 20:57:15 +00:00
|
|
|
#include "webrtc/common_audio/wav_file.h"
|
|
|
|
|
#include "webrtc/modules/audio_processing/include/audio_processing.h"
|
2015-11-20 00:11:53 -08:00
|
|
|
#include "webrtc/modules/audio_processing/test/audio_file_processor.h"
|
2015-05-07 22:17:51 -07:00
|
|
|
#include "webrtc/modules/audio_processing/test/protobuf_utils.h"
|
2014-12-16 20:57:15 +00:00
|
|
|
#include "webrtc/modules/audio_processing/test/test_utils.h"
|
2015-10-28 18:17:40 +01:00
|
|
|
#include "webrtc/system_wrappers/include/tick_util.h"
|
2015-05-27 17:26:03 -07:00
|
|
|
#include "webrtc/test/testsupport/trace_to_stderr.h"
|
2014-12-16 20:57:15 +00:00
|
|
|
|
Convert channel counts to size_t.
IIRC, this was originally requested by ajm during review of the other size_t conversions I did over the past year, and I agreed it made sense, but wanted to do it separately since those changes were already gargantuan.
BUG=chromium:81439
TEST=none
R=henrik.lundin@webrtc.org, henrika@webrtc.org, kjellander@webrtc.org, minyue@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1316523002 .
Cr-Commit-Position: refs/heads/master@{#11229}
2016-01-12 16:26:35 -08:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
bool ValidateOutChannels(const char* flagname, int32_t value) {
|
|
|
|
|
return value >= 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
2015-11-20 00:11:53 -08:00
|
|
|
DEFINE_string(dump, "", "Name of the aecdump debug file to read from.");
|
|
|
|
|
DEFINE_string(i, "", "Name of the capture input stream file to read from.");
|
|
|
|
|
DEFINE_string(
|
|
|
|
|
o,
|
|
|
|
|
"out.wav",
|
|
|
|
|
"Name of the output file to write the processed capture stream to.");
|
|
|
|
|
DEFINE_int32(out_channels, 1, "Number of output channels.");
|
Convert channel counts to size_t.
IIRC, this was originally requested by ajm during review of the other size_t conversions I did over the past year, and I agreed it made sense, but wanted to do it separately since those changes were already gargantuan.
BUG=chromium:81439
TEST=none
R=henrik.lundin@webrtc.org, henrika@webrtc.org, kjellander@webrtc.org, minyue@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1316523002 .
Cr-Commit-Position: refs/heads/master@{#11229}
2016-01-12 16:26:35 -08:00
|
|
|
const bool out_channels_dummy =
|
|
|
|
|
google::RegisterFlagValidator(&FLAGS_out_channels, &ValidateOutChannels);
|
2015-11-20 00:11:53 -08:00
|
|
|
DEFINE_int32(out_sample_rate, 48000, "Output sample rate in Hz.");
|
2015-01-29 22:39:44 +00:00
|
|
|
DEFINE_string(mic_positions, "",
|
|
|
|
|
"Space delimited cartesian coordinates of microphones in meters. "
|
|
|
|
|
"The coordinates of each point are contiguous. "
|
|
|
|
|
"For a two element array: \"x1 y1 z1 x2 y2 z2\"");
|
2015-11-20 00:11:53 -08:00
|
|
|
DEFINE_double(
|
|
|
|
|
target_angle_degrees,
|
|
|
|
|
90,
|
|
|
|
|
"The azimuth of the target in degrees. Only applies to beamforming.");
|
2014-12-16 20:57:15 +00:00
|
|
|
|
|
|
|
|
DEFINE_bool(aec, false, "Enable echo cancellation.");
|
|
|
|
|
DEFINE_bool(agc, false, "Enable automatic gain control.");
|
|
|
|
|
DEFINE_bool(hpf, false, "Enable high-pass filtering.");
|
|
|
|
|
DEFINE_bool(ns, false, "Enable noise suppression.");
|
|
|
|
|
DEFINE_bool(ts, false, "Enable transient suppression.");
|
2015-01-15 01:28:36 +00:00
|
|
|
DEFINE_bool(bf, false, "Enable beamforming.");
|
2015-08-14 10:35:55 -07:00
|
|
|
DEFINE_bool(ie, false, "Enable intelligibility enhancer.");
|
2014-12-16 20:57:15 +00:00
|
|
|
DEFINE_bool(all, false, "Enable all components.");
|
|
|
|
|
|
|
|
|
|
DEFINE_int32(ns_level, -1, "Noise suppression level [0 - 3].");
|
|
|
|
|
|
2015-04-15 11:26:40 -07:00
|
|
|
DEFINE_bool(perf, false, "Enable performance tests.");
|
|
|
|
|
|
2015-05-07 22:17:51 -07:00
|
|
|
namespace webrtc {
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
const int kChunksPerSecond = 100;
|
|
|
|
|
const char kUsage[] =
|
2014-12-16 20:57:15 +00:00
|
|
|
"Command-line tool to run audio processing on WAV files. Accepts either\n"
|
|
|
|
|
"an input capture WAV file or protobuf debug dump and writes to an output\n"
|
|
|
|
|
"WAV file.\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"All components are disabled by default. If any bi-directional components\n"
|
|
|
|
|
"are enabled, only debug dump files are permitted.";
|
|
|
|
|
|
2015-01-29 22:39:44 +00:00
|
|
|
} // namespace
|
|
|
|
|
|
2014-12-16 20:57:15 +00:00
|
|
|
int main(int argc, char* argv[]) {
|
2015-05-07 22:17:51 -07:00
|
|
|
google::SetUsageMessage(kUsage);
|
2014-12-16 20:57:15 +00:00
|
|
|
google::ParseCommandLineFlags(&argc, &argv, true);
|
|
|
|
|
|
2015-07-09 07:48:14 -07:00
|
|
|
if (!((FLAGS_i.empty()) ^ (FLAGS_dump.empty()))) {
|
2014-12-16 20:57:15 +00:00
|
|
|
fprintf(stderr,
|
2015-05-07 22:17:51 -07:00
|
|
|
"An input file must be specified with either -i or -dump.\n");
|
2014-12-16 20:57:15 +00:00
|
|
|
return 1;
|
|
|
|
|
}
|
2015-11-20 00:11:53 -08:00
|
|
|
if (FLAGS_dump.empty() && (FLAGS_aec || FLAGS_ie)) {
|
|
|
|
|
fprintf(stderr, "-aec and -ie require a -dump file.\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (FLAGS_ie) {
|
|
|
|
|
fprintf(stderr,
|
|
|
|
|
"FIXME(ajm): The intelligibility enhancer output is not dumped.\n");
|
2014-12-16 20:57:15 +00:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-27 17:26:03 -07:00
|
|
|
test::TraceToStderr trace_to_stderr(true);
|
2014-12-16 20:57:15 +00:00
|
|
|
Config config;
|
2015-01-15 01:28:36 +00:00
|
|
|
if (FLAGS_bf || FLAGS_all) {
|
2015-11-20 00:11:53 -08:00
|
|
|
if (FLAGS_mic_positions.empty()) {
|
|
|
|
|
fprintf(stderr, "-mic_positions must be specified when -bf is used.\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2015-10-29 18:21:34 -07:00
|
|
|
config.Set<Beamforming>(new Beamforming(
|
2015-11-20 00:11:53 -08:00
|
|
|
true, ParseArrayGeometry(FLAGS_mic_positions),
|
2015-10-29 18:21:34 -07:00
|
|
|
SphericalPointf(DegreesToRadians(FLAGS_target_angle_degrees), 0.f,
|
|
|
|
|
1.f)));
|
2015-01-15 01:28:36 +00:00
|
|
|
}
|
2015-11-20 00:11:53 -08:00
|
|
|
config.Set<ExperimentalNs>(new ExperimentalNs(FLAGS_ts || FLAGS_all));
|
|
|
|
|
config.Set<Intelligibility>(new Intelligibility(FLAGS_ie || FLAGS_all));
|
2015-01-15 01:28:36 +00:00
|
|
|
|
2015-02-26 14:34:55 +00:00
|
|
|
rtc::scoped_ptr<AudioProcessing> ap(AudioProcessing::Create(config));
|
2015-11-20 00:11:53 -08:00
|
|
|
RTC_CHECK_EQ(kNoErr, ap->echo_cancellation()->Enable(FLAGS_aec || FLAGS_all));
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK_EQ(kNoErr, ap->gain_control()->Enable(FLAGS_agc || FLAGS_all));
|
|
|
|
|
RTC_CHECK_EQ(kNoErr, ap->high_pass_filter()->Enable(FLAGS_hpf || FLAGS_all));
|
|
|
|
|
RTC_CHECK_EQ(kNoErr, ap->noise_suppression()->Enable(FLAGS_ns || FLAGS_all));
|
2015-11-05 06:23:02 -08:00
|
|
|
if (FLAGS_ns_level != -1) {
|
2015-09-17 00:24:34 -07:00
|
|
|
RTC_CHECK_EQ(kNoErr,
|
|
|
|
|
ap->noise_suppression()->set_level(
|
|
|
|
|
static_cast<NoiseSuppression::Level>(FLAGS_ns_level)));
|
2015-10-29 23:42:54 -07:00
|
|
|
}
|
2015-10-30 15:29:17 -07:00
|
|
|
ap->set_stream_key_pressed(FLAGS_ts);
|
2014-12-16 20:57:15 +00:00
|
|
|
|
2015-11-20 00:11:53 -08:00
|
|
|
rtc::scoped_ptr<AudioFileProcessor> processor;
|
Convert channel counts to size_t.
IIRC, this was originally requested by ajm during review of the other size_t conversions I did over the past year, and I agreed it made sense, but wanted to do it separately since those changes were already gargantuan.
BUG=chromium:81439
TEST=none
R=henrik.lundin@webrtc.org, henrika@webrtc.org, kjellander@webrtc.org, minyue@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1316523002 .
Cr-Commit-Position: refs/heads/master@{#11229}
2016-01-12 16:26:35 -08:00
|
|
|
auto out_file = rtc_make_scoped_ptr(new WavWriter(
|
|
|
|
|
FLAGS_o, FLAGS_out_sample_rate, static_cast<size_t>(FLAGS_out_channels)));
|
2015-11-20 00:11:53 -08:00
|
|
|
std::cout << FLAGS_o << ": " << out_file->FormatAsString() << std::endl;
|
|
|
|
|
if (FLAGS_dump.empty()) {
|
|
|
|
|
auto in_file = rtc_make_scoped_ptr(new WavReader(FLAGS_i));
|
|
|
|
|
std::cout << FLAGS_i << ": " << in_file->FormatAsString() << std::endl;
|
2015-12-17 03:04:15 -08:00
|
|
|
processor.reset(new WavFileProcessor(std::move(ap), std::move(in_file),
|
|
|
|
|
std::move(out_file)));
|
2015-11-20 00:11:53 -08:00
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
processor.reset(new AecDumpFileProcessor(
|
2015-12-17 03:04:15 -08:00
|
|
|
std::move(ap), fopen(FLAGS_dump.c_str(), "rb"), std::move(out_file)));
|
2015-08-14 10:35:55 -07:00
|
|
|
}
|
|
|
|
|
|
2015-04-15 11:26:40 -07:00
|
|
|
int num_chunks = 0;
|
2015-11-20 00:11:53 -08:00
|
|
|
while (processor->ProcessChunk()) {
|
2015-05-27 17:26:03 -07:00
|
|
|
trace_to_stderr.SetTimeSeconds(num_chunks * 1.f / kChunksPerSecond);
|
2015-11-20 00:11:53 -08:00
|
|
|
++num_chunks;
|
2015-11-05 12:33:18 -08:00
|
|
|
}
|
2015-11-20 00:11:53 -08:00
|
|
|
|
2015-04-15 11:26:40 -07:00
|
|
|
if (FLAGS_perf) {
|
2015-11-20 00:11:53 -08:00
|
|
|
const auto& proc_time = processor->proc_time();
|
|
|
|
|
int64_t exec_time_us = proc_time.sum.Microseconds();
|
|
|
|
|
printf(
|
|
|
|
|
"\nExecution time: %.3f s, File time: %.2f s\n"
|
|
|
|
|
"Time per chunk (mean, max, min):\n%.0f us, %.0f us, %.0f us\n",
|
|
|
|
|
exec_time_us * 1e-6, num_chunks * 1.f / kChunksPerSecond,
|
|
|
|
|
exec_time_us * 1.f / num_chunks, 1.f * proc_time.max.Microseconds(),
|
|
|
|
|
1.f * proc_time.min.Microseconds());
|
2014-12-16 20:57:15 +00:00
|
|
|
}
|
2015-11-20 00:11:53 -08:00
|
|
|
|
2014-12-16 20:57:15 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace webrtc
|
|
|
|
|
|
|
|
|
|
int main(int argc, char* argv[]) {
|
|
|
|
|
return webrtc::main(argc, argv);
|
|
|
|
|
}
|