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-01-29 22:39:44 +00:00
|
|
|
#include <sstream>
|
2015-01-15 01:28:36 +00:00
|
|
|
#include <string>
|
2014-12-16 20:57:15 +00:00
|
|
|
|
|
|
|
|
#include "gflags/gflags.h"
|
|
|
|
|
#include "webrtc/base/checks.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-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-04-15 11:26:40 -07:00
|
|
|
#include "webrtc/system_wrappers/interface/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
|
|
|
|
|
|
|
|
DEFINE_string(dump, "", "The name of the debug dump file to read from.");
|
2015-05-07 22:17:51 -07:00
|
|
|
DEFINE_string(i, "", "The name of the input file to read from.");
|
|
|
|
|
DEFINE_string(o, "out.wav", "Name of the output file to write to.");
|
|
|
|
|
DEFINE_int32(out_channels, 0, "Number of output channels. Defaults to input.");
|
|
|
|
|
DEFINE_int32(out_sample_rate, 0,
|
|
|
|
|
"Output sample rate in Hz. Defaults to input.");
|
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\"");
|
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.");
|
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-07-09 07:48:14 -07:00
|
|
|
if (!FLAGS_dump.empty()) {
|
2014-12-16 20:57:15 +00:00
|
|
|
fprintf(stderr, "FIXME: the -dump option is not yet implemented.\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-27 17:26:03 -07:00
|
|
|
test::TraceToStderr trace_to_stderr(true);
|
2015-05-07 22:17:51 -07:00
|
|
|
WavReader in_file(FLAGS_i);
|
2014-12-16 20:57:15 +00:00
|
|
|
// If the output format is uninitialized, use the input format.
|
2015-05-07 22:17:51 -07:00
|
|
|
const int out_channels =
|
|
|
|
|
FLAGS_out_channels ? FLAGS_out_channels : in_file.num_channels();
|
|
|
|
|
const int out_sample_rate =
|
|
|
|
|
FLAGS_out_sample_rate ? FLAGS_out_sample_rate : in_file.sample_rate();
|
|
|
|
|
WavWriter out_file(FLAGS_o, out_sample_rate, out_channels);
|
2014-12-16 20:57:15 +00:00
|
|
|
|
|
|
|
|
Config config;
|
|
|
|
|
config.Set<ExperimentalNs>(new ExperimentalNs(FLAGS_ts || FLAGS_all));
|
2015-01-15 01:28:36 +00:00
|
|
|
|
|
|
|
|
if (FLAGS_bf || FLAGS_all) {
|
2015-05-07 22:17:51 -07:00
|
|
|
const size_t num_mics = in_file.num_channels();
|
|
|
|
|
const std::vector<Point> array_geometry =
|
|
|
|
|
ParseArrayGeometry(FLAGS_mic_positions, num_mics);
|
|
|
|
|
CHECK_EQ(array_geometry.size(), num_mics);
|
2015-01-15 01:28:36 +00:00
|
|
|
|
|
|
|
|
config.Set<Beamforming>(new Beamforming(true, array_geometry));
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-26 14:34:55 +00:00
|
|
|
rtc::scoped_ptr<AudioProcessing> ap(AudioProcessing::Create(config));
|
2015-07-09 07:48:14 -07:00
|
|
|
if (!FLAGS_dump.empty()) {
|
2014-12-16 20:57:15 +00:00
|
|
|
CHECK_EQ(kNoErr, ap->echo_cancellation()->Enable(FLAGS_aec || FLAGS_all));
|
|
|
|
|
} else if (FLAGS_aec) {
|
|
|
|
|
fprintf(stderr, "-aec requires a -dump file.\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
CHECK_EQ(kNoErr, ap->gain_control()->Enable(FLAGS_agc || FLAGS_all));
|
|
|
|
|
CHECK_EQ(kNoErr, ap->gain_control()->set_mode(GainControl::kFixedDigital));
|
|
|
|
|
CHECK_EQ(kNoErr, ap->high_pass_filter()->Enable(FLAGS_hpf || FLAGS_all));
|
|
|
|
|
CHECK_EQ(kNoErr, ap->noise_suppression()->Enable(FLAGS_ns || FLAGS_all));
|
|
|
|
|
if (FLAGS_ns_level != -1)
|
|
|
|
|
CHECK_EQ(kNoErr, ap->noise_suppression()->set_level(
|
|
|
|
|
static_cast<NoiseSuppression::Level>(FLAGS_ns_level)));
|
|
|
|
|
|
2015-01-15 01:28:36 +00:00
|
|
|
printf("Input file: %s\nChannels: %d, Sample rate: %d Hz\n\n",
|
2015-05-07 22:17:51 -07:00
|
|
|
FLAGS_i.c_str(), in_file.num_channels(), in_file.sample_rate());
|
2015-01-15 01:28:36 +00:00
|
|
|
printf("Output file: %s\nChannels: %d, Sample rate: %d Hz\n\n",
|
2015-05-07 22:17:51 -07:00
|
|
|
FLAGS_o.c_str(), out_file.num_channels(), out_file.sample_rate());
|
|
|
|
|
|
|
|
|
|
ChannelBuffer<float> in_buf(
|
|
|
|
|
rtc::CheckedDivExact(in_file.sample_rate(), kChunksPerSecond),
|
|
|
|
|
in_file.num_channels());
|
|
|
|
|
ChannelBuffer<float> out_buf(
|
|
|
|
|
rtc::CheckedDivExact(out_file.sample_rate(), kChunksPerSecond),
|
|
|
|
|
out_file.num_channels());
|
|
|
|
|
|
|
|
|
|
std::vector<float> in_interleaved(in_buf.size());
|
|
|
|
|
std::vector<float> out_interleaved(out_buf.size());
|
2015-04-15 11:26:40 -07:00
|
|
|
TickTime processing_start_time;
|
|
|
|
|
TickInterval accumulated_time;
|
|
|
|
|
int num_chunks = 0;
|
2015-05-07 22:17:51 -07:00
|
|
|
while (in_file.ReadSamples(in_interleaved.size(),
|
|
|
|
|
&in_interleaved[0]) == in_interleaved.size()) {
|
2015-05-27 17:26:03 -07:00
|
|
|
// Have logs display the file time rather than wallclock time.
|
|
|
|
|
trace_to_stderr.SetTimeSeconds(num_chunks * 1.f / kChunksPerSecond);
|
2015-05-07 22:17:51 -07:00
|
|
|
FloatS16ToFloat(&in_interleaved[0], in_interleaved.size(),
|
|
|
|
|
&in_interleaved[0]);
|
|
|
|
|
Deinterleave(&in_interleaved[0], in_buf.num_frames(),
|
|
|
|
|
in_buf.num_channels(), in_buf.channels());
|
|
|
|
|
|
2015-04-15 11:26:40 -07:00
|
|
|
if (FLAGS_perf) {
|
|
|
|
|
processing_start_time = TickTime::Now();
|
|
|
|
|
}
|
Revert of Allow more than 2 input channels in AudioProcessing. (patchset #13 id:240001 of https://codereview.webrtc.org/1226093007/)
Reason for revert:
Breaks Chromium FYI content_browsertest on all platforms. The testcase that fails is WebRtcAecDumpBrowserTest.CallWithAecDump.
https://build.chromium.org/p/chromium.webrtc.fyi/builders/Linux/builds/19388
Sample output:
[ RUN ] WebRtcAecDumpBrowserTest.CallWithAecDump
Xlib: extension "RANDR" missing on display ":9".
[4:14:0722/211548:1282124453:WARNING:webrtcvoiceengine.cc(472)] Unexpected codec: ISAC/48000/1 (105)
[4:14:0722/211548:1282124593:WARNING:webrtcvoiceengine.cc(472)] Unexpected codec: PCMU/8000/2 (110)
[4:14:0722/211548:1282124700:WARNING:webrtcvoiceengine.cc(472)] Unexpected codec: PCMA/8000/2 (118)
[4:14:0722/211548:1282124815:WARNING:webrtcvoiceengine.cc(472)] Unexpected codec: G722/8000/2 (119)
[19745:19745:0722/211548:1282133667:INFO:CONSOLE(64)] "Looking at video in element remote-view-1", source: http://127.0.0.1:48819/media/webrtc_test_utilities.js (64)
[19745:19745:0722/211548:1282136892:INFO:CONSOLE(64)] "Looking at video in element remote-view-2", source: http://127.0.0.1:48819/media/webrtc_test_utilities.js (64)
../../content/test/webrtc_content_browsertest_base.cc:62: Failure
Value of: ExecuteScriptAndExtractString( shell()->web_contents(), javascript, &result)
Actual: false
Expected: true
Failed to execute javascript call({video: true, audio: true});.
From javascript: (nothing)
When executing 'call({video: true, audio: true});'
../../content/test/webrtc_content_browsertest_base.cc:75: Failure
Failed
../../content/browser/media/webrtc_aecdump_browsertest.cc:26: Failure
Expected: (base::kNullProcessId) != (*id), actual: 0 vs 0
../../content/browser/media/webrtc_aecdump_browsertest.cc:95: Failure
Value of: GetRenderProcessHostId(&render_process_id)
Actual: false
Expected: true
../../content/browser/media/webrtc_aecdump_browsertest.cc:99: Failure
Value of: base::PathExists(dump_file)
Actual: false
Expected: true
../../content/browser/media/webrtc_aecdump_browsertest.cc:101: Failure
Value of: base::GetFileSize(dump_file, &file_size)
Actual: false
Expected: true
../../content/browser/media/webrtc_aecdump_browsertest.cc:102: Failure
Expected: (file_size) > (0), actual: 0 vs 0
[ FAILED ] WebRtcAecDumpBrowserTest.CallWithAecDump, where TypeParam = and GetParam() = (361 ms)
Original issue's description:
> Allow more than 2 input channels in AudioProcessing.
>
> The number of output channels is constrained to be equal to either 1 or the
> number of input channels.
>
> R=aluebs@webrtc.org, andrew@webrtc.org, pbos@webrtc.org
>
> Committed: https://chromium.googlesource.com/external/webrtc/+/c204754b7a0cc801c70e8ce6c689f57f6ce00b3b
TBR=andrew@webrtc.org,aluebs@webrtc.org,ajm@chromium.org,pbos@chromium.org,pbos@webrtc.org,mgraczyk@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
Review URL: https://codereview.webrtc.org/1253573005
Cr-Commit-Position: refs/heads/master@{#9621}
2015-07-23 04:30:06 -07:00
|
|
|
CHECK_EQ(kNoErr,
|
|
|
|
|
ap->ProcessStream(in_buf.channels(),
|
|
|
|
|
in_buf.num_frames(),
|
|
|
|
|
in_file.sample_rate(),
|
|
|
|
|
LayoutFromChannels(in_buf.num_channels()),
|
|
|
|
|
out_file.sample_rate(),
|
|
|
|
|
LayoutFromChannels(out_buf.num_channels()),
|
|
|
|
|
out_buf.channels()));
|
2015-04-15 11:26:40 -07:00
|
|
|
if (FLAGS_perf) {
|
|
|
|
|
accumulated_time += TickTime::Now() - processing_start_time;
|
|
|
|
|
}
|
2015-05-07 22:17:51 -07:00
|
|
|
|
|
|
|
|
Interleave(out_buf.channels(), out_buf.num_frames(),
|
|
|
|
|
out_buf.num_channels(), &out_interleaved[0]);
|
|
|
|
|
FloatToFloatS16(&out_interleaved[0], out_interleaved.size(),
|
|
|
|
|
&out_interleaved[0]);
|
|
|
|
|
out_file.WriteSamples(&out_interleaved[0], out_interleaved.size());
|
2015-04-15 11:26:40 -07:00
|
|
|
num_chunks++;
|
|
|
|
|
}
|
|
|
|
|
if (FLAGS_perf) {
|
2015-05-27 17:26:03 -07:00
|
|
|
int64_t execution_time_ms = accumulated_time.Milliseconds();
|
|
|
|
|
printf("\nExecution time: %.3f s\nFile time: %.2f s\n"
|
|
|
|
|
"Time per chunk: %.3f ms\n",
|
|
|
|
|
execution_time_ms * 0.001f, num_chunks * 1.f / kChunksPerSecond,
|
|
|
|
|
execution_time_ms * 1.f / num_chunks);
|
2014-12-16 20:57:15 +00:00
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace webrtc
|
|
|
|
|
|
|
|
|
|
int main(int argc, char* argv[]) {
|
|
|
|
|
return webrtc::main(argc, argv);
|
|
|
|
|
}
|