blob: 75df72d6d01251bbe902d5ea70c0ac7e4cfe2405 [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"
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");
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";
ivocd66b44d2016-01-15 03:06:36 -0800438 ASSERT_EQ(apm->kNoError, apm->StartDebugRecording(argv[i], -1));
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 {
peah58cf5f12016-02-16 07:26:21 -0800843 event = (event == kCaptureEvent) ? kRenderEvent : kCaptureEvent;
niklase@google.com470e71d2011-07-07 08:21:25 +0000844 }
845 } else {
ajm@google.com808e0e02011-08-03 21:08:51 +0000846 read_count = fread(&event, sizeof(event), 1, event_file);
847 if (read_count != 1) {
848 break;
niklase@google.com470e71d2011-07-07 08:21:25 +0000849 }
850 }
851
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000852 far_frame.sample_rate_hz_ = sample_rate_hz;
853 far_frame.samples_per_channel_ = samples_per_channel;
854 far_frame.num_channels_ = num_render_channels;
855 near_frame.sample_rate_hz_ = sample_rate_hz;
856 near_frame.samples_per_channel_ = samples_per_channel;
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000857
ajm@google.com808e0e02011-08-03 21:08:51 +0000858 if (event == kInitializeEvent || event == kResetEventDeprecated) {
859 ASSERT_EQ(1u,
860 fread(&sample_rate_hz, sizeof(sample_rate_hz), 1, event_file));
861 samples_per_channel = sample_rate_hz / 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000862
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000863 int32_t unused_device_sample_rate_hz;
ajm@google.com808e0e02011-08-03 21:08:51 +0000864 ASSERT_EQ(1u,
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000865 fread(&unused_device_sample_rate_hz,
866 sizeof(unused_device_sample_rate_hz),
ajm@google.com808e0e02011-08-03 21:08:51 +0000867 1,
868 event_file));
869
andrew@webrtc.orgddbb8a22014-04-22 21:00:04 +0000870 ASSERT_EQ(kNoErr, apm->Initialize(
871 sample_rate_hz,
872 sample_rate_hz,
873 sample_rate_hz,
874 LayoutFromChannels(num_capture_input_channels),
875 LayoutFromChannels(num_capture_output_channels),
876 LayoutFromChannels(num_render_channels)));
ajm@google.com808e0e02011-08-03 21:08:51 +0000877
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000878 far_frame.sample_rate_hz_ = sample_rate_hz;
879 far_frame.samples_per_channel_ = samples_per_channel;
880 far_frame.num_channels_ = num_render_channels;
881 near_frame.sample_rate_hz_ = sample_rate_hz;
882 near_frame.samples_per_channel_ = samples_per_channel;
ajm@google.com808e0e02011-08-03 21:08:51 +0000883
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000884 if (!raw_output) {
bjornv@webrtc.org634c9262014-09-24 12:21:51 +0000885 // The WAV file needs to be reset every time, because it can't change
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000886 // it's sample rate or number of channels.
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +0000887 output_wav_file.reset(new WavWriter(out_filename + ".wav",
888 sample_rate_hz,
889 num_capture_output_channels));
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +0000890 }
891
ajm@google.com808e0e02011-08-03 21:08:51 +0000892 if (verbose) {
893 printf("Init at frame: %d (primary), %d (reverse)\n",
894 primary_count, reverse_count);
895 printf(" Sample rate: %d Hz\n", sample_rate_hz);
896 }
897
898 } else if (event == kRenderEvent) {
899 reverse_count++;
ajm@google.com808e0e02011-08-03 21:08:51 +0000900
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000901 size_t size = samples_per_channel * num_render_channels;
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000902 read_count = fread(far_frame.data_,
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000903 sizeof(int16_t),
904 size,
ajm@google.com808e0e02011-08-03 21:08:51 +0000905 far_file);
906
907 if (simulating) {
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000908 if (read_count != size) {
andrew@webrtc.org94c74132011-09-19 15:17:57 +0000909 // Read an equal amount from the near file to avoid errors due to
910 // not reaching end-of-file.
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000911 EXPECT_EQ(0, fseek(near_file, read_count * sizeof(int16_t),
andrew@webrtc.org94c74132011-09-19 15:17:57 +0000912 SEEK_CUR));
Andrew MacDonaldcb05b722015-05-07 22:17:51 -0700913 break; // This is expected.
ajm@google.com808e0e02011-08-03 21:08:51 +0000914 }
915 } else {
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000916 ASSERT_EQ(size, read_count);
ajm@google.com808e0e02011-08-03 21:08:51 +0000917 }
918
919 if (perf_testing) {
920 t0 = TickTime::Now();
921 }
922
923 ASSERT_EQ(apm->kNoError,
924 apm->AnalyzeReverseStream(&far_frame));
925
926 if (perf_testing) {
927 t1 = TickTime::Now();
928 TickInterval tick_diff = t1 - t0;
929 acc_ticks += tick_diff;
930 if (tick_diff.Microseconds() > max_time_reverse_us) {
931 max_time_reverse_us = tick_diff.Microseconds();
932 }
933 if (tick_diff.Microseconds() < min_time_reverse_us) {
934 min_time_reverse_us = tick_diff.Microseconds();
935 }
936 }
937
938 } else if (event == kCaptureEvent) {
939 primary_count++;
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000940 near_frame.num_channels_ = num_capture_input_channels;
ajm@google.com808e0e02011-08-03 21:08:51 +0000941
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000942 size_t size = samples_per_channel * num_capture_input_channels;
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000943 read_count = fread(near_frame.data_,
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000944 sizeof(int16_t),
945 size,
ajm@google.com808e0e02011-08-03 21:08:51 +0000946 near_file);
947
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000948 near_read_bytes += read_count * sizeof(int16_t);
ajm@google.com808e0e02011-08-03 21:08:51 +0000949 if (progress && primary_count % 100 == 0) {
950 printf("%.0f%% complete\r",
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000951 (near_read_bytes * 100.0) / near_size_bytes);
ajm@google.com808e0e02011-08-03 21:08:51 +0000952 fflush(stdout);
953 }
954 if (simulating) {
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000955 if (read_count != size) {
Andrew MacDonaldcb05b722015-05-07 22:17:51 -0700956 break; // This is expected.
ajm@google.com808e0e02011-08-03 21:08:51 +0000957 }
958
959 delay_ms = 0;
960 drift_samples = 0;
961 } else {
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000962 ASSERT_EQ(size, read_count);
ajm@google.com808e0e02011-08-03 21:08:51 +0000963
964 // TODO(ajm): sizeof(delay_ms) for current files?
965 ASSERT_EQ(1u,
966 fread(&delay_ms, 2, 1, delay_file));
967 ASSERT_EQ(1u,
968 fread(&drift_samples, sizeof(drift_samples), 1, drift_file));
969 }
970
andrew@webrtc.orgbafdae32013-01-11 23:11:29 +0000971 if (apm->gain_control()->is_enabled() &&
972 apm->gain_control()->mode() == GainControl::kAdaptiveAnalog) {
andrew@webrtc.org81865342012-10-27 00:28:27 +0000973 SimulateMic(capture_level, &near_frame);
974 }
975
ajm@google.com808e0e02011-08-03 21:08:51 +0000976 if (perf_testing) {
977 t0 = TickTime::Now();
978 }
979
andrew@webrtc.orgbafdae32013-01-11 23:11:29 +0000980 const int capture_level_in = capture_level;
ajm@google.com808e0e02011-08-03 21:08:51 +0000981 ASSERT_EQ(apm->kNoError,
982 apm->gain_control()->set_stream_analog_level(capture_level));
andrew@webrtc.orgca764ab2013-10-07 16:44:32 +0000983 delay_ms += extra_delay_ms;
984 if (override_delay_ms) {
985 delay_ms = override_delay_ms;
986 }
ajm@google.com808e0e02011-08-03 21:08:51 +0000987 ASSERT_EQ(apm->kNoError,
andrew@webrtc.orgca764ab2013-10-07 16:44:32 +0000988 apm->set_stream_delay_ms(delay_ms));
andrew@webrtc.org6be1e932013-03-01 18:47:28 +0000989 apm->echo_cancellation()->set_stream_drift_samples(drift_samples);
ajm@google.com808e0e02011-08-03 21:08:51 +0000990
aluebs@webrtc.orgbc1d2242014-02-25 16:50:22 +0000991 apm->set_stream_key_pressed(true);
992
ajm@google.com808e0e02011-08-03 21:08:51 +0000993 int err = apm->ProcessStream(&near_frame);
994 if (err == apm->kBadStreamParameterWarning) {
995 printf("Bad parameter warning. %s\n", trace_stream.str().c_str());
996 }
997 ASSERT_TRUE(err == apm->kNoError ||
998 err == apm->kBadStreamParameterWarning);
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000999 ASSERT_TRUE(near_frame.num_channels_ == apm->num_output_channels());
ajm@google.com808e0e02011-08-03 21:08:51 +00001000
1001 capture_level = apm->gain_control()->stream_analog_level();
1002
1003 stream_has_voice =
1004 static_cast<int8_t>(apm->voice_detection()->stream_has_voice());
1005 if (vad_out_file != NULL) {
1006 ASSERT_EQ(1u, fwrite(&stream_has_voice,
1007 sizeof(stream_has_voice),
1008 1,
1009 vad_out_file));
1010 }
1011
bjornv@webrtc.org08329f42012-07-12 21:00:43 +00001012 if (ns_prob_file != NULL) {
1013 ns_speech_prob = apm->noise_suppression()->speech_probability();
1014 ASSERT_EQ(1u, fwrite(&ns_speech_prob,
1015 sizeof(ns_speech_prob),
1016 1,
1017 ns_prob_file));
1018 }
1019
ajm@google.com808e0e02011-08-03 21:08:51 +00001020 if (apm->gain_control()->mode() != GainControl::kAdaptiveAnalog) {
1021 ASSERT_EQ(capture_level_in, capture_level);
1022 }
1023
1024 if (perf_testing) {
1025 t1 = TickTime::Now();
1026 TickInterval tick_diff = t1 - t0;
1027 acc_ticks += tick_diff;
1028 if (tick_diff.Microseconds() > max_time_us) {
1029 max_time_us = tick_diff.Microseconds();
1030 }
1031 if (tick_diff.Microseconds() < min_time_us) {
1032 min_time_us = tick_diff.Microseconds();
1033 }
1034 }
1035
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +00001036 if (raw_output && !output_raw_file) {
1037 output_raw_file.reset(new RawFile(out_filename + ".pcm"));
1038 }
bjornv@webrtc.org634c9262014-09-24 12:21:51 +00001039 if (!raw_output && !output_wav_file) {
andrew@webrtc.orga3ed7132014-10-31 21:51:03 +00001040 output_wav_file.reset(new WavWriter(out_filename + ".wav",
1041 sample_rate_hz,
1042 num_capture_output_channels));
bjornv@webrtc.org634c9262014-09-24 12:21:51 +00001043 }
aluebs@webrtc.org021e76f2014-09-04 18:12:00 +00001044 WriteIntData(near_frame.data_,
1045 size,
1046 output_wav_file.get(),
1047 output_raw_file.get());
Andrew MacDonaldcb05b722015-05-07 22:17:51 -07001048 } else {
ajm@google.com808e0e02011-08-03 21:08:51 +00001049 FAIL() << "Event " << event << " is unrecognized";
niklase@google.com470e71d2011-07-07 08:21:25 +00001050 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001051 }
1052 }
peahc1cd2bb2015-11-09 10:38:07 -08001053 if (progress) {
1054 printf("100%% complete\r");
1055 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001056
bjornv@google.comc4b939c2011-07-13 08:09:56 +00001057 if (aecm_echo_path_out_file != NULL) {
ajm@google.com22e65152011-07-18 18:03:01 +00001058 const size_t path_size =
1059 apm->echo_control_mobile()->echo_path_size_bytes();
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001060 rtc::scoped_ptr<char[]> echo_path(new char[path_size]);
andrew@webrtc.org3119ecf2011-11-01 17:00:18 +00001061 apm->echo_control_mobile()->GetEchoPath(echo_path.get(), path_size);
1062 ASSERT_EQ(path_size, fwrite(echo_path.get(),
1063 sizeof(char),
bjornv@google.comc4b939c2011-07-13 08:09:56 +00001064 path_size,
1065 aecm_echo_path_out_file));
1066 fclose(aecm_echo_path_out_file);
1067 aecm_echo_path_out_file = NULL;
1068 }
1069
niklase@google.com470e71d2011-07-07 08:21:25 +00001070 if (verbose) {
1071 printf("\nProcessed frames: %d (primary), %d (reverse)\n",
1072 primary_count, reverse_count);
andrew@webrtc.org94c74132011-09-19 15:17:57 +00001073
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001074 if (apm->level_estimator()->is_enabled()) {
1075 printf("\n--Level metrics--\n");
1076 printf("RMS: %d dBFS\n", -apm->level_estimator()->RMS());
1077 }
andrew@webrtc.org94c74132011-09-19 15:17:57 +00001078 if (apm->echo_cancellation()->are_metrics_enabled()) {
1079 EchoCancellation::Metrics metrics;
1080 apm->echo_cancellation()->GetMetrics(&metrics);
1081 printf("\n--Echo metrics--\n");
1082 printf("(avg, max, min)\n");
1083 printf("ERL: ");
1084 PrintStat(metrics.echo_return_loss);
1085 printf("ERLE: ");
1086 PrintStat(metrics.echo_return_loss_enhancement);
1087 printf("ANLP: ");
1088 PrintStat(metrics.a_nlp);
1089 }
bjornv@google.com1ba3dbe2011-10-03 08:18:10 +00001090 if (apm->echo_cancellation()->is_delay_logging_enabled()) {
1091 int median = 0;
1092 int std = 0;
bjornv@webrtc.orgb1786db2015-02-03 06:06:26 +00001093 float fraction_poor_delays = 0;
1094 apm->echo_cancellation()->GetDelayMetrics(&median, &std,
1095 &fraction_poor_delays);
bjornv@google.com1ba3dbe2011-10-03 08:18:10 +00001096 printf("\n--Delay metrics--\n");
1097 printf("Median: %3d\n", median);
1098 printf("Standard deviation: %3d\n", std);
bjornv@webrtc.orgb1786db2015-02-03 06:06:26 +00001099 printf("Poor delay values: %3.1f%%\n", fraction_poor_delays * 100);
bjornv@google.com1ba3dbe2011-10-03 08:18:10 +00001100 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001101 }
1102
ajm@google.com808e0e02011-08-03 21:08:51 +00001103 if (!pb_file) {
1104 int8_t temp_int8;
1105 if (far_file) {
1106 read_count = fread(&temp_int8, sizeof(temp_int8), 1, far_file);
1107 EXPECT_NE(0, feof(far_file)) << "Far-end file not fully processed";
1108 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001109
ajm@google.com808e0e02011-08-03 21:08:51 +00001110 read_count = fread(&temp_int8, sizeof(temp_int8), 1, near_file);
1111 EXPECT_NE(0, feof(near_file)) << "Near-end file not fully processed";
1112
1113 if (!simulating) {
1114 read_count = fread(&temp_int8, sizeof(temp_int8), 1, event_file);
1115 EXPECT_NE(0, feof(event_file)) << "Event file not fully processed";
1116 read_count = fread(&temp_int8, sizeof(temp_int8), 1, delay_file);
1117 EXPECT_NE(0, feof(delay_file)) << "Delay file not fully processed";
1118 read_count = fread(&temp_int8, sizeof(temp_int8), 1, drift_file);
1119 EXPECT_NE(0, feof(drift_file)) << "Drift file not fully processed";
1120 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001121 }
1122
1123 if (perf_testing) {
1124 if (primary_count > 0) {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +00001125 int64_t exec_time = acc_ticks.Milliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +00001126 printf("\nTotal time: %.3f s, file time: %.2f s\n",
1127 exec_time * 0.001, primary_count * 0.01);
1128 printf("Time per frame: %.3f ms (average), %.3f ms (max),"
1129 " %.3f ms (min)\n",
1130 (exec_time * 1.0) / primary_count,
1131 (max_time_us + max_time_reverse_us) / 1000.0,
1132 (min_time_us + min_time_reverse_us) / 1000.0);
kma@webrtc.org0e739502012-12-07 15:26:28 +00001133 // Record the results with Perf test tools.
kjellander@webrtc.org00ab7cf2013-02-11 12:33:03 +00001134 webrtc::test::PrintResult("audioproc", "", "time_per_10ms_frame",
kma@webrtc.org0e739502012-12-07 15:26:28 +00001135 (exec_time * 1000) / primary_count, "us", false);
niklase@google.com470e71d2011-07-07 08:21:25 +00001136 } else {
1137 printf("Warning: no capture frames\n");
1138 }
1139 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001140}
andrew@webrtc.orga8b97372014-03-10 22:26:12 +00001141
ajm@google.com808e0e02011-08-03 21:08:51 +00001142} // namespace
andrew@webrtc.orga8b97372014-03-10 22:26:12 +00001143} // namespace webrtc
niklase@google.com470e71d2011-07-07 08:21:25 +00001144
Andrew MacDonaldcb05b722015-05-07 22:17:51 -07001145int main(int argc, char* argv[]) {
andrew@webrtc.orga8b97372014-03-10 22:26:12 +00001146 webrtc::void_main(argc, argv);
niklase@google.com470e71d2011-07-07 08:21:25 +00001147
andrew@webrtc.org64235092011-08-19 21:22:08 +00001148 // Optional, but removes memory leak noise from Valgrind.
1149 google::protobuf::ShutdownProtobufLibrary();
niklase@google.com470e71d2011-07-07 08:21:25 +00001150 return 0;
1151}