blob: 576245f63a9b67851c15694d0091835586c5fb83 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
leozwang@webrtc.org9a85d8e2012-03-16 18:03:18 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
andrew@webrtc.org81865342012-10-27 00:28:27 +000011#include <math.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000012#include <stdio.h>
13#include <string.h>
14#ifdef WEBRTC_ANDROID
15#include <sys/stat.h>
16#endif
17
andrew@webrtc.org81865342012-10-27 00:28:27 +000018#include <algorithm>
kwiberg62eaacf2016-02-17 06:39:05 -080019#include <memory>
andrew@webrtc.org81865342012-10-27 00:28:27 +000020
Peter Kasting69558702016-01-12 16:26:35 -080021#include "webrtc/base/format_macros.h"
andrew@webrtc.org22858d42013-10-23 14:07:17 +000022#include "webrtc/common.h"
kma@webrtc.org0e739502012-12-07 15:26:28 +000023#include "webrtc/modules/audio_processing/include/audio_processing.h"
Andrew MacDonaldcb05b722015-05-07 22:17:51 -070024#include "webrtc/modules/audio_processing/test/protobuf_utils.h"
andrew@webrtc.orga8b97372014-03-10 22:26:12 +000025#include "webrtc/modules/audio_processing/test/test_utils.h"
Henrik Kjellanderff761fb2015-11-04 08:31:52 +010026#include "webrtc/modules/include/module_common_types.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010027#include "webrtc/system_wrappers/include/cpu_features_wrapper.h"
28#include "webrtc/system_wrappers/include/tick_util.h"
kjellander@webrtc.org10abe252012-12-17 18:28:07 +000029#include "webrtc/test/testsupport/fileutils.h"
kma@webrtc.org0e739502012-12-07 15:26:28 +000030#include "webrtc/test/testsupport/perf_test.h"
leozwang@webrtc.orga3736342012-03-16 21:36:00 +000031#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
pbos@webrtc.org8c34cee2013-05-28 09:24:03 +000032#include "gtest/gtest.h"
leozwang@webrtc.org534e4952012-10-22 21:21:52 +000033#include "external/webrtc/webrtc/modules/audio_processing/debug.pb.h"
leozwang@webrtc.orga3736342012-03-16 21:36:00 +000034#else
pbos@webrtc.org8c34cee2013-05-28 09:24:03 +000035#include "testing/gtest/include/gtest/gtest.h"
kjellander78ddd732016-02-09 08:13:06 -080036#include "webrtc/modules/audio_processing/debug.pb.h"
leozwang@webrtc.orga3736342012-03-16 21:36:00 +000037#endif
niklase@google.com470e71d2011-07-07 08:21:25 +000038
andrew@webrtc.orga8b97372014-03-10 22:26:12 +000039namespace webrtc {
andrew@webrtc.org3119ecf2011-11-01 17:00:18 +000040
ajm@google.com808e0e02011-08-03 21:08:51 +000041using webrtc::audioproc::Event;
42using webrtc::audioproc::Init;
43using webrtc::audioproc::ReverseStream;
44using webrtc::audioproc::Stream;
45
46namespace {
niklase@google.com470e71d2011-07-07 08:21:25 +000047
andrew@webrtc.org94c74132011-09-19 15:17:57 +000048void PrintStat(const AudioProcessing::Statistic& stat) {
49 printf("%d, %d, %d\n", stat.average,
50 stat.maximum,
51 stat.minimum);
52}
53
niklase@google.com470e71d2011-07-07 08:21:25 +000054void usage() {
55 printf(
ajm@google.com808e0e02011-08-03 21:08:51 +000056 "Usage: process_test [options] [-pb PROTOBUF_FILE]\n"
57 " [-ir REVERSE_FILE] [-i PRIMARY_FILE] [-o OUT_FILE]\n");
niklase@google.com470e71d2011-07-07 08:21:25 +000058 printf(
59 "process_test is a test application for AudioProcessing.\n\n"
andrew@webrtc.orga8b97372014-03-10 22:26:12 +000060 "When a protobuf debug file is available, specify it with -pb. Alternately,\n"
61 "when -ir or -i is used, the specified files will be processed directly in\n"
62 "a simulation mode. Otherwise the full set of legacy test files is expected\n"
63 "to be present in the working directory. OUT_FILE should be specified\n"
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +000064 "without extension to support both raw and wav output.\n\n");
niklase@google.com470e71d2011-07-07 08:21:25 +000065 printf("Options\n");
ajm@google.com808e0e02011-08-03 21:08:51 +000066 printf("General configuration (only used for the simulation mode):\n");
niklase@google.com470e71d2011-07-07 08:21:25 +000067 printf(" -fs SAMPLE_RATE_HZ\n");
68 printf(" -ch CHANNELS_IN CHANNELS_OUT\n");
69 printf(" -rch REVERSE_CHANNELS\n");
70 printf("\n");
71 printf("Component configuration:\n");
72 printf(
73 "All components are disabled by default. Each block below begins with a\n"
74 "flag to enable the component with default settings. The subsequent flags\n"
75 "in the block are used to provide configuration settings.\n");
76 printf("\n -aec Echo cancellation\n");
77 printf(" --drift_compensation\n");
78 printf(" --no_drift_compensation\n");
andrew@webrtc.org94c74132011-09-19 15:17:57 +000079 printf(" --no_echo_metrics\n");
bjornv@google.com1ba3dbe2011-10-03 08:18:10 +000080 printf(" --no_delay_logging\n");
andrew@webrtc.orgdff69c52013-04-30 23:01:09 +000081 printf(" --aec_suppression_level LEVEL [0 - 2]\n");
andrew@webrtc.org22858d42013-10-23 14:07:17 +000082 printf(" --extended_filter\n");
bjornv@webrtc.org84f8ec12014-06-19 12:14:33 +000083 printf(" --no_reported_delay\n");
peah6ebc4d32016-03-07 16:59:39 -080084 printf(" --aec3\n");
niklase@google.com470e71d2011-07-07 08:21:25 +000085 printf("\n -aecm Echo control mobile\n");
bjornv@google.com238a0222011-07-15 14:51:52 +000086 printf(" --aecm_echo_path_in_file FILE\n");
87 printf(" --aecm_echo_path_out_file FILE\n");
andrew@webrtc.org1acb3b32013-04-26 00:39:27 +000088 printf(" --no_comfort_noise\n");
89 printf(" --routing_mode MODE [0 - 4]\n");
niklase@google.com470e71d2011-07-07 08:21:25 +000090 printf("\n -agc Gain control\n");
91 printf(" --analog\n");
92 printf(" --adaptive_digital\n");
93 printf(" --fixed_digital\n");
94 printf(" --target_level LEVEL\n");
95 printf(" --compression_gain GAIN\n");
96 printf(" --limiter\n");
97 printf(" --no_limiter\n");
98 printf("\n -hpf High pass filter\n");
99 printf("\n -ns Noise suppression\n");
100 printf(" --ns_low\n");
101 printf(" --ns_moderate\n");
102 printf(" --ns_high\n");
103 printf(" --ns_very_high\n");
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000104 printf(" --ns_prob_file FILE\n");
niklase@google.com470e71d2011-07-07 08:21:25 +0000105 printf("\n -vad Voice activity detection\n");
ajm@google.com808e0e02011-08-03 21:08:51 +0000106 printf(" --vad_out_file FILE\n");
andrew@webrtc.orgb13a7d52014-03-27 00:11:11 +0000107 printf("\n -expns Experimental noise suppression\n");
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000108 printf("\n Level metrics (enabled by default)\n");
109 printf(" --no_level_metrics\n");
niklase@google.com470e71d2011-07-07 08:21:25 +0000110 printf("\n");
111 printf("Modifiers:\n");
andrew@webrtc.orgcb181212011-10-26 00:27:17 +0000112 printf(" --noasm Disable SSE optimization.\n");
andrew@webrtc.orgca764ab2013-10-07 16:44:32 +0000113 printf(" --add_delay DELAY Add DELAY ms to input value.\n");
114 printf(" --delay DELAY Override input delay with DELAY ms.\n");
andrew@webrtc.orgcb181212011-10-26 00:27:17 +0000115 printf(" --perf Measure performance.\n");
116 printf(" --quiet Suppress text output.\n");
117 printf(" --no_progress Suppress progress.\n");
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000118 printf(" --raw_output Raw output instead of WAV file.\n");
andrew@webrtc.orgcb181212011-10-26 00:27:17 +0000119 printf(" --debug_file FILE Dump a debug recording.\n");
niklase@google.com470e71d2011-07-07 08:21:25 +0000120}
121
andrew@webrtc.orgbafdae32013-01-11 23:11:29 +0000122static float MicLevel2Gain(int level) {
123 return pow(10.0f, ((level - 127.0f) / 128.0f * 40.0f) / 20.0f);
andrew@webrtc.org81865342012-10-27 00:28:27 +0000124}
125
126static void SimulateMic(int mic_level, AudioFrame* frame) {
127 mic_level = std::min(std::max(mic_level, 0), 255);
andrew@webrtc.orgbafdae32013-01-11 23:11:29 +0000128 float mic_gain = MicLevel2Gain(mic_level);
andrew@webrtc.org81865342012-10-27 00:28:27 +0000129 int num_samples = frame->samples_per_channel_ * frame->num_channels_;
andrew@webrtc.orgbafdae32013-01-11 23:11:29 +0000130 float v;
andrew@webrtc.org81865342012-10-27 00:28:27 +0000131 for (int n = 0; n < num_samples; n++) {
132 v = floor(frame->data_[n] * mic_gain + 0.5);
andrew@webrtc.orgbafdae32013-01-11 23:11:29 +0000133 v = std::max(std::min(32767.0f, v), -32768.0f);
andrew@webrtc.org81865342012-10-27 00:28:27 +0000134 frame->data_[n] = static_cast<int16_t>(v);
135 }
136}
137
niklase@google.com470e71d2011-07-07 08:21:25 +0000138// void function for gtest.
139void void_main(int argc, char* argv[]) {
140 if (argc > 1 && strcmp(argv[1], "--help") == 0) {
141 usage();
142 return;
143 }
144
145 if (argc < 2) {
146 printf("Did you mean to run without arguments?\n");
147 printf("Try `process_test --help' for more information.\n\n");
148 }
149
kwiberg62eaacf2016-02-17 06:39:05 -0800150 std::unique_ptr<AudioProcessing> apm(AudioProcessing::Create());
andrew@webrtc.orgf3930e92013-09-18 22:37:32 +0000151 ASSERT_TRUE(apm.get() != NULL);
niklase@google.com470e71d2011-07-07 08:21:25 +0000152
ajm@google.com808e0e02011-08-03 21:08:51 +0000153 const char* pb_filename = NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000154 const char* far_filename = NULL;
155 const char* near_filename = NULL;
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000156 std::string out_filename;
niklase@google.com470e71d2011-07-07 08:21:25 +0000157 const char* vad_out_filename = NULL;
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000158 const char* ns_prob_filename = NULL;
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000159 const char* aecm_echo_path_in_filename = NULL;
160 const char* aecm_echo_path_out_filename = NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000161
162 int32_t sample_rate_hz = 16000;
niklase@google.com470e71d2011-07-07 08:21:25 +0000163
Peter Kasting69558702016-01-12 16:26:35 -0800164 size_t num_capture_input_channels = 1;
165 size_t num_capture_output_channels = 1;
166 size_t num_render_channels = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000167
168 int samples_per_channel = sample_rate_hz / 100;
169
170 bool simulating = false;
171 bool perf_testing = false;
172 bool verbose = true;
173 bool progress = true;
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000174 bool raw_output = false;
andrew@webrtc.org4b13fc92011-11-09 19:27:11 +0000175 int extra_delay_ms = 0;
andrew@webrtc.orgca764ab2013-10-07 16:44:32 +0000176 int override_delay_ms = 0;
Bjorn Volckerbeb97982015-04-28 13:52:50 +0200177 Config config;
niklase@google.com470e71d2011-07-07 08:21:25 +0000178
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000179 ASSERT_EQ(apm->kNoError, apm->level_estimator()->Enable(true));
niklase@google.com470e71d2011-07-07 08:21:25 +0000180 for (int i = 1; i < argc; i++) {
andrew@webrtc.org94c74132011-09-19 15:17:57 +0000181 if (strcmp(argv[i], "-pb") == 0) {
ajm@google.com808e0e02011-08-03 21:08:51 +0000182 i++;
183 ASSERT_LT(i, argc) << "Specify protobuf filename after -pb";
184 pb_filename = argv[i];
185
186 } else if (strcmp(argv[i], "-ir") == 0) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000187 i++;
188 ASSERT_LT(i, argc) << "Specify filename after -ir";
189 far_filename = argv[i];
190 simulating = true;
191
192 } else if (strcmp(argv[i], "-i") == 0) {
193 i++;
194 ASSERT_LT(i, argc) << "Specify filename after -i";
195 near_filename = argv[i];
196 simulating = true;
197
198 } else if (strcmp(argv[i], "-o") == 0) {
199 i++;
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000200 ASSERT_LT(i, argc) << "Specify filename without extension after -o";
niklase@google.com470e71d2011-07-07 08:21:25 +0000201 out_filename = argv[i];
202
203 } else if (strcmp(argv[i], "-fs") == 0) {
204 i++;
205 ASSERT_LT(i, argc) << "Specify sample rate after -fs";
206 ASSERT_EQ(1, sscanf(argv[i], "%d", &sample_rate_hz));
207 samples_per_channel = sample_rate_hz / 100;
208
niklase@google.com470e71d2011-07-07 08:21:25 +0000209 } else if (strcmp(argv[i], "-ch") == 0) {
210 i++;
211 ASSERT_LT(i + 1, argc) << "Specify number of channels after -ch";
Peter Kasting69558702016-01-12 16:26:35 -0800212 ASSERT_EQ(1, sscanf(argv[i], "%" PRIuS, &num_capture_input_channels));
niklase@google.com470e71d2011-07-07 08:21:25 +0000213 i++;
Peter Kasting69558702016-01-12 16:26:35 -0800214 ASSERT_EQ(1, sscanf(argv[i], "%" PRIuS, &num_capture_output_channels));
niklase@google.com470e71d2011-07-07 08:21:25 +0000215
niklase@google.com470e71d2011-07-07 08:21:25 +0000216 } else if (strcmp(argv[i], "-rch") == 0) {
217 i++;
218 ASSERT_LT(i, argc) << "Specify number of channels after -rch";
Peter Kasting69558702016-01-12 16:26:35 -0800219 ASSERT_EQ(1, sscanf(argv[i], "%" PRIuS, &num_render_channels));
niklase@google.com470e71d2011-07-07 08:21:25 +0000220
niklase@google.com470e71d2011-07-07 08:21:25 +0000221 } else if (strcmp(argv[i], "-aec") == 0) {
222 ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
bjornv@google.com1ba3dbe2011-10-03 08:18:10 +0000223 ASSERT_EQ(apm->kNoError,
224 apm->echo_cancellation()->enable_metrics(true));
225 ASSERT_EQ(apm->kNoError,
226 apm->echo_cancellation()->enable_delay_logging(true));
niklase@google.com470e71d2011-07-07 08:21:25 +0000227
niklase@google.com470e71d2011-07-07 08:21:25 +0000228 } else if (strcmp(argv[i], "--drift_compensation") == 0) {
229 ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
230 // TODO(ajm): this is enabled in the VQE test app by default. Investigate
231 // why it can give better performance despite passing zeros.
232 ASSERT_EQ(apm->kNoError,
233 apm->echo_cancellation()->enable_drift_compensation(true));
234 } else if (strcmp(argv[i], "--no_drift_compensation") == 0) {
235 ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
236 ASSERT_EQ(apm->kNoError,
237 apm->echo_cancellation()->enable_drift_compensation(false));
238
andrew@webrtc.org94c74132011-09-19 15:17:57 +0000239 } else if (strcmp(argv[i], "--no_echo_metrics") == 0) {
240 ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
241 ASSERT_EQ(apm->kNoError,
242 apm->echo_cancellation()->enable_metrics(false));
243
bjornv@google.com1ba3dbe2011-10-03 08:18:10 +0000244 } else if (strcmp(argv[i], "--no_delay_logging") == 0) {
245 ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
246 ASSERT_EQ(apm->kNoError,
247 apm->echo_cancellation()->enable_delay_logging(false));
248
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000249 } else if (strcmp(argv[i], "--no_level_metrics") == 0) {
250 ASSERT_EQ(apm->kNoError, apm->level_estimator()->Enable(false));
251
andrew@webrtc.orgdff69c52013-04-30 23:01:09 +0000252 } else if (strcmp(argv[i], "--aec_suppression_level") == 0) {
253 i++;
254 ASSERT_LT(i, argc) << "Specify level after --aec_suppression_level";
255 int suppression_level;
256 ASSERT_EQ(1, sscanf(argv[i], "%d", &suppression_level));
257 ASSERT_EQ(apm->kNoError,
258 apm->echo_cancellation()->set_suppression_level(
259 static_cast<webrtc::EchoCancellation::SuppressionLevel>(
260 suppression_level)));
261
andrew@webrtc.org22858d42013-10-23 14:07:17 +0000262 } else if (strcmp(argv[i], "--extended_filter") == 0) {
Henrik Lundin441f6342015-06-09 16:03:13 +0200263 config.Set<ExtendedFilter>(new ExtendedFilter(true));
andrew@webrtc.org22858d42013-10-23 14:07:17 +0000264
bjornv@webrtc.org84f8ec12014-06-19 12:14:33 +0000265 } else if (strcmp(argv[i], "--no_reported_delay") == 0) {
henrik.lundin0f133b92015-07-02 00:17:55 -0700266 config.Set<DelayAgnostic>(new DelayAgnostic(true));
267
268 } else if (strcmp(argv[i], "--delay_agnostic") == 0) {
269 config.Set<DelayAgnostic>(new DelayAgnostic(true));
bjornv@webrtc.org84f8ec12014-06-19 12:14:33 +0000270
peah6ebc4d32016-03-07 16:59:39 -0800271 } else if (strcmp(argv[i], "--aec3") == 0) {
272 config.Set<EchoCanceller3>(new EchoCanceller3(true));
peaha332e2d2016-02-17 01:11:16 -0800273
niklase@google.com470e71d2011-07-07 08:21:25 +0000274 } else if (strcmp(argv[i], "-aecm") == 0) {
275 ASSERT_EQ(apm->kNoError, apm->echo_control_mobile()->Enable(true));
276
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000277 } else if (strcmp(argv[i], "--aecm_echo_path_in_file") == 0) {
278 i++;
279 ASSERT_LT(i, argc) << "Specify filename after --aecm_echo_path_in_file";
280 aecm_echo_path_in_filename = argv[i];
281
282 } else if (strcmp(argv[i], "--aecm_echo_path_out_file") == 0) {
283 i++;
284 ASSERT_LT(i, argc) << "Specify filename after --aecm_echo_path_out_file";
285 aecm_echo_path_out_filename = argv[i];
286
andrew@webrtc.org1acb3b32013-04-26 00:39:27 +0000287 } else if (strcmp(argv[i], "--no_comfort_noise") == 0) {
288 ASSERT_EQ(apm->kNoError,
289 apm->echo_control_mobile()->enable_comfort_noise(false));
290
291 } else if (strcmp(argv[i], "--routing_mode") == 0) {
292 i++;
293 ASSERT_LT(i, argc) << "Specify mode after --routing_mode";
294 int routing_mode;
295 ASSERT_EQ(1, sscanf(argv[i], "%d", &routing_mode));
296 ASSERT_EQ(apm->kNoError,
297 apm->echo_control_mobile()->set_routing_mode(
298 static_cast<webrtc::EchoControlMobile::RoutingMode>(
299 routing_mode)));
300
niklase@google.com470e71d2011-07-07 08:21:25 +0000301 } else if (strcmp(argv[i], "-agc") == 0) {
302 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
303
304 } else if (strcmp(argv[i], "--analog") == 0) {
305 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
306 ASSERT_EQ(apm->kNoError,
307 apm->gain_control()->set_mode(GainControl::kAdaptiveAnalog));
308
309 } else if (strcmp(argv[i], "--adaptive_digital") == 0) {
310 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
311 ASSERT_EQ(apm->kNoError,
312 apm->gain_control()->set_mode(GainControl::kAdaptiveDigital));
313
314 } else if (strcmp(argv[i], "--fixed_digital") == 0) {
315 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
316 ASSERT_EQ(apm->kNoError,
317 apm->gain_control()->set_mode(GainControl::kFixedDigital));
318
319 } else if (strcmp(argv[i], "--target_level") == 0) {
320 i++;
321 int level;
322 ASSERT_EQ(1, sscanf(argv[i], "%d", &level));
323
324 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
325 ASSERT_EQ(apm->kNoError,
326 apm->gain_control()->set_target_level_dbfs(level));
327
328 } else if (strcmp(argv[i], "--compression_gain") == 0) {
329 i++;
330 int gain;
331 ASSERT_EQ(1, sscanf(argv[i], "%d", &gain));
332
333 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
334 ASSERT_EQ(apm->kNoError,
335 apm->gain_control()->set_compression_gain_db(gain));
336
337 } else if (strcmp(argv[i], "--limiter") == 0) {
338 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
339 ASSERT_EQ(apm->kNoError,
340 apm->gain_control()->enable_limiter(true));
341
342 } else if (strcmp(argv[i], "--no_limiter") == 0) {
343 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
344 ASSERT_EQ(apm->kNoError,
345 apm->gain_control()->enable_limiter(false));
346
347 } else if (strcmp(argv[i], "-hpf") == 0) {
348 ASSERT_EQ(apm->kNoError, apm->high_pass_filter()->Enable(true));
349
350 } else if (strcmp(argv[i], "-ns") == 0) {
351 ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(true));
352
353 } else if (strcmp(argv[i], "--ns_low") == 0) {
354 ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(true));
355 ASSERT_EQ(apm->kNoError,
356 apm->noise_suppression()->set_level(NoiseSuppression::kLow));
357
358 } else if (strcmp(argv[i], "--ns_moderate") == 0) {
359 ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(true));
360 ASSERT_EQ(apm->kNoError,
361 apm->noise_suppression()->set_level(NoiseSuppression::kModerate));
362
363 } else if (strcmp(argv[i], "--ns_high") == 0) {
364 ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(true));
365 ASSERT_EQ(apm->kNoError,
366 apm->noise_suppression()->set_level(NoiseSuppression::kHigh));
367
368 } else if (strcmp(argv[i], "--ns_very_high") == 0) {
369 ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(true));
370 ASSERT_EQ(apm->kNoError,
371 apm->noise_suppression()->set_level(NoiseSuppression::kVeryHigh));
372
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000373 } else if (strcmp(argv[i], "--ns_prob_file") == 0) {
374 i++;
375 ASSERT_LT(i, argc) << "Specify filename after --ns_prob_file";
376 ns_prob_filename = argv[i];
377
niklase@google.com470e71d2011-07-07 08:21:25 +0000378 } else if (strcmp(argv[i], "-vad") == 0) {
379 ASSERT_EQ(apm->kNoError, apm->voice_detection()->Enable(true));
380
andrew@webrtc.org89752612012-10-12 16:41:45 +0000381 } else if (strcmp(argv[i], "--vad_very_low") == 0) {
382 ASSERT_EQ(apm->kNoError, apm->voice_detection()->Enable(true));
383 ASSERT_EQ(apm->kNoError,
384 apm->voice_detection()->set_likelihood(
385 VoiceDetection::kVeryLowLikelihood));
386
387 } else if (strcmp(argv[i], "--vad_low") == 0) {
388 ASSERT_EQ(apm->kNoError, apm->voice_detection()->Enable(true));
389 ASSERT_EQ(apm->kNoError,
390 apm->voice_detection()->set_likelihood(
391 VoiceDetection::kLowLikelihood));
392
393 } else if (strcmp(argv[i], "--vad_moderate") == 0) {
394 ASSERT_EQ(apm->kNoError, apm->voice_detection()->Enable(true));
395 ASSERT_EQ(apm->kNoError,
396 apm->voice_detection()->set_likelihood(
397 VoiceDetection::kModerateLikelihood));
398
399 } else if (strcmp(argv[i], "--vad_high") == 0) {
400 ASSERT_EQ(apm->kNoError, apm->voice_detection()->Enable(true));
401 ASSERT_EQ(apm->kNoError,
402 apm->voice_detection()->set_likelihood(
403 VoiceDetection::kHighLikelihood));
404
niklase@google.com470e71d2011-07-07 08:21:25 +0000405 } else if (strcmp(argv[i], "--vad_out_file") == 0) {
406 i++;
407 ASSERT_LT(i, argc) << "Specify filename after --vad_out_file";
408 vad_out_filename = argv[i];
409
aluebs@webrtc.orgbc1d2242014-02-25 16:50:22 +0000410 } else if (strcmp(argv[i], "-expns") == 0) {
aluebs@webrtc.org9825afc2014-06-30 17:39:53 +0000411 config.Set<ExperimentalNs>(new ExperimentalNs(true));
aluebs@webrtc.orgbc1d2242014-02-25 16:50:22 +0000412
andrew@webrtc.org94c74132011-09-19 15:17:57 +0000413 } else if (strcmp(argv[i], "--noasm") == 0) {
414 WebRtc_GetCPUInfo = WebRtc_GetCPUInfoNoASM;
415 // We need to reinitialize here if components have already been enabled.
416 ASSERT_EQ(apm->kNoError, apm->Initialize());
417
andrew@webrtc.orgca764ab2013-10-07 16:44:32 +0000418 } else if (strcmp(argv[i], "--add_delay") == 0) {
andrew@webrtc.org4b13fc92011-11-09 19:27:11 +0000419 i++;
420 ASSERT_EQ(1, sscanf(argv[i], "%d", &extra_delay_ms));
421
andrew@webrtc.orgca764ab2013-10-07 16:44:32 +0000422 } else if (strcmp(argv[i], "--delay") == 0) {
423 i++;
424 ASSERT_EQ(1, sscanf(argv[i], "%d", &override_delay_ms));
425
niklase@google.com470e71d2011-07-07 08:21:25 +0000426 } else if (strcmp(argv[i], "--perf") == 0) {
427 perf_testing = true;
428
429 } else if (strcmp(argv[i], "--quiet") == 0) {
430 verbose = false;
431 progress = false;
432
433 } else if (strcmp(argv[i], "--no_progress") == 0) {
434 progress = false;
435
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000436 } else if (strcmp(argv[i], "--raw_output") == 0) {
437 raw_output = true;
438
andrew@webrtc.orgcb181212011-10-26 00:27:17 +0000439 } else if (strcmp(argv[i], "--debug_file") == 0) {
ajm@google.com808e0e02011-08-03 21:08:51 +0000440 i++;
andrew@webrtc.orgcb181212011-10-26 00:27:17 +0000441 ASSERT_LT(i, argc) << "Specify filename after --debug_file";
ivocd66b44d2016-01-15 03:06:36 -0800442 ASSERT_EQ(apm->kNoError, apm->StartDebugRecording(argv[i], -1));
niklase@google.com470e71d2011-07-07 08:21:25 +0000443 } else {
444 FAIL() << "Unrecognized argument " << argv[i];
445 }
446 }
Bjorn Volckerbeb97982015-04-28 13:52:50 +0200447 apm->SetExtraOptions(config);
448
ajm@google.com808e0e02011-08-03 21:08:51 +0000449 // If we're reading a protobuf file, ensure a simulation hasn't also
450 // been requested (which makes no sense...)
451 ASSERT_FALSE(pb_filename && simulating);
niklase@google.com470e71d2011-07-07 08:21:25 +0000452
453 if (verbose) {
454 printf("Sample rate: %d Hz\n", sample_rate_hz);
Peter Kasting69558702016-01-12 16:26:35 -0800455 printf("Primary channels: %" PRIuS " (in), %" PRIuS " (out)\n",
niklase@google.com470e71d2011-07-07 08:21:25 +0000456 num_capture_input_channels,
457 num_capture_output_channels);
Peter Kasting69558702016-01-12 16:26:35 -0800458 printf("Reverse channels: %" PRIuS "\n", num_render_channels);
niklase@google.com470e71d2011-07-07 08:21:25 +0000459 }
460
kjellander@webrtc.org10abe252012-12-17 18:28:07 +0000461 const std::string out_path = webrtc::test::OutputPath();
niklase@google.com470e71d2011-07-07 08:21:25 +0000462 const char far_file_default[] = "apm_far.pcm";
463 const char near_file_default[] = "apm_near.pcm";
niklase@google.com470e71d2011-07-07 08:21:25 +0000464 const char event_filename[] = "apm_event.dat";
465 const char delay_filename[] = "apm_delay.dat";
466 const char drift_filename[] = "apm_drift.dat";
kjellander@webrtc.org10abe252012-12-17 18:28:07 +0000467 const std::string vad_file_default = out_path + "vad_out.dat";
468 const std::string ns_prob_file_default = out_path + "ns_prob.dat";
niklase@google.com470e71d2011-07-07 08:21:25 +0000469
470 if (!simulating) {
471 far_filename = far_file_default;
472 near_filename = near_file_default;
473 }
474
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000475 if (out_filename.size() == 0) {
476 out_filename = out_path + "out";
niklase@google.com470e71d2011-07-07 08:21:25 +0000477 }
478
ajm@google.com808e0e02011-08-03 21:08:51 +0000479 if (!vad_out_filename) {
kjellander@webrtc.org10abe252012-12-17 18:28:07 +0000480 vad_out_filename = vad_file_default.c_str();
niklase@google.com470e71d2011-07-07 08:21:25 +0000481 }
482
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000483 if (!ns_prob_filename) {
kjellander@webrtc.org10abe252012-12-17 18:28:07 +0000484 ns_prob_filename = ns_prob_file_default.c_str();
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000485 }
486
ajm@google.com808e0e02011-08-03 21:08:51 +0000487 FILE* pb_file = NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000488 FILE* far_file = NULL;
489 FILE* near_file = NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000490 FILE* event_file = NULL;
491 FILE* delay_file = NULL;
492 FILE* drift_file = NULL;
493 FILE* vad_out_file = NULL;
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000494 FILE* ns_prob_file = NULL;
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000495 FILE* aecm_echo_path_in_file = NULL;
496 FILE* aecm_echo_path_out_file = NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000497
kwiberg62eaacf2016-02-17 06:39:05 -0800498 std::unique_ptr<WavWriter> output_wav_file;
499 std::unique_ptr<RawFile> output_raw_file;
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000500
ajm@google.com808e0e02011-08-03 21:08:51 +0000501 if (pb_filename) {
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000502 pb_file = OpenFile(pb_filename, "rb");
ajm@google.com808e0e02011-08-03 21:08:51 +0000503 } else {
504 if (far_filename) {
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000505 far_file = OpenFile(far_filename, "rb");
ajm@google.com808e0e02011-08-03 21:08:51 +0000506 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000507
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000508 near_file = OpenFile(near_filename, "rb");
ajm@google.com808e0e02011-08-03 21:08:51 +0000509 if (!simulating) {
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000510 event_file = OpenFile(event_filename, "rb");
511 delay_file = OpenFile(delay_filename, "rb");
512 drift_file = OpenFile(drift_filename, "rb");
ajm@google.com808e0e02011-08-03 21:08:51 +0000513 }
514 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000515
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000516 int near_size_bytes = 0;
ajm@google.com808e0e02011-08-03 21:08:51 +0000517 if (pb_file) {
518 struct stat st;
519 stat(pb_filename, &st);
520 // Crude estimate, but should be good enough.
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000521 near_size_bytes = st.st_size / 3;
ajm@google.com808e0e02011-08-03 21:08:51 +0000522 } else {
523 struct stat st;
524 stat(near_filename, &st);
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000525 near_size_bytes = st.st_size;
niklase@google.com470e71d2011-07-07 08:21:25 +0000526 }
527
528 if (apm->voice_detection()->is_enabled()) {
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000529 vad_out_file = OpenFile(vad_out_filename, "wb");
niklase@google.com470e71d2011-07-07 08:21:25 +0000530 }
531
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000532 if (apm->noise_suppression()->is_enabled()) {
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000533 ns_prob_file = OpenFile(ns_prob_filename, "wb");
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000534 }
535
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000536 if (aecm_echo_path_in_filename != NULL) {
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000537 aecm_echo_path_in_file = OpenFile(aecm_echo_path_in_filename, "rb");
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000538
ajm@google.com22e65152011-07-18 18:03:01 +0000539 const size_t path_size =
540 apm->echo_control_mobile()->echo_path_size_bytes();
kwiberg62eaacf2016-02-17 06:39:05 -0800541 std::unique_ptr<char[]> echo_path(new char[path_size]);
andrew@webrtc.org3119ecf2011-11-01 17:00:18 +0000542 ASSERT_EQ(path_size, fread(echo_path.get(),
543 sizeof(char),
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000544 path_size,
545 aecm_echo_path_in_file));
546 EXPECT_EQ(apm->kNoError,
andrew@webrtc.org3119ecf2011-11-01 17:00:18 +0000547 apm->echo_control_mobile()->SetEchoPath(echo_path.get(),
548 path_size));
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000549 fclose(aecm_echo_path_in_file);
550 aecm_echo_path_in_file = NULL;
551 }
552
553 if (aecm_echo_path_out_filename != NULL) {
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000554 aecm_echo_path_out_file = OpenFile(aecm_echo_path_out_filename, "wb");
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000555 }
556
niklase@google.com470e71d2011-07-07 08:21:25 +0000557 size_t read_count = 0;
558 int reverse_count = 0;
559 int primary_count = 0;
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000560 int near_read_bytes = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000561 TickInterval acc_ticks;
562
563 AudioFrame far_frame;
niklase@google.com470e71d2011-07-07 08:21:25 +0000564 AudioFrame near_frame;
niklase@google.com470e71d2011-07-07 08:21:25 +0000565
566 int delay_ms = 0;
567 int drift_samples = 0;
568 int capture_level = 127;
569 int8_t stream_has_voice = 0;
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000570 float ns_speech_prob = 0.0f;
niklase@google.com470e71d2011-07-07 08:21:25 +0000571
572 TickTime t0 = TickTime::Now();
573 TickTime t1 = t0;
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000574 int64_t max_time_us = 0;
575 int64_t max_time_reverse_us = 0;
576 int64_t min_time_us = 1e6;
577 int64_t min_time_reverse_us = 1e6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000578
ajm@google.com808e0e02011-08-03 21:08:51 +0000579 // TODO(ajm): Ideally we would refactor this block into separate functions,
580 // but for now we want to share the variables.
581 if (pb_file) {
582 Event event_msg;
kwiberg62eaacf2016-02-17 06:39:05 -0800583 std::unique_ptr<ChannelBuffer<float> > reverse_cb;
584 std::unique_ptr<ChannelBuffer<float> > primary_cb;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000585 int output_sample_rate = 32000;
586 AudioProcessing::ChannelLayout output_layout = AudioProcessing::kMono;
ajm@google.com808e0e02011-08-03 21:08:51 +0000587 while (ReadMessageFromFile(pb_file, &event_msg)) {
588 std::ostringstream trace_stream;
589 trace_stream << "Processed frames: " << reverse_count << " (reverse), "
590 << primary_count << " (primary)";
591 SCOPED_TRACE(trace_stream.str());
niklase@google.com470e71d2011-07-07 08:21:25 +0000592
ajm@google.com808e0e02011-08-03 21:08:51 +0000593 if (event_msg.type() == Event::INIT) {
594 ASSERT_TRUE(event_msg.has_init());
595 const Init msg = event_msg.init();
niklase@google.com470e71d2011-07-07 08:21:25 +0000596
ajm@google.com808e0e02011-08-03 21:08:51 +0000597 ASSERT_TRUE(msg.has_sample_rate());
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000598 ASSERT_TRUE(msg.has_num_input_channels());
599 ASSERT_TRUE(msg.has_num_output_channels());
600 ASSERT_TRUE(msg.has_num_reverse_channels());
601 int reverse_sample_rate = msg.sample_rate();
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000602 if (msg.has_reverse_sample_rate()) {
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000603 reverse_sample_rate = msg.reverse_sample_rate();
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000604 }
605 output_sample_rate = msg.sample_rate();
606 if (msg.has_output_sample_rate()) {
607 output_sample_rate = msg.output_sample_rate();
608 }
Peter Kasting69558702016-01-12 16:26:35 -0800609 output_layout =
610 LayoutFromChannels(static_cast<size_t>(msg.num_output_channels()));
611 ASSERT_EQ(kNoErr,
612 apm->Initialize(
613 msg.sample_rate(),
614 output_sample_rate,
615 reverse_sample_rate,
616 LayoutFromChannels(
617 static_cast<size_t>(msg.num_input_channels())),
618 output_layout,
619 LayoutFromChannels(
620 static_cast<size_t>(msg.num_reverse_channels()))));
ajm@google.com808e0e02011-08-03 21:08:51 +0000621
622 samples_per_channel = msg.sample_rate() / 100;
bjornv@webrtc.orgee300822014-11-13 11:00:10 +0000623 far_frame.sample_rate_hz_ = reverse_sample_rate;
aluebs@webrtc.org74cf9162014-09-03 11:05:01 +0000624 far_frame.samples_per_channel_ = reverse_sample_rate / 100;
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000625 far_frame.num_channels_ = msg.num_reverse_channels();
626 near_frame.sample_rate_hz_ = msg.sample_rate();
627 near_frame.samples_per_channel_ = samples_per_channel;
andrew@webrtc.orgbafdae32013-01-11 23:11:29 +0000628 near_frame.num_channels_ = msg.num_input_channels();
aluebs@webrtc.org74cf9162014-09-03 11:05:01 +0000629 reverse_cb.reset(new ChannelBuffer<float>(
630 far_frame.samples_per_channel_,
631 msg.num_reverse_channels()));
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000632 primary_cb.reset(new ChannelBuffer<float>(samples_per_channel,
633 msg.num_input_channels()));
ajm@google.com808e0e02011-08-03 21:08:51 +0000634
635 if (verbose) {
636 printf("Init at frame: %d (primary), %d (reverse)\n",
637 primary_count, reverse_count);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000638 printf(" Primary rates: %d Hz (in), %d Hz (out)\n",
639 msg.sample_rate(), output_sample_rate);
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000640 printf(" Primary channels: %d (in), %d (out)\n",
641 msg.num_input_channels(),
642 msg.num_output_channels());
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000643 printf(" Reverse rate: %d\n", reverse_sample_rate);
644 printf(" Reverse channels: %d\n", msg.num_reverse_channels());
ajm@google.com808e0e02011-08-03 21:08:51 +0000645 }
646
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000647 if (!raw_output) {
aluebsb0ad43b2015-11-20 00:11:53 -0800648 // The WAV file needs to be reset every time, because it can't change
649 // its sample rate or number of channels.
Peter Kasting69558702016-01-12 16:26:35 -0800650 output_wav_file.reset(new WavWriter(
651 out_filename + ".wav", output_sample_rate,
652 static_cast<size_t>(msg.num_output_channels())));
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000653 }
654
ajm@google.com808e0e02011-08-03 21:08:51 +0000655 } else if (event_msg.type() == Event::REVERSE_STREAM) {
656 ASSERT_TRUE(event_msg.has_reverse_stream());
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000657 ReverseStream msg = event_msg.reverse_stream();
ajm@google.com808e0e02011-08-03 21:08:51 +0000658 reverse_count++;
659
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000660 ASSERT_TRUE(msg.has_data() ^ (msg.channel_size() > 0));
661 if (msg.has_data()) {
aluebs@webrtc.org74cf9162014-09-03 11:05:01 +0000662 ASSERT_EQ(sizeof(int16_t) * far_frame.samples_per_channel_ *
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000663 far_frame.num_channels_, msg.data().size());
664 memcpy(far_frame.data_, msg.data().data(), msg.data().size());
665 } else {
666 for (int i = 0; i < msg.channel_size(); ++i) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000667 memcpy(reverse_cb->channels()[i],
668 msg.channel(i).data(),
669 reverse_cb->num_frames() *
670 sizeof(reverse_cb->channels()[i][0]));
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000671 }
672 }
ajm@google.com808e0e02011-08-03 21:08:51 +0000673
674 if (perf_testing) {
675 t0 = TickTime::Now();
676 }
677
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000678 if (msg.has_data()) {
679 ASSERT_EQ(apm->kNoError,
680 apm->AnalyzeReverseStream(&far_frame));
681 } else {
682 ASSERT_EQ(apm->kNoError,
683 apm->AnalyzeReverseStream(
684 reverse_cb->channels(),
685 far_frame.samples_per_channel_,
686 far_frame.sample_rate_hz_,
687 LayoutFromChannels(far_frame.num_channels_)));
688 }
ajm@google.com808e0e02011-08-03 21:08:51 +0000689
690 if (perf_testing) {
691 t1 = TickTime::Now();
692 TickInterval tick_diff = t1 - t0;
693 acc_ticks += tick_diff;
694 if (tick_diff.Microseconds() > max_time_reverse_us) {
695 max_time_reverse_us = tick_diff.Microseconds();
696 }
697 if (tick_diff.Microseconds() < min_time_reverse_us) {
698 min_time_reverse_us = tick_diff.Microseconds();
699 }
700 }
701
702 } else if (event_msg.type() == Event::STREAM) {
703 ASSERT_TRUE(event_msg.has_stream());
704 const Stream msg = event_msg.stream();
705 primary_count++;
706
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000707 // ProcessStream could have changed this for the output frame.
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000708 near_frame.num_channels_ = apm->num_input_channels();
ajm@google.com808e0e02011-08-03 21:08:51 +0000709
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000710 ASSERT_TRUE(msg.has_input_data() ^ (msg.input_channel_size() > 0));
711 if (msg.has_input_data()) {
712 ASSERT_EQ(sizeof(int16_t) * samples_per_channel *
713 near_frame.num_channels_, msg.input_data().size());
714 memcpy(near_frame.data_,
715 msg.input_data().data(),
716 msg.input_data().size());
aluebs@webrtc.org74cf9162014-09-03 11:05:01 +0000717 near_read_bytes += msg.input_data().size();
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000718 } else {
719 for (int i = 0; i < msg.input_channel_size(); ++i) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000720 memcpy(primary_cb->channels()[i],
721 msg.input_channel(i).data(),
722 primary_cb->num_frames() *
723 sizeof(primary_cb->channels()[i][0]));
aluebs@webrtc.org74cf9162014-09-03 11:05:01 +0000724 near_read_bytes += msg.input_channel(i).size();
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000725 }
726 }
ajm@google.com808e0e02011-08-03 21:08:51 +0000727
ajm@google.com808e0e02011-08-03 21:08:51 +0000728 if (progress && primary_count % 100 == 0) {
aluebs@webrtc.org74cf9162014-09-03 11:05:01 +0000729 near_read_bytes = std::min(near_read_bytes, near_size_bytes);
ajm@google.com808e0e02011-08-03 21:08:51 +0000730 printf("%.0f%% complete\r",
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000731 (near_read_bytes * 100.0) / near_size_bytes);
ajm@google.com808e0e02011-08-03 21:08:51 +0000732 fflush(stdout);
733 }
734
735 if (perf_testing) {
736 t0 = TickTime::Now();
737 }
738
739 ASSERT_EQ(apm->kNoError,
740 apm->gain_control()->set_stream_analog_level(msg.level()));
andrew@webrtc.orgca764ab2013-10-07 16:44:32 +0000741 delay_ms = msg.delay() + extra_delay_ms;
742 if (override_delay_ms) {
743 delay_ms = override_delay_ms;
744 }
ajm@google.com808e0e02011-08-03 21:08:51 +0000745 ASSERT_EQ(apm->kNoError,
andrew@webrtc.orgca764ab2013-10-07 16:44:32 +0000746 apm->set_stream_delay_ms(delay_ms));
andrew@webrtc.org6be1e932013-03-01 18:47:28 +0000747 apm->echo_cancellation()->set_stream_drift_samples(msg.drift());
ajm@google.com808e0e02011-08-03 21:08:51 +0000748
aluebs@webrtc.orgbc1d2242014-02-25 16:50:22 +0000749 if (msg.has_keypress()) {
750 apm->set_stream_key_pressed(msg.keypress());
751 } else {
752 apm->set_stream_key_pressed(true);
753 }
754
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000755 int err = apm->kNoError;
756 if (msg.has_input_data()) {
757 err = apm->ProcessStream(&near_frame);
758 ASSERT_TRUE(near_frame.num_channels_ == apm->num_output_channels());
759 } else {
760 err = apm->ProcessStream(
761 primary_cb->channels(),
762 near_frame.samples_per_channel_,
763 near_frame.sample_rate_hz_,
764 LayoutFromChannels(near_frame.num_channels_),
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000765 output_sample_rate,
766 output_layout,
767 primary_cb->channels());
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000768 }
769
ajm@google.com808e0e02011-08-03 21:08:51 +0000770 if (err == apm->kBadStreamParameterWarning) {
771 printf("Bad parameter warning. %s\n", trace_stream.str().c_str());
772 }
773 ASSERT_TRUE(err == apm->kNoError ||
774 err == apm->kBadStreamParameterWarning);
775
ajm@google.com808e0e02011-08-03 21:08:51 +0000776 stream_has_voice =
777 static_cast<int8_t>(apm->voice_detection()->stream_has_voice());
778 if (vad_out_file != NULL) {
779 ASSERT_EQ(1u, fwrite(&stream_has_voice,
780 sizeof(stream_has_voice),
781 1,
782 vad_out_file));
783 }
784
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000785 if (ns_prob_file != NULL) {
786 ns_speech_prob = apm->noise_suppression()->speech_probability();
787 ASSERT_EQ(1u, fwrite(&ns_speech_prob,
788 sizeof(ns_speech_prob),
789 1,
790 ns_prob_file));
791 }
792
ajm@google.com808e0e02011-08-03 21:08:51 +0000793 if (perf_testing) {
794 t1 = TickTime::Now();
795 TickInterval tick_diff = t1 - t0;
796 acc_ticks += tick_diff;
797 if (tick_diff.Microseconds() > max_time_us) {
798 max_time_us = tick_diff.Microseconds();
799 }
800 if (tick_diff.Microseconds() < min_time_us) {
801 min_time_us = tick_diff.Microseconds();
802 }
803 }
804
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000805 const size_t samples_per_channel = output_sample_rate / 100;
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000806 if (msg.has_input_data()) {
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000807 if (raw_output && !output_raw_file) {
808 output_raw_file.reset(new RawFile(out_filename + ".pcm"));
809 }
810 WriteIntData(near_frame.data_,
811 apm->num_output_channels() * samples_per_channel,
812 output_wav_file.get(),
813 output_raw_file.get());
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000814 } else {
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000815 if (raw_output && !output_raw_file) {
816 output_raw_file.reset(new RawFile(out_filename + ".float"));
817 }
818 WriteFloatData(primary_cb->channels(),
819 samples_per_channel,
820 apm->num_output_channels(),
821 output_wav_file.get(),
822 output_raw_file.get());
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000823 }
ajm@google.com808e0e02011-08-03 21:08:51 +0000824 }
825 }
826
827 ASSERT_TRUE(feof(pb_file));
ajm@google.com808e0e02011-08-03 21:08:51 +0000828
829 } else {
bjornv@google.coma2c6ea02011-09-27 08:04:45 +0000830 enum Events {
831 kInitializeEvent,
832 kRenderEvent,
833 kCaptureEvent,
834 kResetEventDeprecated
835 };
836 int16_t event = 0;
ajm@google.com808e0e02011-08-03 21:08:51 +0000837 while (simulating || feof(event_file) == 0) {
838 std::ostringstream trace_stream;
839 trace_stream << "Processed frames: " << reverse_count << " (reverse), "
840 << primary_count << " (primary)";
841 SCOPED_TRACE(trace_stream.str());
842
843 if (simulating) {
844 if (far_file == NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000845 event = kCaptureEvent;
846 } else {
peah58cf5f12016-02-16 07:26:21 -0800847 event = (event == kCaptureEvent) ? kRenderEvent : kCaptureEvent;
niklase@google.com470e71d2011-07-07 08:21:25 +0000848 }
849 } else {
ajm@google.com808e0e02011-08-03 21:08:51 +0000850 read_count = fread(&event, sizeof(event), 1, event_file);
851 if (read_count != 1) {
852 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000853 }
854 }
855
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000856 far_frame.sample_rate_hz_ = sample_rate_hz;
857 far_frame.samples_per_channel_ = samples_per_channel;
858 far_frame.num_channels_ = num_render_channels;
859 near_frame.sample_rate_hz_ = sample_rate_hz;
860 near_frame.samples_per_channel_ = samples_per_channel;
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000861
ajm@google.com808e0e02011-08-03 21:08:51 +0000862 if (event == kInitializeEvent || event == kResetEventDeprecated) {
863 ASSERT_EQ(1u,
864 fread(&sample_rate_hz, sizeof(sample_rate_hz), 1, event_file));
865 samples_per_channel = sample_rate_hz / 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000866
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000867 int32_t unused_device_sample_rate_hz;
ajm@google.com808e0e02011-08-03 21:08:51 +0000868 ASSERT_EQ(1u,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000869 fread(&unused_device_sample_rate_hz,
870 sizeof(unused_device_sample_rate_hz),
ajm@google.com808e0e02011-08-03 21:08:51 +0000871 1,
872 event_file));
873
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000874 ASSERT_EQ(kNoErr, apm->Initialize(
875 sample_rate_hz,
876 sample_rate_hz,
877 sample_rate_hz,
878 LayoutFromChannels(num_capture_input_channels),
879 LayoutFromChannels(num_capture_output_channels),
880 LayoutFromChannels(num_render_channels)));
ajm@google.com808e0e02011-08-03 21:08:51 +0000881
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000882 far_frame.sample_rate_hz_ = sample_rate_hz;
883 far_frame.samples_per_channel_ = samples_per_channel;
884 far_frame.num_channels_ = num_render_channels;
885 near_frame.sample_rate_hz_ = sample_rate_hz;
886 near_frame.samples_per_channel_ = samples_per_channel;
ajm@google.com808e0e02011-08-03 21:08:51 +0000887
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000888 if (!raw_output) {
bjornv@webrtc.org634c9262014-09-24 12:21:51 +0000889 // The WAV file needs to be reset every time, because it can't change
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000890 // it's sample rate or number of channels.
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +0000891 output_wav_file.reset(new WavWriter(out_filename + ".wav",
892 sample_rate_hz,
893 num_capture_output_channels));
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000894 }
895
ajm@google.com808e0e02011-08-03 21:08:51 +0000896 if (verbose) {
897 printf("Init at frame: %d (primary), %d (reverse)\n",
898 primary_count, reverse_count);
899 printf(" Sample rate: %d Hz\n", sample_rate_hz);
900 }
901
902 } else if (event == kRenderEvent) {
903 reverse_count++;
ajm@google.com808e0e02011-08-03 21:08:51 +0000904
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000905 size_t size = samples_per_channel * num_render_channels;
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000906 read_count = fread(far_frame.data_,
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000907 sizeof(int16_t),
908 size,
ajm@google.com808e0e02011-08-03 21:08:51 +0000909 far_file);
910
911 if (simulating) {
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000912 if (read_count != size) {
andrew@webrtc.org94c74132011-09-19 15:17:57 +0000913 // Read an equal amount from the near file to avoid errors due to
914 // not reaching end-of-file.
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000915 EXPECT_EQ(0, fseek(near_file, read_count * sizeof(int16_t),
andrew@webrtc.org94c74132011-09-19 15:17:57 +0000916 SEEK_CUR));
Andrew MacDonaldcb05b722015-05-07 22:17:51 -0700917 break; // This is expected.
ajm@google.com808e0e02011-08-03 21:08:51 +0000918 }
919 } else {
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000920 ASSERT_EQ(size, read_count);
ajm@google.com808e0e02011-08-03 21:08:51 +0000921 }
922
923 if (perf_testing) {
924 t0 = TickTime::Now();
925 }
926
927 ASSERT_EQ(apm->kNoError,
928 apm->AnalyzeReverseStream(&far_frame));
929
930 if (perf_testing) {
931 t1 = TickTime::Now();
932 TickInterval tick_diff = t1 - t0;
933 acc_ticks += tick_diff;
934 if (tick_diff.Microseconds() > max_time_reverse_us) {
935 max_time_reverse_us = tick_diff.Microseconds();
936 }
937 if (tick_diff.Microseconds() < min_time_reverse_us) {
938 min_time_reverse_us = tick_diff.Microseconds();
939 }
940 }
941
942 } else if (event == kCaptureEvent) {
943 primary_count++;
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000944 near_frame.num_channels_ = num_capture_input_channels;
ajm@google.com808e0e02011-08-03 21:08:51 +0000945
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000946 size_t size = samples_per_channel * num_capture_input_channels;
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000947 read_count = fread(near_frame.data_,
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000948 sizeof(int16_t),
949 size,
ajm@google.com808e0e02011-08-03 21:08:51 +0000950 near_file);
951
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000952 near_read_bytes += read_count * sizeof(int16_t);
ajm@google.com808e0e02011-08-03 21:08:51 +0000953 if (progress && primary_count % 100 == 0) {
954 printf("%.0f%% complete\r",
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000955 (near_read_bytes * 100.0) / near_size_bytes);
ajm@google.com808e0e02011-08-03 21:08:51 +0000956 fflush(stdout);
957 }
958 if (simulating) {
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000959 if (read_count != size) {
Andrew MacDonaldcb05b722015-05-07 22:17:51 -0700960 break; // This is expected.
ajm@google.com808e0e02011-08-03 21:08:51 +0000961 }
962
963 delay_ms = 0;
964 drift_samples = 0;
965 } else {
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000966 ASSERT_EQ(size, read_count);
ajm@google.com808e0e02011-08-03 21:08:51 +0000967
968 // TODO(ajm): sizeof(delay_ms) for current files?
969 ASSERT_EQ(1u,
970 fread(&delay_ms, 2, 1, delay_file));
971 ASSERT_EQ(1u,
972 fread(&drift_samples, sizeof(drift_samples), 1, drift_file));
973 }
974
andrew@webrtc.orgbafdae32013-01-11 23:11:29 +0000975 if (apm->gain_control()->is_enabled() &&
976 apm->gain_control()->mode() == GainControl::kAdaptiveAnalog) {
andrew@webrtc.org81865342012-10-27 00:28:27 +0000977 SimulateMic(capture_level, &near_frame);
978 }
979
ajm@google.com808e0e02011-08-03 21:08:51 +0000980 if (perf_testing) {
981 t0 = TickTime::Now();
982 }
983
andrew@webrtc.orgbafdae32013-01-11 23:11:29 +0000984 const int capture_level_in = capture_level;
ajm@google.com808e0e02011-08-03 21:08:51 +0000985 ASSERT_EQ(apm->kNoError,
986 apm->gain_control()->set_stream_analog_level(capture_level));
andrew@webrtc.orgca764ab2013-10-07 16:44:32 +0000987 delay_ms += extra_delay_ms;
988 if (override_delay_ms) {
989 delay_ms = override_delay_ms;
990 }
ajm@google.com808e0e02011-08-03 21:08:51 +0000991 ASSERT_EQ(apm->kNoError,
andrew@webrtc.orgca764ab2013-10-07 16:44:32 +0000992 apm->set_stream_delay_ms(delay_ms));
andrew@webrtc.org6be1e932013-03-01 18:47:28 +0000993 apm->echo_cancellation()->set_stream_drift_samples(drift_samples);
ajm@google.com808e0e02011-08-03 21:08:51 +0000994
aluebs@webrtc.orgbc1d2242014-02-25 16:50:22 +0000995 apm->set_stream_key_pressed(true);
996
ajm@google.com808e0e02011-08-03 21:08:51 +0000997 int err = apm->ProcessStream(&near_frame);
998 if (err == apm->kBadStreamParameterWarning) {
999 printf("Bad parameter warning. %s\n", trace_stream.str().c_str());
1000 }
1001 ASSERT_TRUE(err == apm->kNoError ||
1002 err == apm->kBadStreamParameterWarning);
andrew@webrtc.org63a50982012-05-02 23:56:37 +00001003 ASSERT_TRUE(near_frame.num_channels_ == apm->num_output_channels());
ajm@google.com808e0e02011-08-03 21:08:51 +00001004
1005 capture_level = apm->gain_control()->stream_analog_level();
1006
1007 stream_has_voice =
1008 static_cast<int8_t>(apm->voice_detection()->stream_has_voice());
1009 if (vad_out_file != NULL) {
1010 ASSERT_EQ(1u, fwrite(&stream_has_voice,
1011 sizeof(stream_has_voice),
1012 1,
1013 vad_out_file));
1014 }
1015
bjornv@webrtc.org08329f42012-07-12 21:00:43 +00001016 if (ns_prob_file != NULL) {
1017 ns_speech_prob = apm->noise_suppression()->speech_probability();
1018 ASSERT_EQ(1u, fwrite(&ns_speech_prob,
1019 sizeof(ns_speech_prob),
1020 1,
1021 ns_prob_file));
1022 }
1023
ajm@google.com808e0e02011-08-03 21:08:51 +00001024 if (apm->gain_control()->mode() != GainControl::kAdaptiveAnalog) {
1025 ASSERT_EQ(capture_level_in, capture_level);
1026 }
1027
1028 if (perf_testing) {
1029 t1 = TickTime::Now();
1030 TickInterval tick_diff = t1 - t0;
1031 acc_ticks += tick_diff;
1032 if (tick_diff.Microseconds() > max_time_us) {
1033 max_time_us = tick_diff.Microseconds();
1034 }
1035 if (tick_diff.Microseconds() < min_time_us) {
1036 min_time_us = tick_diff.Microseconds();
1037 }
1038 }
1039
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +00001040 if (raw_output && !output_raw_file) {
1041 output_raw_file.reset(new RawFile(out_filename + ".pcm"));
1042 }
bjornv@webrtc.org634c9262014-09-24 12:21:51 +00001043 if (!raw_output && !output_wav_file) {
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +00001044 output_wav_file.reset(new WavWriter(out_filename + ".wav",
1045 sample_rate_hz,
1046 num_capture_output_channels));
bjornv@webrtc.org634c9262014-09-24 12:21:51 +00001047 }
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +00001048 WriteIntData(near_frame.data_,
1049 size,
1050 output_wav_file.get(),
1051 output_raw_file.get());
Andrew MacDonaldcb05b722015-05-07 22:17:51 -07001052 } else {
ajm@google.com808e0e02011-08-03 21:08:51 +00001053 FAIL() << "Event " << event << " is unrecognized";
niklase@google.com470e71d2011-07-07 08:21:25 +00001054 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001055 }
1056 }
peahc1cd2bb2015-11-09 10:38:07 -08001057 if (progress) {
1058 printf("100%% complete\r");
1059 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001060
bjornv@google.comc4b939c2011-07-13 08:09:56 +00001061 if (aecm_echo_path_out_file != NULL) {
ajm@google.com22e65152011-07-18 18:03:01 +00001062 const size_t path_size =
1063 apm->echo_control_mobile()->echo_path_size_bytes();
kwiberg62eaacf2016-02-17 06:39:05 -08001064 std::unique_ptr<char[]> echo_path(new char[path_size]);
andrew@webrtc.org3119ecf2011-11-01 17:00:18 +00001065 apm->echo_control_mobile()->GetEchoPath(echo_path.get(), path_size);
1066 ASSERT_EQ(path_size, fwrite(echo_path.get(),
1067 sizeof(char),
bjornv@google.comc4b939c2011-07-13 08:09:56 +00001068 path_size,
1069 aecm_echo_path_out_file));
1070 fclose(aecm_echo_path_out_file);
1071 aecm_echo_path_out_file = NULL;
1072 }
1073
niklase@google.com470e71d2011-07-07 08:21:25 +00001074 if (verbose) {
1075 printf("\nProcessed frames: %d (primary), %d (reverse)\n",
1076 primary_count, reverse_count);
andrew@webrtc.org94c74132011-09-19 15:17:57 +00001077
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001078 if (apm->level_estimator()->is_enabled()) {
1079 printf("\n--Level metrics--\n");
1080 printf("RMS: %d dBFS\n", -apm->level_estimator()->RMS());
1081 }
andrew@webrtc.org94c74132011-09-19 15:17:57 +00001082 if (apm->echo_cancellation()->are_metrics_enabled()) {
1083 EchoCancellation::Metrics metrics;
1084 apm->echo_cancellation()->GetMetrics(&metrics);
1085 printf("\n--Echo metrics--\n");
1086 printf("(avg, max, min)\n");
1087 printf("ERL: ");
1088 PrintStat(metrics.echo_return_loss);
1089 printf("ERLE: ");
1090 PrintStat(metrics.echo_return_loss_enhancement);
1091 printf("ANLP: ");
1092 PrintStat(metrics.a_nlp);
1093 }
bjornv@google.com1ba3dbe2011-10-03 08:18:10 +00001094 if (apm->echo_cancellation()->is_delay_logging_enabled()) {
1095 int median = 0;
1096 int std = 0;
bjornv@webrtc.orgb1786db2015-02-03 06:06:26 +00001097 float fraction_poor_delays = 0;
1098 apm->echo_cancellation()->GetDelayMetrics(&median, &std,
1099 &fraction_poor_delays);
bjornv@google.com1ba3dbe2011-10-03 08:18:10 +00001100 printf("\n--Delay metrics--\n");
1101 printf("Median: %3d\n", median);
1102 printf("Standard deviation: %3d\n", std);
bjornv@webrtc.orgb1786db2015-02-03 06:06:26 +00001103 printf("Poor delay values: %3.1f%%\n", fraction_poor_delays * 100);
bjornv@google.com1ba3dbe2011-10-03 08:18:10 +00001104 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001105 }
1106
ajm@google.com808e0e02011-08-03 21:08:51 +00001107 if (!pb_file) {
1108 int8_t temp_int8;
1109 if (far_file) {
1110 read_count = fread(&temp_int8, sizeof(temp_int8), 1, far_file);
1111 EXPECT_NE(0, feof(far_file)) << "Far-end file not fully processed";
1112 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001113
ajm@google.com808e0e02011-08-03 21:08:51 +00001114 read_count = fread(&temp_int8, sizeof(temp_int8), 1, near_file);
1115 EXPECT_NE(0, feof(near_file)) << "Near-end file not fully processed";
1116
1117 if (!simulating) {
1118 read_count = fread(&temp_int8, sizeof(temp_int8), 1, event_file);
1119 EXPECT_NE(0, feof(event_file)) << "Event file not fully processed";
1120 read_count = fread(&temp_int8, sizeof(temp_int8), 1, delay_file);
1121 EXPECT_NE(0, feof(delay_file)) << "Delay file not fully processed";
1122 read_count = fread(&temp_int8, sizeof(temp_int8), 1, drift_file);
1123 EXPECT_NE(0, feof(drift_file)) << "Drift file not fully processed";
1124 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001125 }
1126
1127 if (perf_testing) {
1128 if (primary_count > 0) {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +00001129 int64_t exec_time = acc_ticks.Milliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +00001130 printf("\nTotal time: %.3f s, file time: %.2f s\n",
1131 exec_time * 0.001, primary_count * 0.01);
1132 printf("Time per frame: %.3f ms (average), %.3f ms (max),"
1133 " %.3f ms (min)\n",
1134 (exec_time * 1.0) / primary_count,
1135 (max_time_us + max_time_reverse_us) / 1000.0,
1136 (min_time_us + min_time_reverse_us) / 1000.0);
kma@webrtc.org0e739502012-12-07 15:26:28 +00001137 // Record the results with Perf test tools.
kjellander@webrtc.org00ab7cf2013-02-11 12:33:03 +00001138 webrtc::test::PrintResult("audioproc", "", "time_per_10ms_frame",
kma@webrtc.org0e739502012-12-07 15:26:28 +00001139 (exec_time * 1000) / primary_count, "us", false);
niklase@google.com470e71d2011-07-07 08:21:25 +00001140 } else {
1141 printf("Warning: no capture frames\n");
1142 }
1143 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001144}
andrew@webrtc.orga8b97372014-03-10 22:26:12 +00001145
ajm@google.com808e0e02011-08-03 21:08:51 +00001146} // namespace
andrew@webrtc.orga8b97372014-03-10 22:26:12 +00001147} // namespace webrtc
niklase@google.com470e71d2011-07-07 08:21:25 +00001148
Andrew MacDonaldcb05b722015-05-07 22:17:51 -07001149int main(int argc, char* argv[]) {
andrew@webrtc.orga8b97372014-03-10 22:26:12 +00001150 webrtc::void_main(argc, argv);
niklase@google.com470e71d2011-07-07 08:21:25 +00001151
andrew@webrtc.org64235092011-08-19 21:22:08 +00001152 // Optional, but removes memory leak noise from Valgrind.
1153 google::protobuf::ShutdownProtobufLibrary();
niklase@google.com470e71d2011-07-07 08:21:25 +00001154 return 0;
1155}