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

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

Issue 1409943002: Add aecdump support to audioproc_f. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Rebase. 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
136 printf("Input file: %s\nChannels: %d, Sample rate: %d Hz\n\n",
137 FLAGS_i.c_str(), in_file.num_channels(), in_file.sample_rate());
138 printf("Output file: %s\nChannels: %d, Sample rate: %d Hz\n\n",
139 FLAGS_o.c_str(), out_file.num_channels(), out_file.sample_rate());
140
141 ChannelBuffer<float> in_buf(
142 rtc::CheckedDivExact(in_file.sample_rate(), kChunksPerSecond),
143 in_file.num_channels());
144 ChannelBuffer<float> out_buf(
145 rtc::CheckedDivExact(out_file.sample_rate(), kChunksPerSecond),
146 out_file.num_channels());
147
148 std::vector<float> in_interleaved(in_buf.size());
149 std::vector<float> out_interleaved(out_buf.size());
150
151 rtc::scoped_ptr<WavReader> in_rev_file;
152 rtc::scoped_ptr<WavWriter> out_rev_file;
153 rtc::scoped_ptr<ChannelBuffer<float>> in_rev_buf;
154 rtc::scoped_ptr<ChannelBuffer<float>> out_rev_buf;
155 std::vector<float> in_rev_interleaved;
156 std::vector<float> out_rev_interleaved;
157 if (process_reverse) {
158 in_rev_file.reset(new WavReader(FLAGS_i_rev));
159 out_rev_file.reset(new WavWriter(FLAGS_o_rev, in_rev_file->sample_rate(),
160 in_rev_file->num_channels()));
161 printf("In rev file: %s\nChannels: %d, Sample rate: %d Hz\n\n",
162 FLAGS_i_rev.c_str(), in_rev_file->num_channels(),
163 in_rev_file->sample_rate());
164 printf("Out rev file: %s\nChannels: %d, Sample rate: %d Hz\n\n",
165 FLAGS_o_rev.c_str(), out_rev_file->num_channels(),
166 out_rev_file->sample_rate());
167 in_rev_buf.reset(new ChannelBuffer<float>(
168 rtc::CheckedDivExact(in_rev_file->sample_rate(), kChunksPerSecond),
169 in_rev_file->num_channels()));
170 in_rev_interleaved.resize(in_rev_buf->size());
171 out_rev_buf.reset(new ChannelBuffer<float>(
172 rtc::CheckedDivExact(out_rev_file->sample_rate(), kChunksPerSecond),
173 out_rev_file->num_channels()));
174 out_rev_interleaved.resize(out_rev_buf->size());
175 } 115 }
176 116
177 TickTime processing_start_time; 117 rtc::scoped_ptr<AudioFileProcessor> processor;
178 TickInterval accumulated_time; 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
179 int num_chunks = 0; 132 int num_chunks = 0;
133 while (processor->ProcessChunk()) {
134 trace_to_stderr.SetTimeSeconds(num_chunks * 1.f / kChunksPerSecond);
135 ++num_chunks;
136 }
180 137
181 const auto input_config = MakeStreamConfig(&in_file); 138 if (FLAGS_perf) {
182 const auto output_config = MakeStreamConfig(&out_file); 139 const auto& proc_time = processor->proc_time();
183 const auto reverse_input_config = MakeStreamConfig(in_rev_file.get()); 140 int64_t exec_time_us = proc_time.sum.Microseconds();
184 const auto reverse_output_config = MakeStreamConfig(out_rev_file.get()); 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());
147 }
185 148
186 while (in_file.ReadSamples(in_interleaved.size(),
187 &in_interleaved[0]) == in_interleaved.size()) {
188 // Have logs display the file time rather than wallclock time.
189 trace_to_stderr.SetTimeSeconds(num_chunks * 1.f / kChunksPerSecond);
190 FloatS16ToFloat(&in_interleaved[0], in_interleaved.size(),
191 &in_interleaved[0]);
192 Deinterleave(&in_interleaved[0], in_buf.num_frames(),
193 in_buf.num_channels(), in_buf.channels());
194 if (process_reverse) {
195 in_rev_file->ReadSamples(in_rev_interleaved.size(),
196 in_rev_interleaved.data());
197 FloatS16ToFloat(in_rev_interleaved.data(), in_rev_interleaved.size(),
198 in_rev_interleaved.data());
199 Deinterleave(in_rev_interleaved.data(), in_rev_buf->num_frames(),
200 in_rev_buf->num_channels(), in_rev_buf->channels());
201 }
202
203 if (FLAGS_perf) {
204 processing_start_time = TickTime::Now();
205 }
206 RTC_CHECK_EQ(kNoErr, ap->ProcessStream(in_buf.channels(), input_config,
207 output_config, out_buf.channels()));
208 if (process_reverse) {
209 RTC_CHECK_EQ(kNoErr, ap->ProcessReverseStream(
210 in_rev_buf->channels(), reverse_input_config,
211 reverse_output_config, out_rev_buf->channels()));
212 }
213 if (FLAGS_perf) {
214 accumulated_time += TickTime::Now() - processing_start_time;
215 }
216
217 Interleave(out_buf.channels(), out_buf.num_frames(),
218 out_buf.num_channels(), &out_interleaved[0]);
219 FloatToFloatS16(&out_interleaved[0], out_interleaved.size(),
220 &out_interleaved[0]);
221 out_file.WriteSamples(&out_interleaved[0], out_interleaved.size());
222 if (process_reverse) {
223 Interleave(out_rev_buf->channels(), out_rev_buf->num_frames(),
224 out_rev_buf->num_channels(), out_rev_interleaved.data());
225 FloatToFloatS16(out_rev_interleaved.data(), out_rev_interleaved.size(),
226 out_rev_interleaved.data());
227 out_rev_file->WriteSamples(out_rev_interleaved.data(),
228 out_rev_interleaved.size());
229 }
230 num_chunks++;
231 }
232 if (FLAGS_perf) {
233 int64_t execution_time_ms = accumulated_time.Milliseconds();
234 printf("\nExecution time: %.3f s\nFile time: %.2f s\n"
235 "Time per chunk: %.3f ms\n",
236 execution_time_ms * 0.001f, num_chunks * 1.f / kChunksPerSecond,
237 execution_time_ms * 1.f / num_chunks);
238 }
239 return 0; 149 return 0;
240 } 150 }
241 151
242 } // namespace webrtc 152 } // namespace webrtc
243 153
244 int main(int argc, char* argv[]) { 154 int main(int argc, char* argv[]) {
245 return webrtc::main(argc, argv); 155 return webrtc::main(argc, argv);
246 } 156 }
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