blob: d0520a03afd17f9ed6c599a59297e4033982de3f [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
andrew@webrtc.org293d22b2012-01-30 22:04:26 +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
ajm@google.com59e41402011-07-28 17:34:04 +000011#include <stdio.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000012
andrew@webrtc.org07bf9a02012-05-05 00:32:00 +000013#include <algorithm>
14
kjellander@webrtc.org61f07c32011-10-18 06:54:58 +000015#include "gtest/gtest.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000016
17#include "audio_processing.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000018#include "event_wrapper.h"
19#include "module_common_types.h"
andrew@webrtc.org3119ecf2011-11-01 17:00:18 +000020#include "scoped_ptr.h"
ajm@google.com59e41402011-07-28 17:34:04 +000021#include "signal_processing_library.h"
andrew@webrtc.org7a281a52012-06-27 03:22:37 +000022#include "test/testsupport/fileutils.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000023#include "thread_wrapper.h"
24#include "trace.h"
leozwang@webrtc.orga3736342012-03-16 21:36:00 +000025#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
leozwang@webrtc.org534e4952012-10-22 21:21:52 +000026#include "external/webrtc/webrtc/modules/audio_processing/test/unittest.pb.h"
leozwang@webrtc.orga3736342012-03-16 21:36:00 +000027#else
ajm@google.com808e0e02011-08-03 21:08:51 +000028#include "webrtc/audio_processing/unittest.pb.h"
leozwang@webrtc.orga3736342012-03-16 21:36:00 +000029#endif
niklase@google.com470e71d2011-07-07 08:21:25 +000030
andrew@webrtc.org293d22b2012-01-30 22:04:26 +000031#if (defined(WEBRTC_AUDIOPROC_FIXED_PROFILE)) || \
32 (defined(WEBRTC_LINUX) && defined(WEBRTC_ARCH_X86_64) && !defined(NDEBUG))
33# define WEBRTC_AUDIOPROC_BIT_EXACT
34#endif
35
niklase@google.com470e71d2011-07-07 08:21:25 +000036using webrtc::AudioProcessing;
37using webrtc::AudioFrame;
38using webrtc::GainControl;
39using webrtc::NoiseSuppression;
40using webrtc::EchoCancellation;
41using webrtc::EventWrapper;
andrew@webrtc.org3119ecf2011-11-01 17:00:18 +000042using webrtc::scoped_array;
niklase@google.com470e71d2011-07-07 08:21:25 +000043using webrtc::Trace;
44using webrtc::LevelEstimator;
45using webrtc::EchoCancellation;
46using webrtc::EchoControlMobile;
47using webrtc::VoiceDetection;
48
49namespace {
ajm@google.com59e41402011-07-28 17:34:04 +000050// When false, this will compare the output data with the results stored to
niklase@google.com470e71d2011-07-07 08:21:25 +000051// file. This is the typical case. When the file should be updated, it can
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +000052// be set to true with the command-line switch --write_ref_data.
53bool write_ref_data = false;
ajm@google.com59e41402011-07-28 17:34:04 +000054
andrew@webrtc.orgecac9b72012-05-02 00:04:10 +000055const int kSampleRates[] = {8000, 16000, 32000};
56const size_t kSampleRatesSize = sizeof(kSampleRates) / sizeof(*kSampleRates);
57const int kChannels[] = {1, 2};
58const size_t kChannelsSize = sizeof(kChannels) / sizeof(*kChannels);
59
andrew@webrtc.org07bf9a02012-05-05 00:32:00 +000060#if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE)
61// AECM doesn't support super-wb.
62const int kProcessSampleRates[] = {8000, 16000};
63#elif defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
64const int kProcessSampleRates[] = {8000, 16000, 32000};
65#endif
66const size_t kProcessSampleRatesSize = sizeof(kProcessSampleRates) /
67 sizeof(*kProcessSampleRates);
68
niklase@google.com470e71d2011-07-07 08:21:25 +000069class ApmTest : public ::testing::Test {
70 protected:
71 ApmTest();
72 virtual void SetUp();
73 virtual void TearDown();
andrew@webrtc.org755b04a2011-11-15 16:57:56 +000074
75 static void SetUpTestCase() {
76 Trace::CreateTrace();
77 std::string trace_filename = webrtc::test::OutputPath() +
78 "audioproc_trace.txt";
79 ASSERT_EQ(0, Trace::SetTraceFile(trace_filename.c_str()));
80 }
81
82 static void TearDownTestCase() {
83 Trace::ReturnTrace();
84 }
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +000085
86 void Init(int sample_rate_hz, int num_reverse_channels,
87 int num_input_channels, int num_output_channels,
88 bool open_output_file);
89 std::string ResourceFilePath(std::string name, int sample_rate_hz);
90 std::string OutputFilePath(std::string name,
91 int sample_rate_hz,
92 int num_reverse_channels,
93 int num_input_channels,
94 int num_output_channels);
andrew@webrtc.org07bf9a02012-05-05 00:32:00 +000095 void EnableAllComponents();
96 bool ReadFrame(FILE* file, AudioFrame* frame);
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +000097
98 const std::string output_path_;
99 const std::string ref_path_;
100 const std::string ref_filename_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000101 webrtc::AudioProcessing* apm_;
102 webrtc::AudioFrame* frame_;
103 webrtc::AudioFrame* revframe_;
104 FILE* far_file_;
105 FILE* near_file_;
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +0000106 FILE* out_file_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000107};
108
109ApmTest::ApmTest()
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +0000110 : output_path_(webrtc::test::OutputPath()),
111 ref_path_(webrtc::test::ProjectRootPath() +
andrew@webrtc.org9dc45da2012-05-23 15:39:01 +0000112 "data/audio_processing/"),
andrew@webrtc.org293d22b2012-01-30 22:04:26 +0000113#if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE)
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +0000114 ref_filename_(ref_path_ + "output_data_fixed.pb"),
andrew@webrtc.org293d22b2012-01-30 22:04:26 +0000115#elif defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +0000116 ref_filename_(ref_path_ + "output_data_float.pb"),
kjellander@webrtc.org61f07c32011-10-18 06:54:58 +0000117#endif
118 apm_(NULL),
niklase@google.com470e71d2011-07-07 08:21:25 +0000119 frame_(NULL),
ajm@google.com22e65152011-07-18 18:03:01 +0000120 revframe_(NULL),
121 far_file_(NULL),
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +0000122 near_file_(NULL),
123 out_file_(NULL) {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000124
125void ApmTest::SetUp() {
126 apm_ = AudioProcessing::Create(0);
127 ASSERT_TRUE(apm_ != NULL);
128
129 frame_ = new AudioFrame();
130 revframe_ = new AudioFrame();
131
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +0000132 Init(32000, 2, 2, 2, false);
niklase@google.com470e71d2011-07-07 08:21:25 +0000133}
134
135void ApmTest::TearDown() {
136 if (frame_) {
137 delete frame_;
138 }
139 frame_ = NULL;
140
141 if (revframe_) {
142 delete revframe_;
143 }
144 revframe_ = NULL;
145
146 if (far_file_) {
147 ASSERT_EQ(0, fclose(far_file_));
148 }
149 far_file_ = NULL;
150
151 if (near_file_) {
152 ASSERT_EQ(0, fclose(near_file_));
153 }
154 near_file_ = NULL;
155
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +0000156 if (out_file_) {
157 ASSERT_EQ(0, fclose(out_file_));
158 }
159 out_file_ = NULL;
160
niklase@google.com470e71d2011-07-07 08:21:25 +0000161 if (apm_ != NULL) {
162 AudioProcessing::Destroy(apm_);
163 }
164 apm_ = NULL;
165}
166
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +0000167std::string ApmTest::ResourceFilePath(std::string name, int sample_rate_hz) {
168 std::ostringstream ss;
169 // Resource files are all stereo.
170 ss << name << sample_rate_hz / 1000 << "_stereo";
171 return webrtc::test::ResourcePath(ss.str(), "pcm");
172}
173
174std::string ApmTest::OutputFilePath(std::string name,
175 int sample_rate_hz,
176 int num_reverse_channels,
177 int num_input_channels,
178 int num_output_channels) {
179 std::ostringstream ss;
180 ss << name << sample_rate_hz / 1000 << "_" << num_reverse_channels << "r" <<
181 num_input_channels << "i" << "_";
182 if (num_output_channels == 1) {
183 ss << "mono";
184 } else if (num_output_channels == 2) {
185 ss << "stereo";
186 } else {
187 assert(false);
188 return "";
189 }
190 ss << ".pcm";
191
192 return output_path_ + ss.str();
193}
194
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +0000195void ApmTest::Init(int sample_rate_hz, int num_reverse_channels,
196 int num_input_channels, int num_output_channels,
197 bool open_output_file) {
198 ASSERT_EQ(apm_->kNoError, apm_->Initialize());
199
200 // Handles error checking of the parameters as well. No need to repeat it.
201 ASSERT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(sample_rate_hz));
202 ASSERT_EQ(apm_->kNoError, apm_->set_num_channels(num_input_channels,
203 num_output_channels));
204 ASSERT_EQ(apm_->kNoError,
205 apm_->set_num_reverse_channels(num_reverse_channels));
206
207 // We always use 10 ms frames.
208 const int samples_per_channel = sample_rate_hz / 100;
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000209 frame_->samples_per_channel_ = samples_per_channel;
210 frame_->num_channels_ = num_input_channels;
211 frame_->sample_rate_hz_ = sample_rate_hz;
212 revframe_->samples_per_channel_ = samples_per_channel;
213 revframe_->num_channels_ = num_reverse_channels;
214 revframe_->sample_rate_hz_ = sample_rate_hz;
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +0000215
216 if (far_file_) {
217 ASSERT_EQ(0, fclose(far_file_));
218 }
219 std::string filename = ResourceFilePath("far", sample_rate_hz);
220 far_file_ = fopen(filename.c_str(), "rb");
221 ASSERT_TRUE(far_file_ != NULL) << "Could not open file " <<
222 filename << "\n";
223
224 if (near_file_) {
225 ASSERT_EQ(0, fclose(near_file_));
226 }
227 filename = ResourceFilePath("near", sample_rate_hz);
228 near_file_ = fopen(filename.c_str(), "rb");
229 ASSERT_TRUE(near_file_ != NULL) << "Could not open file " <<
230 filename << "\n";
231
232 if (open_output_file) {
233 if (out_file_) {
234 ASSERT_EQ(0, fclose(out_file_));
235 }
236 filename = OutputFilePath("out", sample_rate_hz, num_reverse_channels,
237 num_input_channels, num_output_channels);
238 out_file_ = fopen(filename.c_str(), "wb");
239 ASSERT_TRUE(out_file_ != NULL) << "Could not open file " <<
240 filename << "\n";
241 }
242}
243
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000244void MixStereoToMono(const int16_t* stereo,
245 int16_t* mono,
246 int samples_per_channel) {
247 for (int i = 0; i < samples_per_channel; i++) {
248 int32_t int32 = (static_cast<int32_t>(stereo[i * 2]) +
249 static_cast<int32_t>(stereo[i * 2 + 1])) >> 1;
250 mono[i] = static_cast<int16_t>(int32);
niklase@google.com470e71d2011-07-07 08:21:25 +0000251 }
252}
253
andrew@webrtc.org07bf9a02012-05-05 00:32:00 +0000254void CopyLeftToRightChannel(int16_t* stereo, int samples_per_channel) {
255 for (int i = 0; i < samples_per_channel; i++) {
256 stereo[i * 2 + 1] = stereo[i * 2];
257 }
ajm@google.coma769fa52011-07-13 21:57:58 +0000258}
259
andrew@webrtc.org07bf9a02012-05-05 00:32:00 +0000260void VerifyChannelsAreEqual(int16_t* stereo, int samples_per_channel) {
261 for (int i = 0; i < samples_per_channel; i++) {
262 EXPECT_EQ(stereo[i * 2 + 1], stereo[i * 2]);
263 }
264}
265
266void ApmTest::EnableAllComponents() {
267#if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE)
268 EXPECT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(16000));
269 EXPECT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(true));
270
271 EXPECT_EQ(apm_->kNoError,
272 apm_->gain_control()->set_mode(GainControl::kAdaptiveDigital));
273 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
274#elif defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
275 EXPECT_EQ(apm_->kNoError,
276 apm_->echo_cancellation()->enable_drift_compensation(true));
277 EXPECT_EQ(apm_->kNoError,
278 apm_->echo_cancellation()->enable_metrics(true));
279 EXPECT_EQ(apm_->kNoError,
280 apm_->echo_cancellation()->enable_delay_logging(true));
281 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
282
283 EXPECT_EQ(apm_->kNoError,
284 apm_->gain_control()->set_mode(GainControl::kAdaptiveAnalog));
285 EXPECT_EQ(apm_->kNoError,
286 apm_->gain_control()->set_analog_level_limits(0, 255));
287 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
288#endif
289
290 EXPECT_EQ(apm_->kNoError,
291 apm_->high_pass_filter()->Enable(true));
292
293 EXPECT_EQ(apm_->kNoError,
294 apm_->level_estimator()->Enable(true));
295
296 EXPECT_EQ(apm_->kNoError,
297 apm_->noise_suppression()->Enable(true));
298
299 EXPECT_EQ(apm_->kNoError,
300 apm_->voice_detection()->Enable(true));
301}
302
303bool ApmTest::ReadFrame(FILE* file, AudioFrame* frame) {
304 // The files always contain stereo audio.
305 size_t frame_size = frame->samples_per_channel_ * 2;
306 size_t read_count = fread(frame->data_,
307 sizeof(int16_t),
308 frame_size,
309 file);
310 if (read_count != frame_size) {
311 // Check that the file really ended.
312 EXPECT_NE(0, feof(file));
313 return false; // This is expected.
314 }
315
316 if (frame->num_channels_ == 1) {
317 MixStereoToMono(frame->data_, frame->data_,
318 frame->samples_per_channel_);
319 }
320
321 return true;
ajm@google.coma769fa52011-07-13 21:57:58 +0000322}
323
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000324void SetFrameTo(AudioFrame* frame, int16_t value) {
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000325 for (int i = 0; i < frame->samples_per_channel_ * frame->num_channels_;
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000326 ++i) {
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000327 frame->data_[i] = value;
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000328 }
329}
330
andrew@webrtc.orgecac9b72012-05-02 00:04:10 +0000331void SetFrameTo(AudioFrame* frame, int16_t left, int16_t right) {
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000332 ASSERT_EQ(2, frame->num_channels_);
333 for (int i = 0; i < frame->samples_per_channel_ * 2; i += 2) {
334 frame->data_[i] = left;
335 frame->data_[i + 1] = right;
andrew@webrtc.orgecac9b72012-05-02 00:04:10 +0000336 }
337}
338
andrew@webrtc.org07bf9a02012-05-05 00:32:00 +0000339template <class T>
340T AbsValue(T a) {
341 return a > 0 ? a: -a;
342}
343
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000344int16_t MaxAudioFrame(const AudioFrame& frame) {
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000345 const int length = frame.samples_per_channel_ * frame.num_channels_;
andrew@webrtc.org07bf9a02012-05-05 00:32:00 +0000346 int16_t max_data = AbsValue(frame.data_[0]);
ajm@google.coma769fa52011-07-13 21:57:58 +0000347 for (int i = 1; i < length; i++) {
andrew@webrtc.org07bf9a02012-05-05 00:32:00 +0000348 max_data = std::max(max_data, AbsValue(frame.data_[i]));
ajm@google.coma769fa52011-07-13 21:57:58 +0000349 }
350
andrew@webrtc.org07bf9a02012-05-05 00:32:00 +0000351 return max_data;
ajm@google.coma769fa52011-07-13 21:57:58 +0000352}
353
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000354bool FrameDataAreEqual(const AudioFrame& frame1, const AudioFrame& frame2) {
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000355 if (frame1.samples_per_channel_ !=
356 frame2.samples_per_channel_) {
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000357 return false;
358 }
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000359 if (frame1.num_channels_ !=
360 frame2.num_channels_) {
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000361 return false;
362 }
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000363 if (memcmp(frame1.data_, frame2.data_,
364 frame1.samples_per_channel_ * frame1.num_channels_ *
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000365 sizeof(int16_t))) {
366 return false;
367 }
368 return true;
369}
370
ajm@google.coma769fa52011-07-13 21:57:58 +0000371void TestStats(const AudioProcessing::Statistic& test,
ajm@google.com808e0e02011-08-03 21:08:51 +0000372 const webrtc::audioproc::Test::Statistic& reference) {
ajm@google.coma769fa52011-07-13 21:57:58 +0000373 EXPECT_EQ(reference.instant(), test.instant);
374 EXPECT_EQ(reference.average(), test.average);
375 EXPECT_EQ(reference.maximum(), test.maximum);
376 EXPECT_EQ(reference.minimum(), test.minimum);
377}
378
379void WriteStatsMessage(const AudioProcessing::Statistic& output,
ajm@google.com808e0e02011-08-03 21:08:51 +0000380 webrtc::audioproc::Test::Statistic* message) {
ajm@google.coma769fa52011-07-13 21:57:58 +0000381 message->set_instant(output.instant);
382 message->set_average(output.average);
383 message->set_maximum(output.maximum);
384 message->set_minimum(output.minimum);
385}
386
kjellander@webrtc.org61f07c32011-10-18 06:54:58 +0000387void WriteMessageLiteToFile(const std::string filename,
niklase@google.com470e71d2011-07-07 08:21:25 +0000388 const ::google::protobuf::MessageLite& message) {
kjellander@webrtc.org61f07c32011-10-18 06:54:58 +0000389 FILE* file = fopen(filename.c_str(), "wb");
niklase@google.com470e71d2011-07-07 08:21:25 +0000390 ASSERT_TRUE(file != NULL) << "Could not open " << filename;
391 int size = message.ByteSize();
392 ASSERT_GT(size, 0);
393 unsigned char* array = new unsigned char[size];
394 ASSERT_TRUE(message.SerializeToArray(array, size));
395
ajm@google.com22e65152011-07-18 18:03:01 +0000396 ASSERT_EQ(1u, fwrite(&size, sizeof(int), 1, file));
397 ASSERT_EQ(static_cast<size_t>(size),
398 fwrite(array, sizeof(unsigned char), size, file));
niklase@google.com470e71d2011-07-07 08:21:25 +0000399
400 delete [] array;
401 fclose(file);
402}
403
kjellander@webrtc.org61f07c32011-10-18 06:54:58 +0000404void ReadMessageLiteFromFile(const std::string filename,
niklase@google.com470e71d2011-07-07 08:21:25 +0000405 ::google::protobuf::MessageLite* message) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000406 assert(message != NULL);
407
kjellander@webrtc.org61f07c32011-10-18 06:54:58 +0000408 FILE* file = fopen(filename.c_str(), "rb");
niklase@google.com470e71d2011-07-07 08:21:25 +0000409 ASSERT_TRUE(file != NULL) << "Could not open " << filename;
410 int size = 0;
ajm@google.com22e65152011-07-18 18:03:01 +0000411 ASSERT_EQ(1u, fread(&size, sizeof(int), 1, file));
niklase@google.com470e71d2011-07-07 08:21:25 +0000412 ASSERT_GT(size, 0);
413 unsigned char* array = new unsigned char[size];
ajm@google.com22e65152011-07-18 18:03:01 +0000414 ASSERT_EQ(static_cast<size_t>(size),
415 fread(array, sizeof(unsigned char), size, file));
niklase@google.com470e71d2011-07-07 08:21:25 +0000416
417 ASSERT_TRUE(message->ParseFromArray(array, size));
418
419 delete [] array;
420 fclose(file);
421}
422
423struct ThreadData {
424 ThreadData(int thread_num_, AudioProcessing* ap_)
425 : thread_num(thread_num_),
426 error(false),
427 ap(ap_) {}
428 int thread_num;
429 bool error;
430 AudioProcessing* ap;
431};
432
433// Don't use GTest here; non-thread-safe on Windows (as of 1.5.0).
434bool DeadlockProc(void* thread_object) {
435 ThreadData* thread_data = static_cast<ThreadData*>(thread_object);
436 AudioProcessing* ap = thread_data->ap;
437 int err = ap->kNoError;
438
439 AudioFrame primary_frame;
440 AudioFrame reverse_frame;
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000441 primary_frame.samples_per_channel_ = 320;
442 primary_frame.num_channels_ = 2;
443 primary_frame.sample_rate_hz_ = 32000;
444 reverse_frame.samples_per_channel_ = 320;
445 reverse_frame.num_channels_ = 2;
446 reverse_frame.sample_rate_hz_ = 32000;
niklase@google.com470e71d2011-07-07 08:21:25 +0000447
448 ap->echo_cancellation()->Enable(true);
449 ap->gain_control()->Enable(true);
450 ap->high_pass_filter()->Enable(true);
451 ap->level_estimator()->Enable(true);
452 ap->noise_suppression()->Enable(true);
453 ap->voice_detection()->Enable(true);
454
455 if (thread_data->thread_num % 2 == 0) {
456 err = ap->AnalyzeReverseStream(&reverse_frame);
457 if (err != ap->kNoError) {
458 printf("Error in AnalyzeReverseStream(): %d\n", err);
459 thread_data->error = true;
460 return false;
461 }
462 }
463
464 if (thread_data->thread_num % 2 == 1) {
465 ap->set_stream_delay_ms(0);
466 ap->echo_cancellation()->set_stream_drift_samples(0);
467 ap->gain_control()->set_stream_analog_level(0);
468 err = ap->ProcessStream(&primary_frame);
469 if (err == ap->kStreamParameterNotSetError) {
470 printf("Expected kStreamParameterNotSetError in ProcessStream(): %d\n",
471 err);
472 } else if (err != ap->kNoError) {
473 printf("Error in ProcessStream(): %d\n", err);
474 thread_data->error = true;
475 return false;
476 }
477 ap->gain_control()->stream_analog_level();
478 }
479
480 EventWrapper* event = EventWrapper::Create();
481 event->Wait(1);
482 delete event;
483 event = NULL;
484
485 return true;
486}
487
488/*TEST_F(ApmTest, Deadlock) {
489 const int num_threads = 16;
490 std::vector<ThreadWrapper*> threads(num_threads);
491 std::vector<ThreadData*> thread_data(num_threads);
492
493 ASSERT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(32000));
494 ASSERT_EQ(apm_->kNoError, apm_->set_num_channels(2, 2));
495 ASSERT_EQ(apm_->kNoError, apm_->set_num_reverse_channels(2));
496
497 for (int i = 0; i < num_threads; i++) {
498 thread_data[i] = new ThreadData(i, apm_);
499 threads[i] = ThreadWrapper::CreateThread(DeadlockProc,
500 thread_data[i],
501 kNormalPriority,
502 0);
503 ASSERT_TRUE(threads[i] != NULL);
504 unsigned int thread_id = 0;
505 threads[i]->Start(thread_id);
506 }
507
508 EventWrapper* event = EventWrapper::Create();
509 ASSERT_EQ(kEventTimeout, event->Wait(5000));
510 delete event;
511 event = NULL;
512
513 for (int i = 0; i < num_threads; i++) {
514 // This will return false if the thread has deadlocked.
515 ASSERT_TRUE(threads[i]->Stop());
516 ASSERT_FALSE(thread_data[i]->error);
517 delete threads[i];
518 threads[i] = NULL;
519 delete thread_data[i];
520 thread_data[i] = NULL;
521 }
522}*/
523
524TEST_F(ApmTest, StreamParameters) {
525 // No errors when the components are disabled.
526 EXPECT_EQ(apm_->kNoError,
527 apm_->ProcessStream(frame_));
528
andrew@webrtc.org1e916932011-11-29 18:28:57 +0000529 // -- Missing AGC level --
niklase@google.com470e71d2011-07-07 08:21:25 +0000530 EXPECT_EQ(apm_->kNoError, apm_->Initialize());
531 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
andrew@webrtc.org1e916932011-11-29 18:28:57 +0000532 EXPECT_EQ(apm_->kStreamParameterNotSetError, apm_->ProcessStream(frame_));
niklase@google.com470e71d2011-07-07 08:21:25 +0000533
andrew@webrtc.org1e916932011-11-29 18:28:57 +0000534 // Resets after successful ProcessStream().
niklase@google.com470e71d2011-07-07 08:21:25 +0000535 EXPECT_EQ(apm_->kNoError,
536 apm_->gain_control()->set_stream_analog_level(127));
andrew@webrtc.org1e916932011-11-29 18:28:57 +0000537 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
538 EXPECT_EQ(apm_->kStreamParameterNotSetError, apm_->ProcessStream(frame_));
niklase@google.com470e71d2011-07-07 08:21:25 +0000539
andrew@webrtc.org1e916932011-11-29 18:28:57 +0000540 // Other stream parameters set correctly.
541 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
niklase@google.com470e71d2011-07-07 08:21:25 +0000542 EXPECT_EQ(apm_->kNoError,
543 apm_->echo_cancellation()->enable_drift_compensation(true));
andrew@webrtc.org1e916932011-11-29 18:28:57 +0000544 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
545 EXPECT_EQ(apm_->kNoError,
546 apm_->echo_cancellation()->set_stream_drift_samples(0));
niklase@google.com470e71d2011-07-07 08:21:25 +0000547 EXPECT_EQ(apm_->kStreamParameterNotSetError,
548 apm_->ProcessStream(frame_));
andrew@webrtc.org1e916932011-11-29 18:28:57 +0000549 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(false));
550 EXPECT_EQ(apm_->kNoError,
551 apm_->echo_cancellation()->enable_drift_compensation(false));
552
553 // -- Missing delay --
554 EXPECT_EQ(apm_->kNoError, apm_->Initialize());
555 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
556 EXPECT_EQ(apm_->kStreamParameterNotSetError, apm_->ProcessStream(frame_));
557
558 // Resets after successful ProcessStream().
559 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
560 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
561 EXPECT_EQ(apm_->kStreamParameterNotSetError, apm_->ProcessStream(frame_));
562
563 // Other stream parameters set correctly.
564 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
565 EXPECT_EQ(apm_->kNoError,
566 apm_->echo_cancellation()->enable_drift_compensation(true));
567 EXPECT_EQ(apm_->kNoError,
568 apm_->echo_cancellation()->set_stream_drift_samples(0));
569 EXPECT_EQ(apm_->kNoError,
570 apm_->gain_control()->set_stream_analog_level(127));
571 EXPECT_EQ(apm_->kStreamParameterNotSetError, apm_->ProcessStream(frame_));
572 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(false));
573
574 // -- Missing drift --
575 EXPECT_EQ(apm_->kNoError, apm_->Initialize());
576 EXPECT_EQ(apm_->kStreamParameterNotSetError, apm_->ProcessStream(frame_));
577
578 // Resets after successful ProcessStream().
579 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
580 EXPECT_EQ(apm_->kNoError,
581 apm_->echo_cancellation()->set_stream_drift_samples(0));
582 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
583 EXPECT_EQ(apm_->kStreamParameterNotSetError, apm_->ProcessStream(frame_));
584
585 // Other stream parameters set correctly.
niklase@google.com470e71d2011-07-07 08:21:25 +0000586 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
587 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
588 EXPECT_EQ(apm_->kNoError,
589 apm_->gain_control()->set_stream_analog_level(127));
andrew@webrtc.org1e916932011-11-29 18:28:57 +0000590 EXPECT_EQ(apm_->kStreamParameterNotSetError, apm_->ProcessStream(frame_));
niklase@google.com470e71d2011-07-07 08:21:25 +0000591
andrew@webrtc.org1e916932011-11-29 18:28:57 +0000592 // -- No stream parameters --
niklase@google.com470e71d2011-07-07 08:21:25 +0000593 EXPECT_EQ(apm_->kNoError, apm_->Initialize());
594 EXPECT_EQ(apm_->kNoError,
595 apm_->AnalyzeReverseStream(revframe_));
596 EXPECT_EQ(apm_->kStreamParameterNotSetError,
597 apm_->ProcessStream(frame_));
598
andrew@webrtc.org1e916932011-11-29 18:28:57 +0000599 // -- All there --
niklase@google.com470e71d2011-07-07 08:21:25 +0000600 EXPECT_EQ(apm_->kNoError, apm_->Initialize());
601 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
602 EXPECT_EQ(apm_->kNoError,
603 apm_->echo_cancellation()->set_stream_drift_samples(0));
604 EXPECT_EQ(apm_->kNoError,
605 apm_->gain_control()->set_stream_analog_level(127));
606 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
607}
608
andrew@webrtc.org5f23d642012-05-29 21:14:06 +0000609TEST_F(ApmTest, DefaultDelayOffsetIsZero) {
610 EXPECT_EQ(0, apm_->delay_offset_ms());
611 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(50));
612 EXPECT_EQ(50, apm_->stream_delay_ms());
613}
614
615TEST_F(ApmTest, DelayOffsetWithLimitsIsSetProperly) {
616 // High limit of 500 ms.
andrew@webrtc.org6f9f8172012-03-06 19:03:39 +0000617 apm_->set_delay_offset_ms(100);
618 EXPECT_EQ(100, apm_->delay_offset_ms());
619 EXPECT_EQ(apm_->kBadStreamParameterWarning, apm_->set_stream_delay_ms(450));
andrew@webrtc.org5f23d642012-05-29 21:14:06 +0000620 EXPECT_EQ(500, apm_->stream_delay_ms());
andrew@webrtc.org6f9f8172012-03-06 19:03:39 +0000621 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
622 EXPECT_EQ(200, apm_->stream_delay_ms());
623
andrew@webrtc.org5f23d642012-05-29 21:14:06 +0000624 // Low limit of 0 ms.
andrew@webrtc.org6f9f8172012-03-06 19:03:39 +0000625 apm_->set_delay_offset_ms(-50);
626 EXPECT_EQ(-50, apm_->delay_offset_ms());
andrew@webrtc.org5f23d642012-05-29 21:14:06 +0000627 EXPECT_EQ(apm_->kBadStreamParameterWarning, apm_->set_stream_delay_ms(20));
628 EXPECT_EQ(0, apm_->stream_delay_ms());
andrew@webrtc.org6f9f8172012-03-06 19:03:39 +0000629 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
630 EXPECT_EQ(50, apm_->stream_delay_ms());
631}
632
niklase@google.com470e71d2011-07-07 08:21:25 +0000633TEST_F(ApmTest, Channels) {
634 // Testing number of invalid channels
635 EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_channels(0, 1));
636 EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_channels(1, 0));
637 EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_channels(3, 1));
638 EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_channels(1, 3));
639 EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_reverse_channels(0));
640 EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_reverse_channels(3));
641 // Testing number of valid channels
642 for (int i = 1; i < 3; i++) {
643 for (int j = 1; j < 3; j++) {
644 if (j > i) {
645 EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_channels(i, j));
646 } else {
647 EXPECT_EQ(apm_->kNoError, apm_->set_num_channels(i, j));
648 EXPECT_EQ(j, apm_->num_output_channels());
649 }
650 }
651 EXPECT_EQ(i, apm_->num_input_channels());
652 EXPECT_EQ(apm_->kNoError, apm_->set_num_reverse_channels(i));
653 EXPECT_EQ(i, apm_->num_reverse_channels());
654 }
655}
656
657TEST_F(ApmTest, SampleRates) {
658 // Testing invalid sample rates
659 EXPECT_EQ(apm_->kBadParameterError, apm_->set_sample_rate_hz(10000));
660 // Testing valid sample rates
661 int fs[] = {8000, 16000, 32000};
662 for (size_t i = 0; i < sizeof(fs) / sizeof(*fs); i++) {
663 EXPECT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(fs[i]));
664 EXPECT_EQ(fs[i], apm_->sample_rate_hz());
665 }
666}
667
niklase@google.com470e71d2011-07-07 08:21:25 +0000668
669TEST_F(ApmTest, EchoCancellation) {
670 EXPECT_EQ(apm_->kNoError,
671 apm_->echo_cancellation()->enable_drift_compensation(true));
672 EXPECT_TRUE(apm_->echo_cancellation()->is_drift_compensation_enabled());
673 EXPECT_EQ(apm_->kNoError,
674 apm_->echo_cancellation()->enable_drift_compensation(false));
675 EXPECT_FALSE(apm_->echo_cancellation()->is_drift_compensation_enabled());
676
677 EXPECT_EQ(apm_->kBadParameterError,
678 apm_->echo_cancellation()->set_device_sample_rate_hz(4000));
679 EXPECT_EQ(apm_->kBadParameterError,
680 apm_->echo_cancellation()->set_device_sample_rate_hz(100000));
681
682 int rate[] = {16000, 44100, 48000};
683 for (size_t i = 0; i < sizeof(rate)/sizeof(*rate); i++) {
684 EXPECT_EQ(apm_->kNoError,
685 apm_->echo_cancellation()->set_device_sample_rate_hz(rate[i]));
686 EXPECT_EQ(rate[i],
687 apm_->echo_cancellation()->device_sample_rate_hz());
688 }
689
niklase@google.com470e71d2011-07-07 08:21:25 +0000690 EchoCancellation::SuppressionLevel level[] = {
691 EchoCancellation::kLowSuppression,
692 EchoCancellation::kModerateSuppression,
693 EchoCancellation::kHighSuppression,
694 };
695 for (size_t i = 0; i < sizeof(level)/sizeof(*level); i++) {
696 EXPECT_EQ(apm_->kNoError,
697 apm_->echo_cancellation()->set_suppression_level(level[i]));
698 EXPECT_EQ(level[i],
699 apm_->echo_cancellation()->suppression_level());
700 }
701
702 EchoCancellation::Metrics metrics;
703 EXPECT_EQ(apm_->kNotEnabledError,
704 apm_->echo_cancellation()->GetMetrics(&metrics));
705
706 EXPECT_EQ(apm_->kNoError,
707 apm_->echo_cancellation()->enable_metrics(true));
708 EXPECT_TRUE(apm_->echo_cancellation()->are_metrics_enabled());
709 EXPECT_EQ(apm_->kNoError,
710 apm_->echo_cancellation()->enable_metrics(false));
711 EXPECT_FALSE(apm_->echo_cancellation()->are_metrics_enabled());
712
bjornv@google.com1ba3dbe2011-10-03 08:18:10 +0000713 int median = 0;
714 int std = 0;
715 EXPECT_EQ(apm_->kNotEnabledError,
716 apm_->echo_cancellation()->GetDelayMetrics(&median, &std));
717
718 EXPECT_EQ(apm_->kNoError,
719 apm_->echo_cancellation()->enable_delay_logging(true));
720 EXPECT_TRUE(apm_->echo_cancellation()->is_delay_logging_enabled());
721 EXPECT_EQ(apm_->kNoError,
722 apm_->echo_cancellation()->enable_delay_logging(false));
723 EXPECT_FALSE(apm_->echo_cancellation()->is_delay_logging_enabled());
724
niklase@google.com470e71d2011-07-07 08:21:25 +0000725 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
726 EXPECT_TRUE(apm_->echo_cancellation()->is_enabled());
727 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false));
728 EXPECT_FALSE(apm_->echo_cancellation()->is_enabled());
729}
730
731TEST_F(ApmTest, EchoControlMobile) {
732 // AECM won't use super-wideband.
733 EXPECT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(32000));
734 EXPECT_EQ(apm_->kBadSampleRateError, apm_->echo_control_mobile()->Enable(true));
niklase@google.com470e71d2011-07-07 08:21:25 +0000735 // Turn AECM on (and AEC off)
andrew@webrtc.org75f19482012-02-09 17:16:18 +0000736 Init(16000, 2, 2, 2, false);
niklase@google.com470e71d2011-07-07 08:21:25 +0000737 EXPECT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(true));
738 EXPECT_TRUE(apm_->echo_control_mobile()->is_enabled());
739
niklase@google.com470e71d2011-07-07 08:21:25 +0000740 // Toggle routing modes
741 EchoControlMobile::RoutingMode mode[] = {
742 EchoControlMobile::kQuietEarpieceOrHeadset,
743 EchoControlMobile::kEarpiece,
744 EchoControlMobile::kLoudEarpiece,
745 EchoControlMobile::kSpeakerphone,
746 EchoControlMobile::kLoudSpeakerphone,
747 };
748 for (size_t i = 0; i < sizeof(mode)/sizeof(*mode); i++) {
749 EXPECT_EQ(apm_->kNoError,
750 apm_->echo_control_mobile()->set_routing_mode(mode[i]));
751 EXPECT_EQ(mode[i],
752 apm_->echo_control_mobile()->routing_mode());
753 }
754 // Turn comfort noise off/on
755 EXPECT_EQ(apm_->kNoError,
756 apm_->echo_control_mobile()->enable_comfort_noise(false));
757 EXPECT_FALSE(apm_->echo_control_mobile()->is_comfort_noise_enabled());
758 EXPECT_EQ(apm_->kNoError,
759 apm_->echo_control_mobile()->enable_comfort_noise(true));
760 EXPECT_TRUE(apm_->echo_control_mobile()->is_comfort_noise_enabled());
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000761 // Set and get echo path
ajm@google.com22e65152011-07-18 18:03:01 +0000762 const size_t echo_path_size =
763 apm_->echo_control_mobile()->echo_path_size_bytes();
andrew@webrtc.org3119ecf2011-11-01 17:00:18 +0000764 scoped_array<char> echo_path_in(new char[echo_path_size]);
765 scoped_array<char> echo_path_out(new char[echo_path_size]);
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000766 EXPECT_EQ(apm_->kNullPointerError,
767 apm_->echo_control_mobile()->SetEchoPath(NULL, echo_path_size));
768 EXPECT_EQ(apm_->kNullPointerError,
769 apm_->echo_control_mobile()->GetEchoPath(NULL, echo_path_size));
770 EXPECT_EQ(apm_->kBadParameterError,
andrew@webrtc.org3119ecf2011-11-01 17:00:18 +0000771 apm_->echo_control_mobile()->GetEchoPath(echo_path_out.get(), 1));
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000772 EXPECT_EQ(apm_->kNoError,
andrew@webrtc.org3119ecf2011-11-01 17:00:18 +0000773 apm_->echo_control_mobile()->GetEchoPath(echo_path_out.get(),
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000774 echo_path_size));
ajm@google.com22e65152011-07-18 18:03:01 +0000775 for (size_t i = 0; i < echo_path_size; i++) {
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000776 echo_path_in[i] = echo_path_out[i] + 1;
777 }
778 EXPECT_EQ(apm_->kBadParameterError,
andrew@webrtc.org3119ecf2011-11-01 17:00:18 +0000779 apm_->echo_control_mobile()->SetEchoPath(echo_path_in.get(), 1));
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000780 EXPECT_EQ(apm_->kNoError,
andrew@webrtc.org3119ecf2011-11-01 17:00:18 +0000781 apm_->echo_control_mobile()->SetEchoPath(echo_path_in.get(),
782 echo_path_size));
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000783 EXPECT_EQ(apm_->kNoError,
andrew@webrtc.org3119ecf2011-11-01 17:00:18 +0000784 apm_->echo_control_mobile()->GetEchoPath(echo_path_out.get(),
785 echo_path_size));
ajm@google.com22e65152011-07-18 18:03:01 +0000786 for (size_t i = 0; i < echo_path_size; i++) {
bjornv@google.comc4b939c2011-07-13 08:09:56 +0000787 EXPECT_EQ(echo_path_in[i], echo_path_out[i]);
788 }
andrew@webrtc.org75f19482012-02-09 17:16:18 +0000789
790 // Process a few frames with NS in the default disabled state. This exercises
791 // a different codepath than with it enabled.
792 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0));
793 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
794 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0));
795 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
796
niklase@google.com470e71d2011-07-07 08:21:25 +0000797 // Turn AECM off
798 EXPECT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(false));
799 EXPECT_FALSE(apm_->echo_control_mobile()->is_enabled());
800}
801
802TEST_F(ApmTest, GainControl) {
803 // Testing gain modes
niklase@google.com470e71d2011-07-07 08:21:25 +0000804 EXPECT_EQ(apm_->kNoError,
805 apm_->gain_control()->set_mode(
806 apm_->gain_control()->mode()));
807
808 GainControl::Mode mode[] = {
809 GainControl::kAdaptiveAnalog,
810 GainControl::kAdaptiveDigital,
811 GainControl::kFixedDigital
812 };
813 for (size_t i = 0; i < sizeof(mode)/sizeof(*mode); i++) {
814 EXPECT_EQ(apm_->kNoError,
815 apm_->gain_control()->set_mode(mode[i]));
816 EXPECT_EQ(mode[i], apm_->gain_control()->mode());
817 }
818 // Testing invalid target levels
819 EXPECT_EQ(apm_->kBadParameterError,
820 apm_->gain_control()->set_target_level_dbfs(-3));
821 EXPECT_EQ(apm_->kBadParameterError,
822 apm_->gain_control()->set_target_level_dbfs(-40));
823 // Testing valid target levels
824 EXPECT_EQ(apm_->kNoError,
825 apm_->gain_control()->set_target_level_dbfs(
826 apm_->gain_control()->target_level_dbfs()));
827
828 int level_dbfs[] = {0, 6, 31};
829 for (size_t i = 0; i < sizeof(level_dbfs)/sizeof(*level_dbfs); i++) {
830 EXPECT_EQ(apm_->kNoError,
831 apm_->gain_control()->set_target_level_dbfs(level_dbfs[i]));
832 EXPECT_EQ(level_dbfs[i], apm_->gain_control()->target_level_dbfs());
833 }
834
835 // Testing invalid compression gains
836 EXPECT_EQ(apm_->kBadParameterError,
837 apm_->gain_control()->set_compression_gain_db(-1));
838 EXPECT_EQ(apm_->kBadParameterError,
839 apm_->gain_control()->set_compression_gain_db(100));
840
841 // Testing valid compression gains
842 EXPECT_EQ(apm_->kNoError,
843 apm_->gain_control()->set_compression_gain_db(
844 apm_->gain_control()->compression_gain_db()));
845
846 int gain_db[] = {0, 10, 90};
847 for (size_t i = 0; i < sizeof(gain_db)/sizeof(*gain_db); i++) {
848 EXPECT_EQ(apm_->kNoError,
849 apm_->gain_control()->set_compression_gain_db(gain_db[i]));
850 EXPECT_EQ(gain_db[i], apm_->gain_control()->compression_gain_db());
851 }
852
853 // Testing limiter off/on
854 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->enable_limiter(false));
855 EXPECT_FALSE(apm_->gain_control()->is_limiter_enabled());
856 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->enable_limiter(true));
857 EXPECT_TRUE(apm_->gain_control()->is_limiter_enabled());
858
859 // Testing invalid level limits
860 EXPECT_EQ(apm_->kBadParameterError,
861 apm_->gain_control()->set_analog_level_limits(-1, 512));
862 EXPECT_EQ(apm_->kBadParameterError,
863 apm_->gain_control()->set_analog_level_limits(100000, 512));
864 EXPECT_EQ(apm_->kBadParameterError,
865 apm_->gain_control()->set_analog_level_limits(512, -1));
866 EXPECT_EQ(apm_->kBadParameterError,
867 apm_->gain_control()->set_analog_level_limits(512, 100000));
868 EXPECT_EQ(apm_->kBadParameterError,
869 apm_->gain_control()->set_analog_level_limits(512, 255));
870
871 // Testing valid level limits
872 EXPECT_EQ(apm_->kNoError,
873 apm_->gain_control()->set_analog_level_limits(
874 apm_->gain_control()->analog_level_minimum(),
875 apm_->gain_control()->analog_level_maximum()));
876
877 int min_level[] = {0, 255, 1024};
878 for (size_t i = 0; i < sizeof(min_level)/sizeof(*min_level); i++) {
879 EXPECT_EQ(apm_->kNoError,
880 apm_->gain_control()->set_analog_level_limits(min_level[i], 1024));
881 EXPECT_EQ(min_level[i], apm_->gain_control()->analog_level_minimum());
882 }
883
884 int max_level[] = {0, 1024, 65535};
885 for (size_t i = 0; i < sizeof(min_level)/sizeof(*min_level); i++) {
886 EXPECT_EQ(apm_->kNoError,
887 apm_->gain_control()->set_analog_level_limits(0, max_level[i]));
888 EXPECT_EQ(max_level[i], apm_->gain_control()->analog_level_maximum());
889 }
890
891 // TODO(ajm): stream_is_saturated() and stream_analog_level()
892
893 // Turn AGC off
894 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(false));
895 EXPECT_FALSE(apm_->gain_control()->is_enabled());
896}
897
898TEST_F(ApmTest, NoiseSuppression) {
andrew@webrtc.org648af742012-02-08 01:57:29 +0000899 // Test valid suppression levels.
niklase@google.com470e71d2011-07-07 08:21:25 +0000900 NoiseSuppression::Level level[] = {
901 NoiseSuppression::kLow,
902 NoiseSuppression::kModerate,
903 NoiseSuppression::kHigh,
904 NoiseSuppression::kVeryHigh
905 };
906 for (size_t i = 0; i < sizeof(level)/sizeof(*level); i++) {
907 EXPECT_EQ(apm_->kNoError,
908 apm_->noise_suppression()->set_level(level[i]));
909 EXPECT_EQ(level[i], apm_->noise_suppression()->level());
910 }
911
andrew@webrtc.org648af742012-02-08 01:57:29 +0000912 // Turn NS on/off
niklase@google.com470e71d2011-07-07 08:21:25 +0000913 EXPECT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(true));
914 EXPECT_TRUE(apm_->noise_suppression()->is_enabled());
915 EXPECT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(false));
916 EXPECT_FALSE(apm_->noise_suppression()->is_enabled());
917}
918
919TEST_F(ApmTest, HighPassFilter) {
andrew@webrtc.org648af742012-02-08 01:57:29 +0000920 // Turn HP filter on/off
niklase@google.com470e71d2011-07-07 08:21:25 +0000921 EXPECT_EQ(apm_->kNoError, apm_->high_pass_filter()->Enable(true));
922 EXPECT_TRUE(apm_->high_pass_filter()->is_enabled());
923 EXPECT_EQ(apm_->kNoError, apm_->high_pass_filter()->Enable(false));
924 EXPECT_FALSE(apm_->high_pass_filter()->is_enabled());
925}
926
927TEST_F(ApmTest, LevelEstimator) {
andrew@webrtc.org648af742012-02-08 01:57:29 +0000928 // Turn level estimator on/off
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000929 EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(false));
niklase@google.com470e71d2011-07-07 08:21:25 +0000930 EXPECT_FALSE(apm_->level_estimator()->is_enabled());
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000931
932 EXPECT_EQ(apm_->kNotEnabledError, apm_->level_estimator()->RMS());
933
934 EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true));
935 EXPECT_TRUE(apm_->level_estimator()->is_enabled());
936
937 // Run this test in wideband; in super-wb, the splitting filter distorts the
938 // audio enough to cause deviation from the expectation for small values.
939 EXPECT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(16000));
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000940 frame_->samples_per_channel_ = 160;
941 frame_->num_channels_ = 2;
942 frame_->sample_rate_hz_ = 16000;
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000943
944 // Min value if no frames have been processed.
945 EXPECT_EQ(127, apm_->level_estimator()->RMS());
946
947 // Min value on zero frames.
948 SetFrameTo(frame_, 0);
949 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
950 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
951 EXPECT_EQ(127, apm_->level_estimator()->RMS());
952
953 // Try a few RMS values.
954 // (These also test that the value resets after retrieving it.)
955 SetFrameTo(frame_, 32767);
956 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
957 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
958 EXPECT_EQ(0, apm_->level_estimator()->RMS());
959
960 SetFrameTo(frame_, 30000);
961 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
962 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
963 EXPECT_EQ(1, apm_->level_estimator()->RMS());
964
965 SetFrameTo(frame_, 10000);
966 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
967 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
968 EXPECT_EQ(10, apm_->level_estimator()->RMS());
969
970 SetFrameTo(frame_, 10);
971 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
972 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
973 EXPECT_EQ(70, apm_->level_estimator()->RMS());
974
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000975 // Min value if energy_ == 0.
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000976 SetFrameTo(frame_, 10000);
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000977 uint32_t energy = frame_->energy_; // Save default to restore below.
978 frame_->energy_ = 0;
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000979 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
980 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
981 EXPECT_EQ(127, apm_->level_estimator()->RMS());
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000982 frame_->energy_ = energy;
andrew@webrtc.org755b04a2011-11-15 16:57:56 +0000983
984 // Verify reset after enable/disable.
985 SetFrameTo(frame_, 32767);
986 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
987 EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(false));
988 EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true));
989 SetFrameTo(frame_, 1);
990 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
991 EXPECT_EQ(90, apm_->level_estimator()->RMS());
992
993 // Verify reset after initialize.
994 SetFrameTo(frame_, 32767);
995 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
996 EXPECT_EQ(apm_->kNoError, apm_->Initialize());
997 SetFrameTo(frame_, 1);
998 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
999 EXPECT_EQ(90, apm_->level_estimator()->RMS());
niklase@google.com470e71d2011-07-07 08:21:25 +00001000}
1001
1002TEST_F(ApmTest, VoiceDetection) {
1003 // Test external VAD
1004 EXPECT_EQ(apm_->kNoError,
1005 apm_->voice_detection()->set_stream_has_voice(true));
1006 EXPECT_TRUE(apm_->voice_detection()->stream_has_voice());
1007 EXPECT_EQ(apm_->kNoError,
1008 apm_->voice_detection()->set_stream_has_voice(false));
1009 EXPECT_FALSE(apm_->voice_detection()->stream_has_voice());
1010
andrew@webrtc.org648af742012-02-08 01:57:29 +00001011 // Test valid likelihoods
niklase@google.com470e71d2011-07-07 08:21:25 +00001012 VoiceDetection::Likelihood likelihood[] = {
1013 VoiceDetection::kVeryLowLikelihood,
1014 VoiceDetection::kLowLikelihood,
1015 VoiceDetection::kModerateLikelihood,
1016 VoiceDetection::kHighLikelihood
1017 };
1018 for (size_t i = 0; i < sizeof(likelihood)/sizeof(*likelihood); i++) {
1019 EXPECT_EQ(apm_->kNoError,
1020 apm_->voice_detection()->set_likelihood(likelihood[i]));
1021 EXPECT_EQ(likelihood[i], apm_->voice_detection()->likelihood());
1022 }
1023
1024 /* TODO(bjornv): Enable once VAD supports other frame lengths than 10 ms
andrew@webrtc.org648af742012-02-08 01:57:29 +00001025 // Test invalid frame sizes
niklase@google.com470e71d2011-07-07 08:21:25 +00001026 EXPECT_EQ(apm_->kBadParameterError,
1027 apm_->voice_detection()->set_frame_size_ms(12));
1028
andrew@webrtc.org648af742012-02-08 01:57:29 +00001029 // Test valid frame sizes
niklase@google.com470e71d2011-07-07 08:21:25 +00001030 for (int i = 10; i <= 30; i += 10) {
1031 EXPECT_EQ(apm_->kNoError,
1032 apm_->voice_detection()->set_frame_size_ms(i));
1033 EXPECT_EQ(i, apm_->voice_detection()->frame_size_ms());
1034 }
1035 */
1036
andrew@webrtc.org648af742012-02-08 01:57:29 +00001037 // Turn VAD on/off
niklase@google.com470e71d2011-07-07 08:21:25 +00001038 EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true));
1039 EXPECT_TRUE(apm_->voice_detection()->is_enabled());
1040 EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(false));
1041 EXPECT_FALSE(apm_->voice_detection()->is_enabled());
1042
andrew@webrtc.orged083d42011-09-19 15:28:51 +00001043 // Test that AudioFrame activity is maintained when VAD is disabled.
1044 EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(false));
1045 AudioFrame::VADActivity activity[] = {
1046 AudioFrame::kVadActive,
1047 AudioFrame::kVadPassive,
1048 AudioFrame::kVadUnknown
1049 };
1050 for (size_t i = 0; i < sizeof(activity)/sizeof(*activity); i++) {
andrew@webrtc.org63a50982012-05-02 23:56:37 +00001051 frame_->vad_activity_ = activity[i];
andrew@webrtc.orged083d42011-09-19 15:28:51 +00001052 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
andrew@webrtc.org63a50982012-05-02 23:56:37 +00001053 EXPECT_EQ(activity[i], frame_->vad_activity_);
andrew@webrtc.orged083d42011-09-19 15:28:51 +00001054 }
1055
1056 // Test that AudioFrame activity is set when VAD is enabled.
1057 EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true));
andrew@webrtc.org63a50982012-05-02 23:56:37 +00001058 frame_->vad_activity_ = AudioFrame::kVadUnknown;
andrew@webrtc.orged083d42011-09-19 15:28:51 +00001059 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
andrew@webrtc.org63a50982012-05-02 23:56:37 +00001060 EXPECT_NE(AudioFrame::kVadUnknown, frame_->vad_activity_);
andrew@webrtc.orged083d42011-09-19 15:28:51 +00001061
niklase@google.com470e71d2011-07-07 08:21:25 +00001062 // TODO(bjornv): Add tests for streamed voice; stream_has_voice()
1063}
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001064
andrew@webrtc.orgecac9b72012-05-02 00:04:10 +00001065TEST_F(ApmTest, VerifyDownMixing) {
1066 for (size_t i = 0; i < kSampleRatesSize; i++) {
1067 Init(kSampleRates[i], 2, 2, 1, false);
1068 SetFrameTo(frame_, 1000, 2000);
1069 AudioFrame mono_frame;
andrew@webrtc.org63a50982012-05-02 23:56:37 +00001070 mono_frame.samples_per_channel_ = frame_->samples_per_channel_;
1071 mono_frame.num_channels_ = 1;
andrew@webrtc.orgecac9b72012-05-02 00:04:10 +00001072 SetFrameTo(&mono_frame, 1500);
1073 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1074 EXPECT_TRUE(FrameDataAreEqual(*frame_, mono_frame));
1075 }
1076}
1077
1078TEST_F(ApmTest, AllProcessingDisabledByDefault) {
1079 EXPECT_FALSE(apm_->echo_cancellation()->is_enabled());
1080 EXPECT_FALSE(apm_->echo_control_mobile()->is_enabled());
1081 EXPECT_FALSE(apm_->gain_control()->is_enabled());
1082 EXPECT_FALSE(apm_->high_pass_filter()->is_enabled());
1083 EXPECT_FALSE(apm_->level_estimator()->is_enabled());
1084 EXPECT_FALSE(apm_->noise_suppression()->is_enabled());
1085 EXPECT_FALSE(apm_->voice_detection()->is_enabled());
1086}
1087
1088TEST_F(ApmTest, NoProcessingWhenAllComponentsDisabled) {
1089 for (size_t i = 0; i < kSampleRatesSize; i++) {
1090 Init(kSampleRates[i], 2, 2, 2, false);
1091 SetFrameTo(frame_, 1000, 2000);
1092 AudioFrame frame_copy = *frame_;
1093 for (int j = 0; j < 1000; j++) {
1094 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1095 EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy));
1096 }
1097 }
1098}
1099
andrew@webrtc.org07bf9a02012-05-05 00:32:00 +00001100TEST_F(ApmTest, IdenticalInputChannelsResultInIdenticalOutputChannels) {
1101 EnableAllComponents();
1102
1103 for (size_t i = 0; i < kProcessSampleRatesSize; i++) {
1104 Init(kProcessSampleRates[i], 2, 2, 2, false);
1105 int analog_level = 127;
1106 while (1) {
1107 if (!ReadFrame(far_file_, revframe_)) break;
1108 CopyLeftToRightChannel(revframe_->data_, revframe_->samples_per_channel_);
1109
1110 EXPECT_EQ(apm_->kNoError, apm_->AnalyzeReverseStream(revframe_));
1111
1112 if (!ReadFrame(near_file_, frame_)) break;
1113 CopyLeftToRightChannel(frame_->data_, frame_->samples_per_channel_);
1114 frame_->vad_activity_ = AudioFrame::kVadUnknown;
1115
1116 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0));
1117 EXPECT_EQ(apm_->kNoError,
1118 apm_->echo_cancellation()->set_stream_drift_samples(0));
1119 EXPECT_EQ(apm_->kNoError,
1120 apm_->gain_control()->set_stream_analog_level(analog_level));
1121 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1122 analog_level = apm_->gain_control()->stream_analog_level();
1123
1124 VerifyChannelsAreEqual(frame_->data_, frame_->samples_per_channel_);
1125 }
1126 }
1127}
1128
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001129TEST_F(ApmTest, SplittingFilter) {
1130 // Verify the filter is not active through undistorted audio when:
1131 // 1. No components are enabled...
1132 SetFrameTo(frame_, 1000);
1133 AudioFrame frame_copy = *frame_;
1134 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1135 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1136 EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy));
1137
1138 // 2. Only the level estimator is enabled...
1139 SetFrameTo(frame_, 1000);
1140 frame_copy = *frame_;
1141 EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true));
1142 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1143 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1144 EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy));
1145 EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(false));
1146
1147 // 3. Only VAD is enabled...
1148 SetFrameTo(frame_, 1000);
1149 frame_copy = *frame_;
1150 EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true));
1151 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1152 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1153 EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy));
1154 EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(false));
1155
1156 // 4. Both VAD and the level estimator are enabled...
1157 SetFrameTo(frame_, 1000);
1158 frame_copy = *frame_;
1159 EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true));
1160 EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true));
1161 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1162 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1163 EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy));
1164 EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(false));
1165 EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(false));
1166
1167 // 5. Not using super-wb.
1168 EXPECT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(16000));
andrew@webrtc.org63a50982012-05-02 23:56:37 +00001169 frame_->samples_per_channel_ = 160;
1170 frame_->num_channels_ = 2;
1171 frame_->sample_rate_hz_ = 16000;
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001172 // Enable AEC, which would require the filter in super-wb. We rely on the
1173 // first few frames of data being unaffected by the AEC.
1174 // TODO(andrew): This test, and the one below, rely rather tenuously on the
1175 // behavior of the AEC. Think of something more robust.
1176 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
1177 SetFrameTo(frame_, 1000);
1178 frame_copy = *frame_;
1179 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0));
1180 EXPECT_EQ(apm_->kNoError,
1181 apm_->echo_cancellation()->set_stream_drift_samples(0));
1182 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1183 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0));
1184 EXPECT_EQ(apm_->kNoError,
1185 apm_->echo_cancellation()->set_stream_drift_samples(0));
1186 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1187 EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy));
1188
1189 // Check the test is valid. We should have distortion from the filter
1190 // when AEC is enabled (which won't affect the audio).
1191 EXPECT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(32000));
andrew@webrtc.org63a50982012-05-02 23:56:37 +00001192 frame_->samples_per_channel_ = 320;
1193 frame_->num_channels_ = 2;
1194 frame_->sample_rate_hz_ = 32000;
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001195 SetFrameTo(frame_, 1000);
1196 frame_copy = *frame_;
1197 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0));
1198 EXPECT_EQ(apm_->kNoError,
1199 apm_->echo_cancellation()->set_stream_drift_samples(0));
1200 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1201 EXPECT_FALSE(FrameDataAreEqual(*frame_, frame_copy));
1202}
1203
andrew@webrtc.org7bf26462011-12-03 00:03:31 +00001204// TODO(andrew): expand test to verify output.
1205TEST_F(ApmTest, DebugDump) {
1206 const std::string filename = webrtc::test::OutputPath() + "debug.aec";
1207 EXPECT_EQ(apm_->kNullPointerError, apm_->StartDebugRecording(NULL));
1208
1209#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
1210 // Stopping without having started should be OK.
1211 EXPECT_EQ(apm_->kNoError, apm_->StopDebugRecording());
1212
1213 EXPECT_EQ(apm_->kNoError, apm_->StartDebugRecording(filename.c_str()));
1214 EXPECT_EQ(apm_->kNoError, apm_->AnalyzeReverseStream(revframe_));
1215 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1216 EXPECT_EQ(apm_->kNoError, apm_->StopDebugRecording());
1217
1218 // Verify the file has been written.
andrew@webrtc.orgf5d8c3b2012-01-24 21:35:39 +00001219 FILE* fid = fopen(filename.c_str(), "r");
1220 ASSERT_TRUE(fid != NULL);
1221
andrew@webrtc.org7bf26462011-12-03 00:03:31 +00001222 // Clean it up.
andrew@webrtc.orgf5d8c3b2012-01-24 21:35:39 +00001223 ASSERT_EQ(0, fclose(fid));
andrew@webrtc.org7bf26462011-12-03 00:03:31 +00001224 ASSERT_EQ(0, remove(filename.c_str()));
1225#else
1226 EXPECT_EQ(apm_->kUnsupportedFunctionError,
1227 apm_->StartDebugRecording(filename.c_str()));
1228 EXPECT_EQ(apm_->kUnsupportedFunctionError, apm_->StopDebugRecording());
1229
1230 // Verify the file has NOT been written.
1231 ASSERT_TRUE(fopen(filename.c_str(), "r") == NULL);
1232#endif // WEBRTC_AUDIOPROC_DEBUG_DUMP
1233}
1234
andrew@webrtc.org75f19482012-02-09 17:16:18 +00001235// TODO(andrew): Add a test to process a few frames with different combinations
1236// of enabled components.
1237
andrew@webrtc.orge2ed5ba2012-01-20 19:06:38 +00001238// TODO(andrew): Make this test more robust such that it can be run on multiple
1239// platforms. It currently requires bit-exactness.
andrew@webrtc.org293d22b2012-01-30 22:04:26 +00001240#ifdef WEBRTC_AUDIOPROC_BIT_EXACT
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001241TEST_F(ApmTest, Process) {
1242 GOOGLE_PROTOBUF_VERIFY_VERSION;
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +00001243 webrtc::audioproc::OutputData ref_data;
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001244
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +00001245 if (!write_ref_data) {
1246 ReadMessageLiteFromFile(ref_filename_, &ref_data);
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001247 } else {
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +00001248 // Write the desired tests to the protobuf reference file.
andrew@webrtc.orgecac9b72012-05-02 00:04:10 +00001249 for (size_t i = 0; i < kChannelsSize; i++) {
1250 for (size_t j = 0; j < kChannelsSize; j++) {
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +00001251 // We can't have more output than input channels.
1252 for (size_t k = 0; k <= j; k++) {
andrew@webrtc.orgecac9b72012-05-02 00:04:10 +00001253 for (size_t l = 0; l < kProcessSampleRatesSize; l++) {
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +00001254 webrtc::audioproc::Test* test = ref_data.add_test();
andrew@webrtc.orgecac9b72012-05-02 00:04:10 +00001255 test->set_num_reverse_channels(kChannels[i]);
1256 test->set_num_input_channels(kChannels[j]);
1257 test->set_num_output_channels(kChannels[k]);
1258 test->set_sample_rate(kProcessSampleRates[l]);
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +00001259 }
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001260 }
1261 }
1262 }
1263 }
1264
andrew@webrtc.org07bf9a02012-05-05 00:32:00 +00001265 EnableAllComponents();
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001266
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +00001267 for (int i = 0; i < ref_data.test_size(); i++) {
1268 printf("Running test %d of %d...\n", i + 1, ref_data.test_size());
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001269
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +00001270 webrtc::audioproc::Test* test = ref_data.mutable_test(i);
1271 Init(test->sample_rate(), test->num_reverse_channels(),
1272 test->num_input_channels(), test->num_output_channels(), true);
1273
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001274 int frame_count = 0;
1275 int has_echo_count = 0;
1276 int has_voice_count = 0;
1277 int is_saturated_count = 0;
1278 int analog_level = 127;
1279 int analog_level_average = 0;
1280 int max_output_average = 0;
bjornv@webrtc.org08329f42012-07-12 21:00:43 +00001281 float ns_speech_prob_average = 0.0f;
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001282
1283 while (1) {
andrew@webrtc.org07bf9a02012-05-05 00:32:00 +00001284 if (!ReadFrame(far_file_, revframe_)) break;
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001285 EXPECT_EQ(apm_->kNoError, apm_->AnalyzeReverseStream(revframe_));
1286
andrew@webrtc.org07bf9a02012-05-05 00:32:00 +00001287 if (!ReadFrame(near_file_, frame_)) break;
1288 frame_->vad_activity_ = AudioFrame::kVadUnknown;
1289
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001290 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0));
1291 EXPECT_EQ(apm_->kNoError,
1292 apm_->echo_cancellation()->set_stream_drift_samples(0));
1293 EXPECT_EQ(apm_->kNoError,
1294 apm_->gain_control()->set_stream_analog_level(analog_level));
1295
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001296 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +00001297 // Ensure the frame was downmixed properly.
andrew@webrtc.org63a50982012-05-02 23:56:37 +00001298 EXPECT_EQ(test->num_output_channels(), frame_->num_channels_);
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001299
1300 max_output_average += MaxAudioFrame(*frame_);
1301
1302 if (apm_->echo_cancellation()->stream_has_echo()) {
1303 has_echo_count++;
1304 }
1305
1306 analog_level = apm_->gain_control()->stream_analog_level();
1307 analog_level_average += analog_level;
1308 if (apm_->gain_control()->stream_is_saturated()) {
1309 is_saturated_count++;
1310 }
1311 if (apm_->voice_detection()->stream_has_voice()) {
1312 has_voice_count++;
andrew@webrtc.org63a50982012-05-02 23:56:37 +00001313 EXPECT_EQ(AudioFrame::kVadActive, frame_->vad_activity_);
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001314 } else {
andrew@webrtc.org63a50982012-05-02 23:56:37 +00001315 EXPECT_EQ(AudioFrame::kVadPassive, frame_->vad_activity_);
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001316 }
1317
bjornv@webrtc.org08329f42012-07-12 21:00:43 +00001318 ns_speech_prob_average += apm_->noise_suppression()->speech_probability();
1319
andrew@webrtc.org07bf9a02012-05-05 00:32:00 +00001320 size_t frame_size = frame_->samples_per_channel_ * frame_->num_channels_;
andrew@webrtc.org63a50982012-05-02 23:56:37 +00001321 size_t write_count = fwrite(frame_->data_,
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +00001322 sizeof(int16_t),
1323 frame_size,
1324 out_file_);
1325 ASSERT_EQ(frame_size, write_count);
1326
1327 // Reset in case of downmixing.
andrew@webrtc.org63a50982012-05-02 23:56:37 +00001328 frame_->num_channels_ = test->num_input_channels();
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001329 frame_count++;
1330 }
1331 max_output_average /= frame_count;
1332 analog_level_average /= frame_count;
bjornv@webrtc.org08329f42012-07-12 21:00:43 +00001333 ns_speech_prob_average /= frame_count;
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001334
andrew@webrtc.org293d22b2012-01-30 22:04:26 +00001335#if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001336 EchoCancellation::Metrics echo_metrics;
1337 EXPECT_EQ(apm_->kNoError,
1338 apm_->echo_cancellation()->GetMetrics(&echo_metrics));
1339 int median = 0;
1340 int std = 0;
1341 EXPECT_EQ(apm_->kNoError,
1342 apm_->echo_cancellation()->GetDelayMetrics(&median, &std));
1343
1344 int rms_level = apm_->level_estimator()->RMS();
1345 EXPECT_LE(0, rms_level);
1346 EXPECT_GE(127, rms_level);
1347#endif
1348
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +00001349 if (!write_ref_data) {
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001350 EXPECT_EQ(test->has_echo_count(), has_echo_count);
1351 EXPECT_EQ(test->has_voice_count(), has_voice_count);
1352 EXPECT_EQ(test->is_saturated_count(), is_saturated_count);
1353
1354 EXPECT_EQ(test->analog_level_average(), analog_level_average);
1355 EXPECT_EQ(test->max_output_average(), max_output_average);
1356
andrew@webrtc.org293d22b2012-01-30 22:04:26 +00001357#if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001358 webrtc::audioproc::Test::EchoMetrics reference =
1359 test->echo_metrics();
1360 TestStats(echo_metrics.residual_echo_return_loss,
1361 reference.residual_echo_return_loss());
1362 TestStats(echo_metrics.echo_return_loss,
1363 reference.echo_return_loss());
1364 TestStats(echo_metrics.echo_return_loss_enhancement,
1365 reference.echo_return_loss_enhancement());
1366 TestStats(echo_metrics.a_nlp,
1367 reference.a_nlp());
1368
1369 webrtc::audioproc::Test::DelayMetrics reference_delay =
1370 test->delay_metrics();
andrew@webrtc.org828af1b2011-11-22 22:40:27 +00001371 EXPECT_EQ(reference_delay.median(), median);
1372 EXPECT_EQ(reference_delay.std(), std);
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001373
1374 EXPECT_EQ(test->rms_level(), rms_level);
bjornv@webrtc.org08329f42012-07-12 21:00:43 +00001375
1376 EXPECT_FLOAT_EQ(test->ns_speech_probability_average(),
1377 ns_speech_prob_average);
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001378#endif
1379 } else {
1380 test->set_has_echo_count(has_echo_count);
1381 test->set_has_voice_count(has_voice_count);
1382 test->set_is_saturated_count(is_saturated_count);
1383
1384 test->set_analog_level_average(analog_level_average);
1385 test->set_max_output_average(max_output_average);
1386
andrew@webrtc.org293d22b2012-01-30 22:04:26 +00001387#if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001388 webrtc::audioproc::Test::EchoMetrics* message =
1389 test->mutable_echo_metrics();
1390 WriteStatsMessage(echo_metrics.residual_echo_return_loss,
1391 message->mutable_residual_echo_return_loss());
1392 WriteStatsMessage(echo_metrics.echo_return_loss,
1393 message->mutable_echo_return_loss());
1394 WriteStatsMessage(echo_metrics.echo_return_loss_enhancement,
1395 message->mutable_echo_return_loss_enhancement());
1396 WriteStatsMessage(echo_metrics.a_nlp,
1397 message->mutable_a_nlp());
1398
1399 webrtc::audioproc::Test::DelayMetrics* message_delay =
1400 test->mutable_delay_metrics();
1401 message_delay->set_median(median);
1402 message_delay->set_std(std);
1403
1404 test->set_rms_level(rms_level);
bjornv@webrtc.org08329f42012-07-12 21:00:43 +00001405
1406 EXPECT_LE(0.0f, ns_speech_prob_average);
1407 EXPECT_GE(1.0f, ns_speech_prob_average);
1408 test->set_ns_speech_probability_average(ns_speech_prob_average);
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001409#endif
1410 }
1411
1412 rewind(far_file_);
1413 rewind(near_file_);
1414 }
1415
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +00001416 if (write_ref_data) {
1417 WriteMessageLiteToFile(ref_filename_, ref_data);
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001418 }
1419}
andrew@webrtc.org293d22b2012-01-30 22:04:26 +00001420#endif // WEBRTC_AUDIOPROC_BIT_EXACT
andrew@webrtc.orge2ed5ba2012-01-20 19:06:38 +00001421
niklase@google.com470e71d2011-07-07 08:21:25 +00001422} // namespace
1423
1424int main(int argc, char** argv) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001425 for (int i = 1; i < argc; i++) {
andrew@webrtc.orgdaacee82012-02-07 00:01:04 +00001426 if (strcmp(argv[i], "--write_ref_data") == 0) {
1427 write_ref_data = true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001428 }
1429 }
1430
andrew@webrtc.org28d01402012-10-18 00:42:32 +00001431 // We don't use TestSuite here because it would require the Android platform
1432 // build to depend on Gmock.
1433 webrtc::test::SetExecutablePath(argv[0]);
1434 testing::InitGoogleTest(&argc, argv);
1435 int result = RUN_ALL_TESTS();
andrew@webrtc.org64235092011-08-19 21:22:08 +00001436 // Optional, but removes memory leak noise from Valgrind.
1437 google::protobuf::ShutdownProtobufLibrary();
andrew@webrtc.org28d01402012-10-18 00:42:32 +00001438 return result;
niklase@google.com470e71d2011-07-07 08:21:25 +00001439}