Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(162)

Side by Side Diff: webrtc/modules/audio_processing/test/audioproc_float.cc

Issue 1419953010: Reland of Add aecdump support to audioproc_f. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include <stdio.h> 11 #include <stdio.h>
12 #include <iostream>
12 #include <sstream> 13 #include <sstream>
13 #include <string> 14 #include <string>
14 15
15 #include "gflags/gflags.h" 16 #include "gflags/gflags.h"
16 #include "webrtc/base/checks.h" 17 #include "webrtc/base/checks.h"
17 #include "webrtc/base/scoped_ptr.h" 18 #include "webrtc/base/scoped_ptr.h"
18 #include "webrtc/common_audio/channel_buffer.h" 19 #include "webrtc/common_audio/channel_buffer.h"
19 #include "webrtc/common_audio/wav_file.h" 20 #include "webrtc/common_audio/wav_file.h"
20 #include "webrtc/modules/audio_processing/include/audio_processing.h" 21 #include "webrtc/modules/audio_processing/include/audio_processing.h"
22 #include "webrtc/modules/audio_processing/test/audio_file_processor.h"
21 #include "webrtc/modules/audio_processing/test/protobuf_utils.h" 23 #include "webrtc/modules/audio_processing/test/protobuf_utils.h"
22 #include "webrtc/modules/audio_processing/test/test_utils.h" 24 #include "webrtc/modules/audio_processing/test/test_utils.h"
23 #include "webrtc/system_wrappers/include/tick_util.h" 25 #include "webrtc/system_wrappers/include/tick_util.h"
24 #include "webrtc/test/testsupport/trace_to_stderr.h" 26 #include "webrtc/test/testsupport/trace_to_stderr.h"
25 27
26 DEFINE_string(dump, "", "The name of the debug dump file to read from."); 28 DEFINE_string(dump, "", "Name of the aecdump debug file to read from.");
27 DEFINE_string(i, "", "The name of the input file to read from."); 29 DEFINE_string(i, "", "Name of the capture input stream file to read from.");
28 DEFINE_string(i_rev, "", "The name of the reverse input file to read from."); 30 DEFINE_string(
29 DEFINE_string(o, "out.wav", "Name of the output file to write to."); 31 o,
30 DEFINE_string(o_rev, 32 "out.wav",
31 "out_rev.wav", 33 "Name of the output file to write the processed capture stream to.");
32 "Name of the reverse output file to write to."); 34 DEFINE_int32(out_channels, 1, "Number of output channels.");
33 DEFINE_int32(out_channels, 0, "Number of output channels. Defaults to input."); 35 DEFINE_int32(out_sample_rate, 48000, "Output sample rate in Hz.");
34 DEFINE_int32(out_sample_rate, 0,
35 "Output sample rate in Hz. Defaults to input.");
36 DEFINE_string(mic_positions, "", 36 DEFINE_string(mic_positions, "",
37 "Space delimited cartesian coordinates of microphones in meters. " 37 "Space delimited cartesian coordinates of microphones in meters. "
38 "The coordinates of each point are contiguous. " 38 "The coordinates of each point are contiguous. "
39 "For a two element array: \"x1 y1 z1 x2 y2 z2\""); 39 "For a two element array: \"x1 y1 z1 x2 y2 z2\"");
40 DEFINE_double(target_angle_degrees, 90, "The azimuth of the target in radians"); 40 DEFINE_double(
41 target_angle_degrees,
42 90,
43 "The azimuth of the target in degrees. Only applies to beamforming.");
41 44
42 DEFINE_bool(aec, false, "Enable echo cancellation."); 45 DEFINE_bool(aec, false, "Enable echo cancellation.");
43 DEFINE_bool(agc, false, "Enable automatic gain control."); 46 DEFINE_bool(agc, false, "Enable automatic gain control.");
44 DEFINE_bool(hpf, false, "Enable high-pass filtering."); 47 DEFINE_bool(hpf, false, "Enable high-pass filtering.");
45 DEFINE_bool(ns, false, "Enable noise suppression."); 48 DEFINE_bool(ns, false, "Enable noise suppression.");
46 DEFINE_bool(ts, false, "Enable transient suppression."); 49 DEFINE_bool(ts, false, "Enable transient suppression.");
47 DEFINE_bool(bf, false, "Enable beamforming."); 50 DEFINE_bool(bf, false, "Enable beamforming.");
48 DEFINE_bool(ie, false, "Enable intelligibility enhancer."); 51 DEFINE_bool(ie, false, "Enable intelligibility enhancer.");
49 DEFINE_bool(all, false, "Enable all components."); 52 DEFINE_bool(all, false, "Enable all components.");
50 53
51 DEFINE_int32(ns_level, -1, "Noise suppression level [0 - 3]."); 54 DEFINE_int32(ns_level, -1, "Noise suppression level [0 - 3].");
52 55
53 DEFINE_bool(perf, false, "Enable performance tests."); 56 DEFINE_bool(perf, false, "Enable performance tests.");
54 57
55 namespace webrtc { 58 namespace webrtc {
56 namespace { 59 namespace {
57 60
58 const int kChunksPerSecond = 100; 61 const int kChunksPerSecond = 100;
59 const char kUsage[] = 62 const char kUsage[] =
60 "Command-line tool to run audio processing on WAV files. Accepts either\n" 63 "Command-line tool to run audio processing on WAV files. Accepts either\n"
61 "an input capture WAV file or protobuf debug dump and writes to an output\n" 64 "an input capture WAV file or protobuf debug dump and writes to an output\n"
62 "WAV file.\n" 65 "WAV file.\n"
63 "\n" 66 "\n"
64 "All components are disabled by default. If any bi-directional components\n" 67 "All components are disabled by default. If any bi-directional components\n"
65 "are enabled, only debug dump files are permitted."; 68 "are enabled, only debug dump files are permitted.";
66 69
67 // Returns a StreamConfig corresponding to wav_file if it's non-nullptr.
68 // Otherwise returns a default initialized StreamConfig.
69 StreamConfig MakeStreamConfig(const WavFile* wav_file) {
70 if (wav_file) {
71 return {wav_file->sample_rate(), wav_file->num_channels()};
72 }
73 return {};
74 }
75
76 } // namespace 70 } // namespace
77 71
78 int main(int argc, char* argv[]) { 72 int main(int argc, char* argv[]) {
79 google::SetUsageMessage(kUsage); 73 google::SetUsageMessage(kUsage);
80 google::ParseCommandLineFlags(&argc, &argv, true); 74 google::ParseCommandLineFlags(&argc, &argv, true);
81 75
82 if (!((FLAGS_i.empty()) ^ (FLAGS_dump.empty()))) { 76 if (!((FLAGS_i.empty()) ^ (FLAGS_dump.empty()))) {
83 fprintf(stderr, 77 fprintf(stderr,
84 "An input file must be specified with either -i or -dump.\n"); 78 "An input file must be specified with either -i or -dump.\n");
85 return 1; 79 return 1;
86 } 80 }
87 if (!FLAGS_dump.empty()) { 81 if (FLAGS_dump.empty() && (FLAGS_aec || FLAGS_ie)) {
88 fprintf(stderr, "FIXME: the -dump option is not yet implemented.\n"); 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");
89 return 1; 88 return 1;
90 } 89 }
91 90
92 test::TraceToStderr trace_to_stderr(true); 91 test::TraceToStderr trace_to_stderr(true);
93 WavReader in_file(FLAGS_i);
94 // If the output format is uninitialized, use the input format.
95 const int out_channels =
96 FLAGS_out_channels ? FLAGS_out_channels : in_file.num_channels();
97 const int out_sample_rate =
98 FLAGS_out_sample_rate ? FLAGS_out_sample_rate : in_file.sample_rate();
99 WavWriter out_file(FLAGS_o, out_sample_rate, out_channels);
100
101 Config config; 92 Config config;
93 if (FLAGS_bf || FLAGS_all) {
94 if (FLAGS_mic_positions.empty()) {
95 fprintf(stderr, "-mic_positions must be specified when -bf is used.\n");
96 return 1;
97 }
98 config.Set<Beamforming>(new Beamforming(
99 true, ParseArrayGeometry(FLAGS_mic_positions),
100 SphericalPointf(DegreesToRadians(FLAGS_target_angle_degrees), 0.f,
101 1.f)));
102 }
102 config.Set<ExperimentalNs>(new ExperimentalNs(FLAGS_ts || FLAGS_all)); 103 config.Set<ExperimentalNs>(new ExperimentalNs(FLAGS_ts || FLAGS_all));
103 config.Set<Intelligibility>(new Intelligibility(FLAGS_ie || FLAGS_all)); 104 config.Set<Intelligibility>(new Intelligibility(FLAGS_ie || FLAGS_all));
104 105
105 if (FLAGS_bf || FLAGS_all) {
106 const size_t num_mics = in_file.num_channels();
107 const std::vector<Point> array_geometry =
108 ParseArrayGeometry(FLAGS_mic_positions, num_mics);
109 RTC_CHECK_EQ(array_geometry.size(), num_mics);
110
111 config.Set<Beamforming>(new Beamforming(
112 true, array_geometry,
113 SphericalPointf(DegreesToRadians(FLAGS_target_angle_degrees), 0.f,
114 1.f)));
115 }
116
117 rtc::scoped_ptr<AudioProcessing> ap(AudioProcessing::Create(config)); 106 rtc::scoped_ptr<AudioProcessing> ap(AudioProcessing::Create(config));
118 if (!FLAGS_dump.empty()) { 107 RTC_CHECK_EQ(kNoErr, ap->echo_cancellation()->Enable(FLAGS_aec || FLAGS_all));
119 RTC_CHECK_EQ(kNoErr,
120 ap->echo_cancellation()->Enable(FLAGS_aec || FLAGS_all));
121 } else if (FLAGS_aec) {
122 fprintf(stderr, "-aec requires a -dump file.\n");
123 return -1;
124 }
125 bool process_reverse = !FLAGS_i_rev.empty();
126 RTC_CHECK_EQ(kNoErr, ap->gain_control()->Enable(FLAGS_agc || FLAGS_all)); 108 RTC_CHECK_EQ(kNoErr, ap->gain_control()->Enable(FLAGS_agc || FLAGS_all));
127 RTC_CHECK_EQ(kNoErr,
128 ap->gain_control()->set_mode(GainControl::kFixedDigital));
129 RTC_CHECK_EQ(kNoErr, ap->high_pass_filter()->Enable(FLAGS_hpf || FLAGS_all)); 109 RTC_CHECK_EQ(kNoErr, ap->high_pass_filter()->Enable(FLAGS_hpf || FLAGS_all));
130 RTC_CHECK_EQ(kNoErr, ap->noise_suppression()->Enable(FLAGS_ns || FLAGS_all)); 110 RTC_CHECK_EQ(kNoErr, ap->noise_suppression()->Enable(FLAGS_ns || FLAGS_all));
131 if (FLAGS_ns_level != -1) 111 if (FLAGS_ns_level != -1) {
132 RTC_CHECK_EQ(kNoErr, 112 RTC_CHECK_EQ(kNoErr,
133 ap->noise_suppression()->set_level( 113 ap->noise_suppression()->set_level(
134 static_cast<NoiseSuppression::Level>(FLAGS_ns_level))); 114 static_cast<NoiseSuppression::Level>(FLAGS_ns_level)));
135 } 115 }
136 ap->set_stream_key_pressed(FLAGS_ts); 116 ap->set_stream_key_pressed(FLAGS_ts);
137 117
138 printf("Input file: %s\nChannels: %d, Sample rate: %d Hz\n\n", 118 rtc::scoped_ptr<AudioFileProcessor> processor;
139 FLAGS_i.c_str(), in_file.num_channels(), in_file.sample_rate()); 119 auto out_file = rtc_make_scoped_ptr(
140 printf("Output file: %s\nChannels: %d, Sample rate: %d Hz\n\n", 120 new WavWriter(FLAGS_o, FLAGS_out_sample_rate, FLAGS_out_channels));
141 FLAGS_o.c_str(), out_file.num_channels(), out_file.sample_rate()); 121 std::cout << FLAGS_o << ": " << out_file->FormatAsString() << std::endl;
122 if (FLAGS_dump.empty()) {
123 auto in_file = rtc_make_scoped_ptr(new WavReader(FLAGS_i));
124 std::cout << FLAGS_i << ": " << in_file->FormatAsString() << std::endl;
125 processor.reset(
126 new WavFileProcessor(ap.Pass(), in_file.Pass(), out_file.Pass()));
142 127
143 ChannelBuffer<float> in_buf( 128 } else {
144 rtc::CheckedDivExact(in_file.sample_rate(), kChunksPerSecond), 129 processor.reset(new AecDumpFileProcessor(
145 in_file.num_channels()); 130 ap.Pass(), fopen(FLAGS_dump.c_str(), "rb"), out_file.Pass()));
146 ChannelBuffer<float> out_buf(
147 rtc::CheckedDivExact(out_file.sample_rate(), kChunksPerSecond),
148 out_file.num_channels());
149
150 std::vector<float> in_interleaved(in_buf.size());
151 std::vector<float> out_interleaved(out_buf.size());
152
153 rtc::scoped_ptr<WavReader> in_rev_file;
154 rtc::scoped_ptr<WavWriter> out_rev_file;
155 rtc::scoped_ptr<ChannelBuffer<float>> in_rev_buf;
156 rtc::scoped_ptr<ChannelBuffer<float>> out_rev_buf;
157 std::vector<float> in_rev_interleaved;
158 std::vector<float> out_rev_interleaved;
159 if (process_reverse) {
160 in_rev_file.reset(new WavReader(FLAGS_i_rev));
161 out_rev_file.reset(new WavWriter(FLAGS_o_rev, in_rev_file->sample_rate(),
162 in_rev_file->num_channels()));
163 printf("In rev file: %s\nChannels: %d, Sample rate: %d Hz\n\n",
164 FLAGS_i_rev.c_str(), in_rev_file->num_channels(),
165 in_rev_file->sample_rate());
166 printf("Out rev file: %s\nChannels: %d, Sample rate: %d Hz\n\n",
167 FLAGS_o_rev.c_str(), out_rev_file->num_channels(),
168 out_rev_file->sample_rate());
169 in_rev_buf.reset(new ChannelBuffer<float>(
170 rtc::CheckedDivExact(in_rev_file->sample_rate(), kChunksPerSecond),
171 in_rev_file->num_channels()));
172 in_rev_interleaved.resize(in_rev_buf->size());
173 out_rev_buf.reset(new ChannelBuffer<float>(
174 rtc::CheckedDivExact(out_rev_file->sample_rate(), kChunksPerSecond),
175 out_rev_file->num_channels()));
176 out_rev_interleaved.resize(out_rev_buf->size());
177 } 131 }
178 132
179 TickTime processing_start_time;
180 TickInterval accumulated_time;
181 int num_chunks = 0; 133 int num_chunks = 0;
134 while (processor->ProcessChunk()) {
135 trace_to_stderr.SetTimeSeconds(num_chunks * 1.f / kChunksPerSecond);
136 ++num_chunks;
137 }
182 138
183 const auto input_config = MakeStreamConfig(&in_file); 139 if (FLAGS_perf) {
184 const auto output_config = MakeStreamConfig(&out_file); 140 const auto& proc_time = processor->proc_time();
185 const auto reverse_input_config = MakeStreamConfig(in_rev_file.get()); 141 int64_t exec_time_us = proc_time.sum.Microseconds();
186 const auto reverse_output_config = MakeStreamConfig(out_rev_file.get()); 142 printf(
143 "\nExecution time: %.3f s, File time: %.2f s\n"
144 "Time per chunk (mean, max, min):\n%.0f us, %.0f us, %.0f us\n",
145 exec_time_us * 1e-6, num_chunks * 1.f / kChunksPerSecond,
146 exec_time_us * 1.f / num_chunks, 1.f * proc_time.max.Microseconds(),
147 1.f * proc_time.min.Microseconds());
148 }
187 149
188 while (in_file.ReadSamples(in_interleaved.size(),
189 &in_interleaved[0]) == in_interleaved.size()) {
190 // Have logs display the file time rather than wallclock time.
191 trace_to_stderr.SetTimeSeconds(num_chunks * 1.f / kChunksPerSecond);
192 FloatS16ToFloat(&in_interleaved[0], in_interleaved.size(),
193 &in_interleaved[0]);
194 Deinterleave(&in_interleaved[0], in_buf.num_frames(),
195 in_buf.num_channels(), in_buf.channels());
196 if (process_reverse) {
197 in_rev_file->ReadSamples(in_rev_interleaved.size(),
198 in_rev_interleaved.data());
199 FloatS16ToFloat(in_rev_interleaved.data(), in_rev_interleaved.size(),
200 in_rev_interleaved.data());
201 Deinterleave(in_rev_interleaved.data(), in_rev_buf->num_frames(),
202 in_rev_buf->num_channels(), in_rev_buf->channels());
203 }
204
205 if (FLAGS_perf) {
206 processing_start_time = TickTime::Now();
207 }
208 RTC_CHECK_EQ(kNoErr, ap->ProcessStream(in_buf.channels(), input_config,
209 output_config, out_buf.channels()));
210 if (process_reverse) {
211 RTC_CHECK_EQ(kNoErr, ap->ProcessReverseStream(
212 in_rev_buf->channels(), reverse_input_config,
213 reverse_output_config, out_rev_buf->channels()));
214 }
215 if (FLAGS_perf) {
216 accumulated_time += TickTime::Now() - processing_start_time;
217 }
218
219 Interleave(out_buf.channels(), out_buf.num_frames(),
220 out_buf.num_channels(), &out_interleaved[0]);
221 FloatToFloatS16(&out_interleaved[0], out_interleaved.size(),
222 &out_interleaved[0]);
223 out_file.WriteSamples(&out_interleaved[0], out_interleaved.size());
224 if (process_reverse) {
225 Interleave(out_rev_buf->channels(), out_rev_buf->num_frames(),
226 out_rev_buf->num_channels(), out_rev_interleaved.data());
227 FloatToFloatS16(out_rev_interleaved.data(), out_rev_interleaved.size(),
228 out_rev_interleaved.data());
229 out_rev_file->WriteSamples(out_rev_interleaved.data(),
230 out_rev_interleaved.size());
231 }
232 num_chunks++;
233 }
234 if (FLAGS_perf) {
235 int64_t execution_time_ms = accumulated_time.Milliseconds();
236 printf("\nExecution time: %.3f s\nFile time: %.2f s\n"
237 "Time per chunk: %.3f ms\n",
238 execution_time_ms * 0.001f, num_chunks * 1.f / kChunksPerSecond,
239 execution_time_ms * 1.f / num_chunks);
240 }
241 return 0; 150 return 0;
242 } 151 }
243 152
244 } // namespace webrtc 153 } // namespace webrtc
245 154
246 int main(int argc, char* argv[]) { 155 int main(int argc, char* argv[]) {
247 return webrtc::main(argc, argv); 156 return webrtc::main(argc, argv);
248 } 157 }
OLDNEW
« no previous file with comments | « webrtc/modules/audio_processing/test/audio_file_processor.cc ('k') | webrtc/modules/audio_processing/test/process_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698