blob: 6e20a787e7d8b03f8018a912bd3114afd26e496f [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>
19
Peter Kasting69558702016-01-12 16:26:35 -080020#include "webrtc/base/format_macros.h"
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +000021#include "webrtc/base/scoped_ptr.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"
ajm@google.com808e0e02011-08-03 21:08:51 +000036#include "webrtc/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");
niklase@google.com470e71d2011-07-07 08:21:25 +000084 printf("\n -aecm Echo control mobile\n");
bjornv@google.com238a0222011-07-15 14:51:52 +000085 printf(" --aecm_echo_path_in_file FILE\n");
86 printf(" --aecm_echo_path_out_file FILE\n");
andrew@webrtc.org1acb3b32013-04-26 00:39:27 +000087 printf(" --no_comfort_noise\n");
88 printf(" --routing_mode MODE [0 - 4]\n");
niklase@google.com470e71d2011-07-07 08:21:25 +000089 printf("\n -agc Gain control\n");
90 printf(" --analog\n");
91 printf(" --adaptive_digital\n");
92 printf(" --fixed_digital\n");
93 printf(" --target_level LEVEL\n");
94 printf(" --compression_gain GAIN\n");
95 printf(" --limiter\n");
96 printf(" --no_limiter\n");
97 printf("\n -hpf High pass filter\n");
98 printf("\n -ns Noise suppression\n");
99 printf(" --ns_low\n");
100 printf(" --ns_moderate\n");
101 printf(" --ns_high\n");
102 printf(" --ns_very_high\n");
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000103 printf(" --ns_prob_file FILE\n");
niklase@google.com470e71d2011-07-07 08:21:25 +0000104 printf("\n -vad Voice activity detection\n");
ajm@google.com808e0e02011-08-03 21:08:51 +0000105 printf(" --vad_out_file FILE\n");
andrew@webrtc.orgb13a7d52014-03-27 00:11:11 +0000106 printf("\n -expns Experimental noise suppression\n");
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000107 printf("\n Level metrics (enabled by default)\n");
108 printf(" --no_level_metrics\n");
niklase@google.com470e71d2011-07-07 08:21:25 +0000109 printf("\n");
110 printf("Modifiers:\n");
andrew@webrtc.orgcb181212011-10-26 00:27:17 +0000111 printf(" --noasm Disable SSE optimization.\n");
andrew@webrtc.orgca764ab2013-10-07 16:44:32 +0000112 printf(" --add_delay DELAY Add DELAY ms to input value.\n");
113 printf(" --delay DELAY Override input delay with DELAY ms.\n");
andrew@webrtc.orgcb181212011-10-26 00:27:17 +0000114 printf(" --perf Measure performance.\n");
115 printf(" --quiet Suppress text output.\n");
116 printf(" --no_progress Suppress progress.\n");
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000117 printf(" --raw_output Raw output instead of WAV file.\n");
andrew@webrtc.orgcb181212011-10-26 00:27:17 +0000118 printf(" --debug_file FILE Dump a debug recording.\n");
niklase@google.com470e71d2011-07-07 08:21:25 +0000119}
120
andrew@webrtc.orgbafdae32013-01-11 23:11:29 +0000121static float MicLevel2Gain(int level) {
122 return pow(10.0f, ((level - 127.0f) / 128.0f * 40.0f) / 20.0f);
andrew@webrtc.org81865342012-10-27 00:28:27 +0000123}
124
125static void SimulateMic(int mic_level, AudioFrame* frame) {
126 mic_level = std::min(std::max(mic_level, 0), 255);
andrew@webrtc.orgbafdae32013-01-11 23:11:29 +0000127 float mic_gain = MicLevel2Gain(mic_level);
andrew@webrtc.org81865342012-10-27 00:28:27 +0000128 int num_samples = frame->samples_per_channel_ * frame->num_channels_;
andrew@webrtc.orgbafdae32013-01-11 23:11:29 +0000129 float v;
andrew@webrtc.org81865342012-10-27 00:28:27 +0000130 for (int n = 0; n < num_samples; n++) {
131 v = floor(frame->data_[n] * mic_gain + 0.5);
andrew@webrtc.orgbafdae32013-01-11 23:11:29 +0000132 v = std::max(std::min(32767.0f, v), -32768.0f);
andrew@webrtc.org81865342012-10-27 00:28:27 +0000133 frame->data_[n] = static_cast<int16_t>(v);
134 }
135}
136
niklase@google.com470e71d2011-07-07 08:21:25 +0000137// void function for gtest.
138void void_main(int argc, char* argv[]) {
139 if (argc > 1 && strcmp(argv[1], "--help") == 0) {
140 usage();
141 return;
142 }
143
144 if (argc < 2) {
145 printf("Did you mean to run without arguments?\n");
146 printf("Try `process_test --help' for more information.\n\n");
147 }
148
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000149 rtc::scoped_ptr<AudioProcessing> apm(AudioProcessing::Create());
andrew@webrtc.orgf3930e92013-09-18 22:37:32 +0000150 ASSERT_TRUE(apm.get() != NULL);
niklase@google.com470e71d2011-07-07 08:21:25 +0000151
ajm@google.com808e0e02011-08-03 21:08:51 +0000152 const char* pb_filename = NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000153 const char* far_filename = NULL;
154 const char* near_filename = NULL;
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000155 std::string out_filename;
niklase@google.com470e71d2011-07-07 08:21:25 +0000156 const char* vad_out_filename = NULL;
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000157 const char* ns_prob_filename = NULL;
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000158 const char* aecm_echo_path_in_filename = NULL;
159 const char* aecm_echo_path_out_filename = NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000160
161 int32_t sample_rate_hz = 16000;
niklase@google.com470e71d2011-07-07 08:21:25 +0000162
Peter Kasting69558702016-01-12 16:26:35 -0800163 size_t num_capture_input_channels = 1;
164 size_t num_capture_output_channels = 1;
165 size_t num_render_channels = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000166
167 int samples_per_channel = sample_rate_hz / 100;
168
169 bool simulating = false;
170 bool perf_testing = false;
171 bool verbose = true;
172 bool progress = true;
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000173 bool raw_output = false;
andrew@webrtc.org4b13fc92011-11-09 19:27:11 +0000174 int extra_delay_ms = 0;
andrew@webrtc.orgca764ab2013-10-07 16:44:32 +0000175 int override_delay_ms = 0;
Bjorn Volckerbeb97982015-04-28 13:52:50 +0200176 Config config;
niklase@google.com470e71d2011-07-07 08:21:25 +0000177
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000178 ASSERT_EQ(apm->kNoError, apm->level_estimator()->Enable(true));
niklase@google.com470e71d2011-07-07 08:21:25 +0000179 for (int i = 1; i < argc; i++) {
andrew@webrtc.org94c74132011-09-19 15:17:57 +0000180 if (strcmp(argv[i], "-pb") == 0) {
ajm@google.com808e0e02011-08-03 21:08:51 +0000181 i++;
182 ASSERT_LT(i, argc) << "Specify protobuf filename after -pb";
183 pb_filename = argv[i];
184
185 } else if (strcmp(argv[i], "-ir") == 0) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000186 i++;
187 ASSERT_LT(i, argc) << "Specify filename after -ir";
188 far_filename = argv[i];
189 simulating = true;
190
191 } else if (strcmp(argv[i], "-i") == 0) {
192 i++;
193 ASSERT_LT(i, argc) << "Specify filename after -i";
194 near_filename = argv[i];
195 simulating = true;
196
197 } else if (strcmp(argv[i], "-o") == 0) {
198 i++;
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000199 ASSERT_LT(i, argc) << "Specify filename without extension after -o";
niklase@google.com470e71d2011-07-07 08:21:25 +0000200 out_filename = argv[i];
201
202 } else if (strcmp(argv[i], "-fs") == 0) {
203 i++;
204 ASSERT_LT(i, argc) << "Specify sample rate after -fs";
205 ASSERT_EQ(1, sscanf(argv[i], "%d", &sample_rate_hz));
206 samples_per_channel = sample_rate_hz / 100;
207
niklase@google.com470e71d2011-07-07 08:21:25 +0000208 } else if (strcmp(argv[i], "-ch") == 0) {
209 i++;
210 ASSERT_LT(i + 1, argc) << "Specify number of channels after -ch";
Peter Kasting69558702016-01-12 16:26:35 -0800211 ASSERT_EQ(1, sscanf(argv[i], "%" PRIuS, &num_capture_input_channels));
niklase@google.com470e71d2011-07-07 08:21:25 +0000212 i++;
Peter Kasting69558702016-01-12 16:26:35 -0800213 ASSERT_EQ(1, sscanf(argv[i], "%" PRIuS, &num_capture_output_channels));
niklase@google.com470e71d2011-07-07 08:21:25 +0000214
niklase@google.com470e71d2011-07-07 08:21:25 +0000215 } else if (strcmp(argv[i], "-rch") == 0) {
216 i++;
217 ASSERT_LT(i, argc) << "Specify number of channels after -rch";
Peter Kasting69558702016-01-12 16:26:35 -0800218 ASSERT_EQ(1, sscanf(argv[i], "%" PRIuS, &num_render_channels));
niklase@google.com470e71d2011-07-07 08:21:25 +0000219
niklase@google.com470e71d2011-07-07 08:21:25 +0000220 } else if (strcmp(argv[i], "-aec") == 0) {
221 ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
bjornv@google.com1ba3dbe2011-10-03 08:18:10 +0000222 ASSERT_EQ(apm->kNoError,
223 apm->echo_cancellation()->enable_metrics(true));
224 ASSERT_EQ(apm->kNoError,
225 apm->echo_cancellation()->enable_delay_logging(true));
niklase@google.com470e71d2011-07-07 08:21:25 +0000226
niklase@google.com470e71d2011-07-07 08:21:25 +0000227 } else if (strcmp(argv[i], "--drift_compensation") == 0) {
228 ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
229 // TODO(ajm): this is enabled in the VQE test app by default. Investigate
230 // why it can give better performance despite passing zeros.
231 ASSERT_EQ(apm->kNoError,
232 apm->echo_cancellation()->enable_drift_compensation(true));
233 } else if (strcmp(argv[i], "--no_drift_compensation") == 0) {
234 ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
235 ASSERT_EQ(apm->kNoError,
236 apm->echo_cancellation()->enable_drift_compensation(false));
237
andrew@webrtc.org94c74132011-09-19 15:17:57 +0000238 } else if (strcmp(argv[i], "--no_echo_metrics") == 0) {
239 ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
240 ASSERT_EQ(apm->kNoError,
241 apm->echo_cancellation()->enable_metrics(false));
242
bjornv@google.com1ba3dbe2011-10-03 08:18:10 +0000243 } else if (strcmp(argv[i], "--no_delay_logging") == 0) {
244 ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
245 ASSERT_EQ(apm->kNoError,
246 apm->echo_cancellation()->enable_delay_logging(false));
247
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000248 } else if (strcmp(argv[i], "--no_level_metrics") == 0) {
249 ASSERT_EQ(apm->kNoError, apm->level_estimator()->Enable(false));
250
andrew@webrtc.orgdff69c52013-04-30 23:01:09 +0000251 } else if (strcmp(argv[i], "--aec_suppression_level") == 0) {
252 i++;
253 ASSERT_LT(i, argc) << "Specify level after --aec_suppression_level";
254 int suppression_level;
255 ASSERT_EQ(1, sscanf(argv[i], "%d", &suppression_level));
256 ASSERT_EQ(apm->kNoError,
257 apm->echo_cancellation()->set_suppression_level(
258 static_cast<webrtc::EchoCancellation::SuppressionLevel>(
259 suppression_level)));
260
andrew@webrtc.org22858d42013-10-23 14:07:17 +0000261 } else if (strcmp(argv[i], "--extended_filter") == 0) {
Henrik Lundin441f6342015-06-09 16:03:13 +0200262 config.Set<ExtendedFilter>(new ExtendedFilter(true));
andrew@webrtc.org22858d42013-10-23 14:07:17 +0000263
bjornv@webrtc.org84f8ec12014-06-19 12:14:33 +0000264 } else if (strcmp(argv[i], "--no_reported_delay") == 0) {
henrik.lundin0f133b92015-07-02 00:17:55 -0700265 config.Set<DelayAgnostic>(new DelayAgnostic(true));
266
267 } else if (strcmp(argv[i], "--delay_agnostic") == 0) {
268 config.Set<DelayAgnostic>(new DelayAgnostic(true));
bjornv@webrtc.org84f8ec12014-06-19 12:14:33 +0000269
niklase@google.com470e71d2011-07-07 08:21:25 +0000270 } else if (strcmp(argv[i], "-aecm") == 0) {
271 ASSERT_EQ(apm->kNoError, apm->echo_control_mobile()->Enable(true));
272
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000273 } else if (strcmp(argv[i], "--aecm_echo_path_in_file") == 0) {
274 i++;
275 ASSERT_LT(i, argc) << "Specify filename after --aecm_echo_path_in_file";
276 aecm_echo_path_in_filename = argv[i];
277
278 } else if (strcmp(argv[i], "--aecm_echo_path_out_file") == 0) {
279 i++;
280 ASSERT_LT(i, argc) << "Specify filename after --aecm_echo_path_out_file";
281 aecm_echo_path_out_filename = argv[i];
282
andrew@webrtc.org1acb3b32013-04-26 00:39:27 +0000283 } else if (strcmp(argv[i], "--no_comfort_noise") == 0) {
284 ASSERT_EQ(apm->kNoError,
285 apm->echo_control_mobile()->enable_comfort_noise(false));
286
287 } else if (strcmp(argv[i], "--routing_mode") == 0) {
288 i++;
289 ASSERT_LT(i, argc) << "Specify mode after --routing_mode";
290 int routing_mode;
291 ASSERT_EQ(1, sscanf(argv[i], "%d", &routing_mode));
292 ASSERT_EQ(apm->kNoError,
293 apm->echo_control_mobile()->set_routing_mode(
294 static_cast<webrtc::EchoControlMobile::RoutingMode>(
295 routing_mode)));
296
niklase@google.com470e71d2011-07-07 08:21:25 +0000297 } else if (strcmp(argv[i], "-agc") == 0) {
298 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
299
300 } else if (strcmp(argv[i], "--analog") == 0) {
301 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
302 ASSERT_EQ(apm->kNoError,
303 apm->gain_control()->set_mode(GainControl::kAdaptiveAnalog));
304
305 } else if (strcmp(argv[i], "--adaptive_digital") == 0) {
306 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
307 ASSERT_EQ(apm->kNoError,
308 apm->gain_control()->set_mode(GainControl::kAdaptiveDigital));
309
310 } else if (strcmp(argv[i], "--fixed_digital") == 0) {
311 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
312 ASSERT_EQ(apm->kNoError,
313 apm->gain_control()->set_mode(GainControl::kFixedDigital));
314
315 } else if (strcmp(argv[i], "--target_level") == 0) {
316 i++;
317 int level;
318 ASSERT_EQ(1, sscanf(argv[i], "%d", &level));
319
320 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
321 ASSERT_EQ(apm->kNoError,
322 apm->gain_control()->set_target_level_dbfs(level));
323
324 } else if (strcmp(argv[i], "--compression_gain") == 0) {
325 i++;
326 int gain;
327 ASSERT_EQ(1, sscanf(argv[i], "%d", &gain));
328
329 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
330 ASSERT_EQ(apm->kNoError,
331 apm->gain_control()->set_compression_gain_db(gain));
332
333 } else if (strcmp(argv[i], "--limiter") == 0) {
334 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
335 ASSERT_EQ(apm->kNoError,
336 apm->gain_control()->enable_limiter(true));
337
338 } else if (strcmp(argv[i], "--no_limiter") == 0) {
339 ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
340 ASSERT_EQ(apm->kNoError,
341 apm->gain_control()->enable_limiter(false));
342
343 } else if (strcmp(argv[i], "-hpf") == 0) {
344 ASSERT_EQ(apm->kNoError, apm->high_pass_filter()->Enable(true));
345
346 } else if (strcmp(argv[i], "-ns") == 0) {
347 ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(true));
348
349 } else if (strcmp(argv[i], "--ns_low") == 0) {
350 ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(true));
351 ASSERT_EQ(apm->kNoError,
352 apm->noise_suppression()->set_level(NoiseSuppression::kLow));
353
354 } else if (strcmp(argv[i], "--ns_moderate") == 0) {
355 ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(true));
356 ASSERT_EQ(apm->kNoError,
357 apm->noise_suppression()->set_level(NoiseSuppression::kModerate));
358
359 } else if (strcmp(argv[i], "--ns_high") == 0) {
360 ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(true));
361 ASSERT_EQ(apm->kNoError,
362 apm->noise_suppression()->set_level(NoiseSuppression::kHigh));
363
364 } else if (strcmp(argv[i], "--ns_very_high") == 0) {
365 ASSERT_EQ(apm->kNoError, apm->noise_suppression()->Enable(true));
366 ASSERT_EQ(apm->kNoError,
367 apm->noise_suppression()->set_level(NoiseSuppression::kVeryHigh));
368
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000369 } else if (strcmp(argv[i], "--ns_prob_file") == 0) {
370 i++;
371 ASSERT_LT(i, argc) << "Specify filename after --ns_prob_file";
372 ns_prob_filename = argv[i];
373
niklase@google.com470e71d2011-07-07 08:21:25 +0000374 } else if (strcmp(argv[i], "-vad") == 0) {
375 ASSERT_EQ(apm->kNoError, apm->voice_detection()->Enable(true));
376
andrew@webrtc.org89752612012-10-12 16:41:45 +0000377 } else if (strcmp(argv[i], "--vad_very_low") == 0) {
378 ASSERT_EQ(apm->kNoError, apm->voice_detection()->Enable(true));
379 ASSERT_EQ(apm->kNoError,
380 apm->voice_detection()->set_likelihood(
381 VoiceDetection::kVeryLowLikelihood));
382
383 } else if (strcmp(argv[i], "--vad_low") == 0) {
384 ASSERT_EQ(apm->kNoError, apm->voice_detection()->Enable(true));
385 ASSERT_EQ(apm->kNoError,
386 apm->voice_detection()->set_likelihood(
387 VoiceDetection::kLowLikelihood));
388
389 } else if (strcmp(argv[i], "--vad_moderate") == 0) {
390 ASSERT_EQ(apm->kNoError, apm->voice_detection()->Enable(true));
391 ASSERT_EQ(apm->kNoError,
392 apm->voice_detection()->set_likelihood(
393 VoiceDetection::kModerateLikelihood));
394
395 } else if (strcmp(argv[i], "--vad_high") == 0) {
396 ASSERT_EQ(apm->kNoError, apm->voice_detection()->Enable(true));
397 ASSERT_EQ(apm->kNoError,
398 apm->voice_detection()->set_likelihood(
399 VoiceDetection::kHighLikelihood));
400
niklase@google.com470e71d2011-07-07 08:21:25 +0000401 } else if (strcmp(argv[i], "--vad_out_file") == 0) {
402 i++;
403 ASSERT_LT(i, argc) << "Specify filename after --vad_out_file";
404 vad_out_filename = argv[i];
405
aluebs@webrtc.orgbc1d2242014-02-25 16:50:22 +0000406 } else if (strcmp(argv[i], "-expns") == 0) {
aluebs@webrtc.org9825afc2014-06-30 17:39:53 +0000407 config.Set<ExperimentalNs>(new ExperimentalNs(true));
aluebs@webrtc.orgbc1d2242014-02-25 16:50:22 +0000408
andrew@webrtc.org94c74132011-09-19 15:17:57 +0000409 } else if (strcmp(argv[i], "--noasm") == 0) {
410 WebRtc_GetCPUInfo = WebRtc_GetCPUInfoNoASM;
411 // We need to reinitialize here if components have already been enabled.
412 ASSERT_EQ(apm->kNoError, apm->Initialize());
413
andrew@webrtc.orgca764ab2013-10-07 16:44:32 +0000414 } else if (strcmp(argv[i], "--add_delay") == 0) {
andrew@webrtc.org4b13fc92011-11-09 19:27:11 +0000415 i++;
416 ASSERT_EQ(1, sscanf(argv[i], "%d", &extra_delay_ms));
417
andrew@webrtc.orgca764ab2013-10-07 16:44:32 +0000418 } else if (strcmp(argv[i], "--delay") == 0) {
419 i++;
420 ASSERT_EQ(1, sscanf(argv[i], "%d", &override_delay_ms));
421
niklase@google.com470e71d2011-07-07 08:21:25 +0000422 } else if (strcmp(argv[i], "--perf") == 0) {
423 perf_testing = true;
424
425 } else if (strcmp(argv[i], "--quiet") == 0) {
426 verbose = false;
427 progress = false;
428
429 } else if (strcmp(argv[i], "--no_progress") == 0) {
430 progress = false;
431
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000432 } else if (strcmp(argv[i], "--raw_output") == 0) {
433 raw_output = true;
434
andrew@webrtc.orgcb181212011-10-26 00:27:17 +0000435 } else if (strcmp(argv[i], "--debug_file") == 0) {
ajm@google.com808e0e02011-08-03 21:08:51 +0000436 i++;
andrew@webrtc.orgcb181212011-10-26 00:27:17 +0000437 ASSERT_LT(i, argc) << "Specify filename after --debug_file";
ivoca4df27b2015-12-19 10:14:10 -0800438 ASSERT_EQ(apm->kNoError, apm->StartDebugRecording(argv[i]));
niklase@google.com470e71d2011-07-07 08:21:25 +0000439 } else {
440 FAIL() << "Unrecognized argument " << argv[i];
441 }
442 }
Bjorn Volckerbeb97982015-04-28 13:52:50 +0200443 apm->SetExtraOptions(config);
444
ajm@google.com808e0e02011-08-03 21:08:51 +0000445 // If we're reading a protobuf file, ensure a simulation hasn't also
446 // been requested (which makes no sense...)
447 ASSERT_FALSE(pb_filename && simulating);
niklase@google.com470e71d2011-07-07 08:21:25 +0000448
449 if (verbose) {
450 printf("Sample rate: %d Hz\n", sample_rate_hz);
Peter Kasting69558702016-01-12 16:26:35 -0800451 printf("Primary channels: %" PRIuS " (in), %" PRIuS " (out)\n",
niklase@google.com470e71d2011-07-07 08:21:25 +0000452 num_capture_input_channels,
453 num_capture_output_channels);
Peter Kasting69558702016-01-12 16:26:35 -0800454 printf("Reverse channels: %" PRIuS "\n", num_render_channels);
niklase@google.com470e71d2011-07-07 08:21:25 +0000455 }
456
kjellander@webrtc.org10abe252012-12-17 18:28:07 +0000457 const std::string out_path = webrtc::test::OutputPath();
niklase@google.com470e71d2011-07-07 08:21:25 +0000458 const char far_file_default[] = "apm_far.pcm";
459 const char near_file_default[] = "apm_near.pcm";
niklase@google.com470e71d2011-07-07 08:21:25 +0000460 const char event_filename[] = "apm_event.dat";
461 const char delay_filename[] = "apm_delay.dat";
462 const char drift_filename[] = "apm_drift.dat";
kjellander@webrtc.org10abe252012-12-17 18:28:07 +0000463 const std::string vad_file_default = out_path + "vad_out.dat";
464 const std::string ns_prob_file_default = out_path + "ns_prob.dat";
niklase@google.com470e71d2011-07-07 08:21:25 +0000465
466 if (!simulating) {
467 far_filename = far_file_default;
468 near_filename = near_file_default;
469 }
470
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000471 if (out_filename.size() == 0) {
472 out_filename = out_path + "out";
niklase@google.com470e71d2011-07-07 08:21:25 +0000473 }
474
ajm@google.com808e0e02011-08-03 21:08:51 +0000475 if (!vad_out_filename) {
kjellander@webrtc.org10abe252012-12-17 18:28:07 +0000476 vad_out_filename = vad_file_default.c_str();
niklase@google.com470e71d2011-07-07 08:21:25 +0000477 }
478
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000479 if (!ns_prob_filename) {
kjellander@webrtc.org10abe252012-12-17 18:28:07 +0000480 ns_prob_filename = ns_prob_file_default.c_str();
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000481 }
482
ajm@google.com808e0e02011-08-03 21:08:51 +0000483 FILE* pb_file = NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000484 FILE* far_file = NULL;
485 FILE* near_file = NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000486 FILE* event_file = NULL;
487 FILE* delay_file = NULL;
488 FILE* drift_file = NULL;
489 FILE* vad_out_file = NULL;
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000490 FILE* ns_prob_file = NULL;
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000491 FILE* aecm_echo_path_in_file = NULL;
492 FILE* aecm_echo_path_out_file = NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +0000493
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000494 rtc::scoped_ptr<WavWriter> output_wav_file;
495 rtc::scoped_ptr<RawFile> output_raw_file;
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000496
ajm@google.com808e0e02011-08-03 21:08:51 +0000497 if (pb_filename) {
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000498 pb_file = OpenFile(pb_filename, "rb");
ajm@google.com808e0e02011-08-03 21:08:51 +0000499 } else {
500 if (far_filename) {
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000501 far_file = OpenFile(far_filename, "rb");
ajm@google.com808e0e02011-08-03 21:08:51 +0000502 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000503
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000504 near_file = OpenFile(near_filename, "rb");
ajm@google.com808e0e02011-08-03 21:08:51 +0000505 if (!simulating) {
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000506 event_file = OpenFile(event_filename, "rb");
507 delay_file = OpenFile(delay_filename, "rb");
508 drift_file = OpenFile(drift_filename, "rb");
ajm@google.com808e0e02011-08-03 21:08:51 +0000509 }
510 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000511
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000512 int near_size_bytes = 0;
ajm@google.com808e0e02011-08-03 21:08:51 +0000513 if (pb_file) {
514 struct stat st;
515 stat(pb_filename, &st);
516 // Crude estimate, but should be good enough.
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000517 near_size_bytes = st.st_size / 3;
ajm@google.com808e0e02011-08-03 21:08:51 +0000518 } else {
519 struct stat st;
520 stat(near_filename, &st);
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000521 near_size_bytes = st.st_size;
niklase@google.com470e71d2011-07-07 08:21:25 +0000522 }
523
524 if (apm->voice_detection()->is_enabled()) {
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000525 vad_out_file = OpenFile(vad_out_filename, "wb");
niklase@google.com470e71d2011-07-07 08:21:25 +0000526 }
527
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000528 if (apm->noise_suppression()->is_enabled()) {
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000529 ns_prob_file = OpenFile(ns_prob_filename, "wb");
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000530 }
531
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000532 if (aecm_echo_path_in_filename != NULL) {
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000533 aecm_echo_path_in_file = OpenFile(aecm_echo_path_in_filename, "rb");
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000534
ajm@google.com22e65152011-07-18 18:03:01 +0000535 const size_t path_size =
536 apm->echo_control_mobile()->echo_path_size_bytes();
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000537 rtc::scoped_ptr<char[]> echo_path(new char[path_size]);
andrew@webrtc.org3119ecf2011-11-01 17:00:18 +0000538 ASSERT_EQ(path_size, fread(echo_path.get(),
539 sizeof(char),
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000540 path_size,
541 aecm_echo_path_in_file));
542 EXPECT_EQ(apm->kNoError,
andrew@webrtc.org3119ecf2011-11-01 17:00:18 +0000543 apm->echo_control_mobile()->SetEchoPath(echo_path.get(),
544 path_size));
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000545 fclose(aecm_echo_path_in_file);
546 aecm_echo_path_in_file = NULL;
547 }
548
549 if (aecm_echo_path_out_filename != NULL) {
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000550 aecm_echo_path_out_file = OpenFile(aecm_echo_path_out_filename, "wb");
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000551 }
552
niklase@google.com470e71d2011-07-07 08:21:25 +0000553 size_t read_count = 0;
554 int reverse_count = 0;
555 int primary_count = 0;
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000556 int near_read_bytes = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000557 TickInterval acc_ticks;
558
559 AudioFrame far_frame;
niklase@google.com470e71d2011-07-07 08:21:25 +0000560 AudioFrame near_frame;
niklase@google.com470e71d2011-07-07 08:21:25 +0000561
562 int delay_ms = 0;
563 int drift_samples = 0;
564 int capture_level = 127;
565 int8_t stream_has_voice = 0;
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000566 float ns_speech_prob = 0.0f;
niklase@google.com470e71d2011-07-07 08:21:25 +0000567
568 TickTime t0 = TickTime::Now();
569 TickTime t1 = t0;
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000570 int64_t max_time_us = 0;
571 int64_t max_time_reverse_us = 0;
572 int64_t min_time_us = 1e6;
573 int64_t min_time_reverse_us = 1e6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000574
ajm@google.com808e0e02011-08-03 21:08:51 +0000575 // TODO(ajm): Ideally we would refactor this block into separate functions,
576 // but for now we want to share the variables.
577 if (pb_file) {
578 Event event_msg;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000579 rtc::scoped_ptr<ChannelBuffer<float> > reverse_cb;
580 rtc::scoped_ptr<ChannelBuffer<float> > primary_cb;
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000581 int output_sample_rate = 32000;
582 AudioProcessing::ChannelLayout output_layout = AudioProcessing::kMono;
ajm@google.com808e0e02011-08-03 21:08:51 +0000583 while (ReadMessageFromFile(pb_file, &event_msg)) {
584 std::ostringstream trace_stream;
585 trace_stream << "Processed frames: " << reverse_count << " (reverse), "
586 << primary_count << " (primary)";
587 SCOPED_TRACE(trace_stream.str());
niklase@google.com470e71d2011-07-07 08:21:25 +0000588
ajm@google.com808e0e02011-08-03 21:08:51 +0000589 if (event_msg.type() == Event::INIT) {
590 ASSERT_TRUE(event_msg.has_init());
591 const Init msg = event_msg.init();
niklase@google.com470e71d2011-07-07 08:21:25 +0000592
ajm@google.com808e0e02011-08-03 21:08:51 +0000593 ASSERT_TRUE(msg.has_sample_rate());
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000594 ASSERT_TRUE(msg.has_num_input_channels());
595 ASSERT_TRUE(msg.has_num_output_channels());
596 ASSERT_TRUE(msg.has_num_reverse_channels());
597 int reverse_sample_rate = msg.sample_rate();
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000598 if (msg.has_reverse_sample_rate()) {
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000599 reverse_sample_rate = msg.reverse_sample_rate();
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000600 }
601 output_sample_rate = msg.sample_rate();
602 if (msg.has_output_sample_rate()) {
603 output_sample_rate = msg.output_sample_rate();
604 }
Peter Kasting69558702016-01-12 16:26:35 -0800605 output_layout =
606 LayoutFromChannels(static_cast<size_t>(msg.num_output_channels()));
607 ASSERT_EQ(kNoErr,
608 apm->Initialize(
609 msg.sample_rate(),
610 output_sample_rate,
611 reverse_sample_rate,
612 LayoutFromChannels(
613 static_cast<size_t>(msg.num_input_channels())),
614 output_layout,
615 LayoutFromChannels(
616 static_cast<size_t>(msg.num_reverse_channels()))));
ajm@google.com808e0e02011-08-03 21:08:51 +0000617
618 samples_per_channel = msg.sample_rate() / 100;
bjornv@webrtc.orgee300822014-11-13 11:00:10 +0000619 far_frame.sample_rate_hz_ = reverse_sample_rate;
aluebs@webrtc.org74cf9162014-09-03 11:05:01 +0000620 far_frame.samples_per_channel_ = reverse_sample_rate / 100;
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000621 far_frame.num_channels_ = msg.num_reverse_channels();
622 near_frame.sample_rate_hz_ = msg.sample_rate();
623 near_frame.samples_per_channel_ = samples_per_channel;
andrew@webrtc.orgbafdae32013-01-11 23:11:29 +0000624 near_frame.num_channels_ = msg.num_input_channels();
aluebs@webrtc.org74cf9162014-09-03 11:05:01 +0000625 reverse_cb.reset(new ChannelBuffer<float>(
626 far_frame.samples_per_channel_,
627 msg.num_reverse_channels()));
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000628 primary_cb.reset(new ChannelBuffer<float>(samples_per_channel,
629 msg.num_input_channels()));
ajm@google.com808e0e02011-08-03 21:08:51 +0000630
631 if (verbose) {
632 printf("Init at frame: %d (primary), %d (reverse)\n",
633 primary_count, reverse_count);
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000634 printf(" Primary rates: %d Hz (in), %d Hz (out)\n",
635 msg.sample_rate(), output_sample_rate);
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000636 printf(" Primary channels: %d (in), %d (out)\n",
637 msg.num_input_channels(),
638 msg.num_output_channels());
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000639 printf(" Reverse rate: %d\n", reverse_sample_rate);
640 printf(" Reverse channels: %d\n", msg.num_reverse_channels());
ajm@google.com808e0e02011-08-03 21:08:51 +0000641 }
642
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000643 if (!raw_output) {
aluebsb0ad43b2015-11-20 00:11:53 -0800644 // The WAV file needs to be reset every time, because it can't change
645 // its sample rate or number of channels.
Peter Kasting69558702016-01-12 16:26:35 -0800646 output_wav_file.reset(new WavWriter(
647 out_filename + ".wav", output_sample_rate,
648 static_cast<size_t>(msg.num_output_channels())));
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000649 }
650
ajm@google.com808e0e02011-08-03 21:08:51 +0000651 } else if (event_msg.type() == Event::REVERSE_STREAM) {
652 ASSERT_TRUE(event_msg.has_reverse_stream());
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000653 ReverseStream msg = event_msg.reverse_stream();
ajm@google.com808e0e02011-08-03 21:08:51 +0000654 reverse_count++;
655
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000656 ASSERT_TRUE(msg.has_data() ^ (msg.channel_size() > 0));
657 if (msg.has_data()) {
aluebs@webrtc.org74cf9162014-09-03 11:05:01 +0000658 ASSERT_EQ(sizeof(int16_t) * far_frame.samples_per_channel_ *
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000659 far_frame.num_channels_, msg.data().size());
660 memcpy(far_frame.data_, msg.data().data(), msg.data().size());
661 } else {
662 for (int i = 0; i < msg.channel_size(); ++i) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000663 memcpy(reverse_cb->channels()[i],
664 msg.channel(i).data(),
665 reverse_cb->num_frames() *
666 sizeof(reverse_cb->channels()[i][0]));
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000667 }
668 }
ajm@google.com808e0e02011-08-03 21:08:51 +0000669
670 if (perf_testing) {
671 t0 = TickTime::Now();
672 }
673
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000674 if (msg.has_data()) {
675 ASSERT_EQ(apm->kNoError,
676 apm->AnalyzeReverseStream(&far_frame));
677 } else {
678 ASSERT_EQ(apm->kNoError,
679 apm->AnalyzeReverseStream(
680 reverse_cb->channels(),
681 far_frame.samples_per_channel_,
682 far_frame.sample_rate_hz_,
683 LayoutFromChannels(far_frame.num_channels_)));
684 }
ajm@google.com808e0e02011-08-03 21:08:51 +0000685
686 if (perf_testing) {
687 t1 = TickTime::Now();
688 TickInterval tick_diff = t1 - t0;
689 acc_ticks += tick_diff;
690 if (tick_diff.Microseconds() > max_time_reverse_us) {
691 max_time_reverse_us = tick_diff.Microseconds();
692 }
693 if (tick_diff.Microseconds() < min_time_reverse_us) {
694 min_time_reverse_us = tick_diff.Microseconds();
695 }
696 }
697
698 } else if (event_msg.type() == Event::STREAM) {
699 ASSERT_TRUE(event_msg.has_stream());
700 const Stream msg = event_msg.stream();
701 primary_count++;
702
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000703 // ProcessStream could have changed this for the output frame.
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000704 near_frame.num_channels_ = apm->num_input_channels();
ajm@google.com808e0e02011-08-03 21:08:51 +0000705
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000706 ASSERT_TRUE(msg.has_input_data() ^ (msg.input_channel_size() > 0));
707 if (msg.has_input_data()) {
708 ASSERT_EQ(sizeof(int16_t) * samples_per_channel *
709 near_frame.num_channels_, msg.input_data().size());
710 memcpy(near_frame.data_,
711 msg.input_data().data(),
712 msg.input_data().size());
aluebs@webrtc.org74cf9162014-09-03 11:05:01 +0000713 near_read_bytes += msg.input_data().size();
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000714 } else {
715 for (int i = 0; i < msg.input_channel_size(); ++i) {
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15 +0000716 memcpy(primary_cb->channels()[i],
717 msg.input_channel(i).data(),
718 primary_cb->num_frames() *
719 sizeof(primary_cb->channels()[i][0]));
aluebs@webrtc.org74cf9162014-09-03 11:05:01 +0000720 near_read_bytes += msg.input_channel(i).size();
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000721 }
722 }
ajm@google.com808e0e02011-08-03 21:08:51 +0000723
ajm@google.com808e0e02011-08-03 21:08:51 +0000724 if (progress && primary_count % 100 == 0) {
aluebs@webrtc.org74cf9162014-09-03 11:05:01 +0000725 near_read_bytes = std::min(near_read_bytes, near_size_bytes);
ajm@google.com808e0e02011-08-03 21:08:51 +0000726 printf("%.0f%% complete\r",
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000727 (near_read_bytes * 100.0) / near_size_bytes);
ajm@google.com808e0e02011-08-03 21:08:51 +0000728 fflush(stdout);
729 }
730
731 if (perf_testing) {
732 t0 = TickTime::Now();
733 }
734
735 ASSERT_EQ(apm->kNoError,
736 apm->gain_control()->set_stream_analog_level(msg.level()));
andrew@webrtc.orgca764ab2013-10-07 16:44:32 +0000737 delay_ms = msg.delay() + extra_delay_ms;
738 if (override_delay_ms) {
739 delay_ms = override_delay_ms;
740 }
ajm@google.com808e0e02011-08-03 21:08:51 +0000741 ASSERT_EQ(apm->kNoError,
andrew@webrtc.orgca764ab2013-10-07 16:44:32 +0000742 apm->set_stream_delay_ms(delay_ms));
andrew@webrtc.org6be1e932013-03-01 18:47:28 +0000743 apm->echo_cancellation()->set_stream_drift_samples(msg.drift());
ajm@google.com808e0e02011-08-03 21:08:51 +0000744
aluebs@webrtc.orgbc1d2242014-02-25 16:50:22 +0000745 if (msg.has_keypress()) {
746 apm->set_stream_key_pressed(msg.keypress());
747 } else {
748 apm->set_stream_key_pressed(true);
749 }
750
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000751 int err = apm->kNoError;
752 if (msg.has_input_data()) {
753 err = apm->ProcessStream(&near_frame);
754 ASSERT_TRUE(near_frame.num_channels_ == apm->num_output_channels());
755 } else {
756 err = apm->ProcessStream(
757 primary_cb->channels(),
758 near_frame.samples_per_channel_,
759 near_frame.sample_rate_hz_,
760 LayoutFromChannels(near_frame.num_channels_),
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000761 output_sample_rate,
762 output_layout,
763 primary_cb->channels());
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000764 }
765
ajm@google.com808e0e02011-08-03 21:08:51 +0000766 if (err == apm->kBadStreamParameterWarning) {
767 printf("Bad parameter warning. %s\n", trace_stream.str().c_str());
768 }
769 ASSERT_TRUE(err == apm->kNoError ||
770 err == apm->kBadStreamParameterWarning);
771
ajm@google.com808e0e02011-08-03 21:08:51 +0000772 stream_has_voice =
773 static_cast<int8_t>(apm->voice_detection()->stream_has_voice());
774 if (vad_out_file != NULL) {
775 ASSERT_EQ(1u, fwrite(&stream_has_voice,
776 sizeof(stream_has_voice),
777 1,
778 vad_out_file));
779 }
780
bjornv@webrtc.org08329f42012-07-12 21:00:43 +0000781 if (ns_prob_file != NULL) {
782 ns_speech_prob = apm->noise_suppression()->speech_probability();
783 ASSERT_EQ(1u, fwrite(&ns_speech_prob,
784 sizeof(ns_speech_prob),
785 1,
786 ns_prob_file));
787 }
788
ajm@google.com808e0e02011-08-03 21:08:51 +0000789 if (perf_testing) {
790 t1 = TickTime::Now();
791 TickInterval tick_diff = t1 - t0;
792 acc_ticks += tick_diff;
793 if (tick_diff.Microseconds() > max_time_us) {
794 max_time_us = tick_diff.Microseconds();
795 }
796 if (tick_diff.Microseconds() < min_time_us) {
797 min_time_us = tick_diff.Microseconds();
798 }
799 }
800
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000801 const size_t samples_per_channel = output_sample_rate / 100;
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000802 if (msg.has_input_data()) {
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000803 if (raw_output && !output_raw_file) {
804 output_raw_file.reset(new RawFile(out_filename + ".pcm"));
805 }
806 WriteIntData(near_frame.data_,
807 apm->num_output_channels() * samples_per_channel,
808 output_wav_file.get(),
809 output_raw_file.get());
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000810 } else {
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000811 if (raw_output && !output_raw_file) {
812 output_raw_file.reset(new RawFile(out_filename + ".float"));
813 }
814 WriteFloatData(primary_cb->channels(),
815 samples_per_channel,
816 apm->num_output_channels(),
817 output_wav_file.get(),
818 output_raw_file.get());
andrew@webrtc.orga8b97372014-03-10 22:26:12 +0000819 }
ajm@google.com808e0e02011-08-03 21:08:51 +0000820 }
821 }
822
823 ASSERT_TRUE(feof(pb_file));
ajm@google.com808e0e02011-08-03 21:08:51 +0000824
825 } else {
bjornv@google.coma2c6ea02011-09-27 08:04:45 +0000826 enum Events {
827 kInitializeEvent,
828 kRenderEvent,
829 kCaptureEvent,
830 kResetEventDeprecated
831 };
832 int16_t event = 0;
ajm@google.com808e0e02011-08-03 21:08:51 +0000833 while (simulating || feof(event_file) == 0) {
834 std::ostringstream trace_stream;
835 trace_stream << "Processed frames: " << reverse_count << " (reverse), "
836 << primary_count << " (primary)";
837 SCOPED_TRACE(trace_stream.str());
838
839 if (simulating) {
840 if (far_file == NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000841 event = kCaptureEvent;
842 } else {
ajm@google.com808e0e02011-08-03 21:08:51 +0000843 if (event == kRenderEvent) {
844 event = kCaptureEvent;
845 } else {
846 event = kRenderEvent;
847 }
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();
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001064 rtc::scoped_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}