1/* 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 * 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 11#include <cstdio> 12 13#include <gtest/gtest.h> 14 15#include "audio_processing.h" 16#include "audio_processing_unittest.pb.h" 17#include "event_wrapper.h" 18#include "module_common_types.h" 19#include "thread_wrapper.h" 20#include "trace.h" 21#include "signal_processing_library.h" 22 23using webrtc::AudioProcessing; 24using webrtc::AudioFrame; 25using webrtc::GainControl; 26using webrtc::NoiseSuppression; 27using webrtc::EchoCancellation; 28using webrtc::EventWrapper; 29using webrtc::Trace; 30using webrtc::LevelEstimator; 31using webrtc::EchoCancellation; 32using webrtc::EchoControlMobile; 33using webrtc::VoiceDetection; 34 35namespace { 36// When true, this will compare the output data with the results stored to 37// file. This is the typical case. When the file should be updated, it can 38// be set to false with the command-line switch --write_output_data. 39bool global_read_output_data = true; 40 41class ApmEnvironment : public ::testing::Environment { 42 public: 43 virtual void SetUp() { 44 Trace::CreateTrace(); 45 ASSERT_EQ(0, Trace::SetTraceFile("apm_trace.txt")); 46 } 47 48 virtual void TearDown() { 49 Trace::ReturnTrace(); 50 } 51}; 52 53class ApmTest : public ::testing::Test { 54 protected: 55 ApmTest(); 56 virtual void SetUp(); 57 virtual void TearDown(); 58 59 webrtc::AudioProcessing* apm_; 60 webrtc::AudioFrame* frame_; 61 webrtc::AudioFrame* revframe_; 62 FILE* far_file_; 63 FILE* near_file_; 64 bool update_output_data_; 65}; 66 67ApmTest::ApmTest() 68 : apm_(NULL), 69 far_file_(NULL), 70 near_file_(NULL), 71 frame_(NULL), 72 revframe_(NULL) {} 73 74void ApmTest::SetUp() { 75 apm_ = AudioProcessing::Create(0); 76 ASSERT_TRUE(apm_ != NULL); 77 78 frame_ = new AudioFrame(); 79 revframe_ = new AudioFrame(); 80 81 ASSERT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(32000)); 82 ASSERT_EQ(apm_->kNoError, apm_->set_num_channels(2, 2)); 83 ASSERT_EQ(apm_->kNoError, apm_->set_num_reverse_channels(2)); 84 85 frame_->_payloadDataLengthInSamples = 320; 86 frame_->_audioChannel = 2; 87 frame_->_frequencyInHz = 32000; 88 revframe_->_payloadDataLengthInSamples = 320; 89 revframe_->_audioChannel = 2; 90 revframe_->_frequencyInHz = 32000; 91 92 far_file_ = fopen("aec_far.pcm", "rb"); 93 ASSERT_TRUE(far_file_ != NULL) << "Could not open input file aec_far.pcm\n"; 94 near_file_ = fopen("aec_near.pcm", "rb"); 95 ASSERT_TRUE(near_file_ != NULL) << "Could not open input file aec_near.pcm\n"; 96} 97 98void ApmTest::TearDown() { 99 if (frame_) { 100 delete frame_; 101 } 102 frame_ = NULL; 103 104 if (revframe_) { 105 delete revframe_; 106 } 107 revframe_ = NULL; 108 109 if (far_file_) { 110 ASSERT_EQ(0, fclose(far_file_)); 111 } 112 far_file_ = NULL; 113 114 if (near_file_) { 115 ASSERT_EQ(0, fclose(near_file_)); 116 } 117 near_file_ = NULL; 118 119 if (apm_ != NULL) { 120 AudioProcessing::Destroy(apm_); 121 } 122 apm_ = NULL; 123} 124 125void MixStereoToMono(WebRtc_Word16* stereo, 126 WebRtc_Word16* mono, 127 int numSamples) { 128 for (int i = 0; i < numSamples; i++) { 129 int int32 = (static_cast<int>(stereo[i * 2]) + 130 static_cast<int>(stereo[i * 2 + 1])) >> 1; 131 mono[i] = static_cast<WebRtc_Word16>(int32); 132 } 133} 134 135void WriteMessageLiteToFile(const char* filename, 136 const ::google::protobuf::MessageLite& message) { 137 assert(filename != NULL); 138 139 FILE* file = fopen(filename, "wb"); 140 ASSERT_TRUE(file != NULL) << "Could not open " << filename; 141 int size = message.ByteSize(); 142 ASSERT_GT(size, 0); 143 unsigned char* array = new unsigned char[size]; 144 ASSERT_TRUE(message.SerializeToArray(array, size)); 145 146 ASSERT_EQ(1, fwrite(&size, sizeof(int), 1, file)); 147 ASSERT_EQ(size, fwrite(array, sizeof(unsigned char), size, file)); 148 149 delete [] array; 150 fclose(file); 151} 152 153void ReadMessageLiteFromFile(const char* filename, 154 ::google::protobuf::MessageLite* message) { 155 assert(filename != NULL); 156 assert(message != NULL); 157 158 FILE* file = fopen(filename, "rb"); 159 ASSERT_TRUE(file != NULL) << "Could not open " << filename; 160 int size = 0; 161 ASSERT_EQ(1, fread(&size, sizeof(int), 1, file)); 162 ASSERT_GT(size, 0); 163 unsigned char* array = new unsigned char[size]; 164 ASSERT_EQ(size, fread(array, sizeof(unsigned char), size, file)); 165 166 ASSERT_TRUE(message->ParseFromArray(array, size)); 167 168 delete [] array; 169 fclose(file); 170} 171 172struct ThreadData { 173 ThreadData(int thread_num_, AudioProcessing* ap_) 174 : thread_num(thread_num_), 175 error(false), 176 ap(ap_) {} 177 int thread_num; 178 bool error; 179 AudioProcessing* ap; 180}; 181 182// Don't use GTest here; non-thread-safe on Windows (as of 1.5.0). 183bool DeadlockProc(void* thread_object) { 184 ThreadData* thread_data = static_cast<ThreadData*>(thread_object); 185 AudioProcessing* ap = thread_data->ap; 186 int err = ap->kNoError; 187 188 AudioFrame primary_frame; 189 AudioFrame reverse_frame; 190 primary_frame._payloadDataLengthInSamples = 320; 191 primary_frame._audioChannel = 2; 192 primary_frame._frequencyInHz = 32000; 193 reverse_frame._payloadDataLengthInSamples = 320; 194 reverse_frame._audioChannel = 2; 195 reverse_frame._frequencyInHz = 32000; 196 197 ap->echo_cancellation()->Enable(true); 198 ap->gain_control()->Enable(true); 199 ap->high_pass_filter()->Enable(true); 200 ap->level_estimator()->Enable(true); 201 ap->noise_suppression()->Enable(true); 202 ap->voice_detection()->Enable(true); 203 204 if (thread_data->thread_num % 2 == 0) { 205 err = ap->AnalyzeReverseStream(&reverse_frame); 206 if (err != ap->kNoError) { 207 printf("Error in AnalyzeReverseStream(): %d\n", err); 208 thread_data->error = true; 209 return false; 210 } 211 } 212 213 if (thread_data->thread_num % 2 == 1) { 214 ap->set_stream_delay_ms(0); 215 ap->echo_cancellation()->set_stream_drift_samples(0); 216 ap->gain_control()->set_stream_analog_level(0); 217 err = ap->ProcessStream(&primary_frame); 218 if (err == ap->kStreamParameterNotSetError) { 219 printf("Expected kStreamParameterNotSetError in ProcessStream(): %d\n", 220 err); 221 } else if (err != ap->kNoError) { 222 printf("Error in ProcessStream(): %d\n", err); 223 thread_data->error = true; 224 return false; 225 } 226 ap->gain_control()->stream_analog_level(); 227 } 228 229 EventWrapper* event = EventWrapper::Create(); 230 event->Wait(1); 231 delete event; 232 event = NULL; 233 234 return true; 235} 236 237/*TEST_F(ApmTest, Deadlock) { 238 const int num_threads = 16; 239 std::vector<ThreadWrapper*> threads(num_threads); 240 std::vector<ThreadData*> thread_data(num_threads); 241 242 ASSERT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(32000)); 243 ASSERT_EQ(apm_->kNoError, apm_->set_num_channels(2, 2)); 244 ASSERT_EQ(apm_->kNoError, apm_->set_num_reverse_channels(2)); 245 246 for (int i = 0; i < num_threads; i++) { 247 thread_data[i] = new ThreadData(i, apm_); 248 threads[i] = ThreadWrapper::CreateThread(DeadlockProc, 249 thread_data[i], 250 kNormalPriority, 251 0); 252 ASSERT_TRUE(threads[i] != NULL); 253 unsigned int thread_id = 0; 254 threads[i]->Start(thread_id); 255 } 256 257 EventWrapper* event = EventWrapper::Create(); 258 ASSERT_EQ(kEventTimeout, event->Wait(5000)); 259 delete event; 260 event = NULL; 261 262 for (int i = 0; i < num_threads; i++) { 263 // This will return false if the thread has deadlocked. 264 ASSERT_TRUE(threads[i]->Stop()); 265 ASSERT_FALSE(thread_data[i]->error); 266 delete threads[i]; 267 threads[i] = NULL; 268 delete thread_data[i]; 269 thread_data[i] = NULL; 270 } 271}*/ 272 273TEST_F(ApmTest, StreamParameters) { 274 // No errors when the components are disabled. 275 EXPECT_EQ(apm_->kNoError, 276 apm_->ProcessStream(frame_)); 277 278 // Missing agc level 279 EXPECT_EQ(apm_->kNoError, apm_->Initialize()); 280 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true)); 281 EXPECT_EQ(apm_->kStreamParameterNotSetError, 282 apm_->ProcessStream(frame_)); 283 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100)); 284 EXPECT_EQ(apm_->kNoError, 285 apm_->echo_cancellation()->set_stream_drift_samples(0)); 286 EXPECT_EQ(apm_->kStreamParameterNotSetError, 287 apm_->ProcessStream(frame_)); 288 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(false)); 289 290 // Missing delay 291 EXPECT_EQ(apm_->kNoError, apm_->Initialize()); 292 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true)); 293 EXPECT_EQ(apm_->kStreamParameterNotSetError, 294 apm_->ProcessStream(frame_)); 295 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true)); 296 EXPECT_EQ(apm_->kNoError, 297 apm_->echo_cancellation()->set_stream_drift_samples(0)); 298 EXPECT_EQ(apm_->kNoError, 299 apm_->gain_control()->set_stream_analog_level(127)); 300 EXPECT_EQ(apm_->kStreamParameterNotSetError, 301 apm_->ProcessStream(frame_)); 302 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(false)); 303 304 // Missing drift 305 EXPECT_EQ(apm_->kNoError, apm_->Initialize()); 306 EXPECT_EQ(apm_->kNoError, 307 apm_->echo_cancellation()->enable_drift_compensation(true)); 308 EXPECT_EQ(apm_->kStreamParameterNotSetError, 309 apm_->ProcessStream(frame_)); 310 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true)); 311 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100)); 312 EXPECT_EQ(apm_->kNoError, 313 apm_->gain_control()->set_stream_analog_level(127)); 314 EXPECT_EQ(apm_->kStreamParameterNotSetError, 315 apm_->ProcessStream(frame_)); 316 317 // No stream parameters 318 EXPECT_EQ(apm_->kNoError, apm_->Initialize()); 319 EXPECT_EQ(apm_->kNoError, 320 apm_->AnalyzeReverseStream(revframe_)); 321 EXPECT_EQ(apm_->kStreamParameterNotSetError, 322 apm_->ProcessStream(frame_)); 323 324 // All there 325 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true)); 326 EXPECT_EQ(apm_->kNoError, apm_->Initialize()); 327 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100)); 328 EXPECT_EQ(apm_->kNoError, 329 apm_->echo_cancellation()->set_stream_drift_samples(0)); 330 EXPECT_EQ(apm_->kNoError, 331 apm_->gain_control()->set_stream_analog_level(127)); 332 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 333} 334 335TEST_F(ApmTest, Channels) { 336 // Testing number of invalid channels 337 EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_channels(0, 1)); 338 EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_channels(1, 0)); 339 EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_channels(3, 1)); 340 EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_channels(1, 3)); 341 EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_reverse_channels(0)); 342 EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_reverse_channels(3)); 343 // Testing number of valid channels 344 for (int i = 1; i < 3; i++) { 345 for (int j = 1; j < 3; j++) { 346 if (j > i) { 347 EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_channels(i, j)); 348 } else { 349 EXPECT_EQ(apm_->kNoError, apm_->set_num_channels(i, j)); 350 EXPECT_EQ(j, apm_->num_output_channels()); 351 } 352 } 353 EXPECT_EQ(i, apm_->num_input_channels()); 354 EXPECT_EQ(apm_->kNoError, apm_->set_num_reverse_channels(i)); 355 EXPECT_EQ(i, apm_->num_reverse_channels()); 356 } 357} 358 359TEST_F(ApmTest, SampleRates) { 360 // Testing invalid sample rates 361 EXPECT_EQ(apm_->kBadParameterError, apm_->set_sample_rate_hz(10000)); 362 // Testing valid sample rates 363 int fs[] = {8000, 16000, 32000}; 364 for (size_t i = 0; i < sizeof(fs) / sizeof(*fs); i++) { 365 EXPECT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(fs[i])); 366 EXPECT_EQ(fs[i], apm_->sample_rate_hz()); 367 } 368} 369 370TEST_F(ApmTest, Process) { 371 GOOGLE_PROTOBUF_VERIFY_VERSION; 372 audio_processing_unittest::OutputData output_data; 373 374 if (global_read_output_data) { 375 ReadMessageLiteFromFile("output_data.pb", &output_data); 376 377 } else { 378 // We don't have a file; add the required tests to the protobuf. 379 int rev_ch[] = {1, 2}; 380 int ch[] = {1, 2}; 381 int fs[] = {8000, 16000, 32000}; 382 for (size_t i = 0; i < sizeof(rev_ch) / sizeof(*rev_ch); i++) { 383 for (size_t j = 0; j < sizeof(ch) / sizeof(*ch); j++) { 384 for (size_t k = 0; k < sizeof(fs) / sizeof(*fs); k++) { 385 audio_processing_unittest::Test* test = output_data.add_test(); 386 test->set_numreversechannels(rev_ch[i]); 387 test->set_numchannels(ch[j]); 388 test->set_samplerate(fs[k]); 389 } 390 } 391 } 392 } 393 394 EXPECT_EQ(apm_->kNoError, 395 apm_->echo_cancellation()->enable_drift_compensation(true)); 396 EXPECT_EQ(apm_->kNoError, 397 apm_->echo_cancellation()->enable_metrics(true)); 398 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true)); 399 400 EXPECT_EQ(apm_->kNoError, 401 apm_->gain_control()->set_mode(GainControl::kAdaptiveAnalog)); 402 EXPECT_EQ(apm_->kNoError, 403 apm_->gain_control()->set_analog_level_limits(0, 255)); 404 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true)); 405 406 EXPECT_EQ(apm_->kNoError, 407 apm_->high_pass_filter()->Enable(true)); 408 409 //EXPECT_EQ(apm_->kNoError, 410 // apm_->level_estimator()->Enable(true)); 411 412 EXPECT_EQ(apm_->kNoError, 413 apm_->noise_suppression()->Enable(true)); 414 415 EXPECT_EQ(apm_->kNoError, 416 apm_->voice_detection()->Enable(true)); 417 418 for (int i = 0; i < output_data.test_size(); i++) { 419 printf("Running test %d of %d...\n", i + 1, output_data.test_size()); 420 421 audio_processing_unittest::Test* test = output_data.mutable_test(i); 422 const int num_samples = test->samplerate() / 100; 423 revframe_->_payloadDataLengthInSamples = num_samples; 424 revframe_->_audioChannel = test->numreversechannels(); 425 revframe_->_frequencyInHz = test->samplerate(); 426 frame_->_payloadDataLengthInSamples = num_samples; 427 frame_->_audioChannel = test->numchannels(); 428 frame_->_frequencyInHz = test->samplerate(); 429 430 EXPECT_EQ(apm_->kNoError, apm_->Initialize()); 431 ASSERT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(test->samplerate())); 432 ASSERT_EQ(apm_->kNoError, apm_->set_num_channels(frame_->_audioChannel, 433 frame_->_audioChannel)); 434 ASSERT_EQ(apm_->kNoError, 435 apm_->set_num_reverse_channels(revframe_->_audioChannel)); 436 437 438 int has_echo_count = 0; 439 int has_voice_count = 0; 440 int is_saturated_count = 0; 441 442 while (1) { 443 WebRtc_Word16 temp_data[640]; 444 int analog_level = 127; 445 446 // Read far-end frame 447 size_t read_count = fread(temp_data, 448 sizeof(WebRtc_Word16), 449 num_samples * 2, 450 far_file_); 451 if (read_count != static_cast<size_t>(num_samples * 2)) { 452 // Check that the file really ended. 453 ASSERT_NE(0, feof(far_file_)); 454 break; // This is expected. 455 } 456 457 if (revframe_->_audioChannel == 1) { 458 MixStereoToMono(temp_data, revframe_->_payloadData, 459 revframe_->_payloadDataLengthInSamples); 460 } else { 461 memcpy(revframe_->_payloadData, 462 &temp_data[0], 463 sizeof(WebRtc_Word16) * read_count); 464 } 465 466 EXPECT_EQ(apm_->kNoError, 467 apm_->AnalyzeReverseStream(revframe_)); 468 469 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0)); 470 EXPECT_EQ(apm_->kNoError, 471 apm_->echo_cancellation()->set_stream_drift_samples(0)); 472 EXPECT_EQ(apm_->kNoError, 473 apm_->gain_control()->set_stream_analog_level(analog_level)); 474 475 // Read near-end frame 476 read_count = fread(temp_data, 477 sizeof(WebRtc_Word16), 478 num_samples * 2, 479 near_file_); 480 if (read_count != static_cast<size_t>(num_samples * 2)) { 481 // Check that the file really ended. 482 ASSERT_NE(0, feof(near_file_)); 483 break; // This is expected. 484 } 485 486 if (frame_->_audioChannel == 1) { 487 MixStereoToMono(temp_data, frame_->_payloadData, num_samples); 488 } else { 489 memcpy(frame_->_payloadData, 490 &temp_data[0], 491 sizeof(WebRtc_Word16) * read_count); 492 } 493 494 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 495 496 if (apm_->echo_cancellation()->stream_has_echo()) { 497 has_echo_count++; 498 } 499 500 analog_level = apm_->gain_control()->stream_analog_level(); 501 if (apm_->gain_control()->stream_is_saturated()) { 502 is_saturated_count++; 503 } 504 if (apm_->voice_detection()->stream_has_voice()) { 505 has_voice_count++; 506 } 507 } 508 509 //<-- Statistics --> 510 //LevelEstimator::Metrics far_metrics; 511 //LevelEstimator::Metrics near_metrics; 512 //EchoCancellation::Metrics echo_metrics; 513 //LevelEstimator::Metrics far_metrics_ref_; 514 //LevelEstimator::Metrics near_metrics_ref_; 515 //EchoCancellation::Metrics echo_metrics_ref_; 516 //EXPECT_EQ(apm_->kNoError, 517 // apm_->echo_cancellation()->GetMetrics(&echo_metrics)); 518 //EXPECT_EQ(apm_->kNoError, 519 // apm_->level_estimator()->GetMetrics(&near_metrics, 520 521 // TODO(ajm): check echo metrics and output audio. 522 if (global_read_output_data) { 523 EXPECT_EQ(has_echo_count, 524 test->hasechocount()); 525 EXPECT_EQ(has_voice_count, 526 test->hasvoicecount()); 527 EXPECT_EQ(is_saturated_count, 528 test->issaturatedcount()); 529 } else { 530 test->set_hasechocount(has_echo_count); 531 test->set_hasvoicecount(has_voice_count); 532 test->set_issaturatedcount(is_saturated_count); 533 } 534 535 rewind(far_file_); 536 rewind(near_file_); 537 } 538 539 if (!global_read_output_data) { 540 WriteMessageLiteToFile("output_data.pb", output_data); 541 } 542 543 google::protobuf::ShutdownProtobufLibrary(); 544} 545 546TEST_F(ApmTest, EchoCancellation) { 547 EXPECT_EQ(apm_->kNoError, 548 apm_->echo_cancellation()->enable_drift_compensation(true)); 549 EXPECT_TRUE(apm_->echo_cancellation()->is_drift_compensation_enabled()); 550 EXPECT_EQ(apm_->kNoError, 551 apm_->echo_cancellation()->enable_drift_compensation(false)); 552 EXPECT_FALSE(apm_->echo_cancellation()->is_drift_compensation_enabled()); 553 554 EXPECT_EQ(apm_->kBadParameterError, 555 apm_->echo_cancellation()->set_device_sample_rate_hz(4000)); 556 EXPECT_EQ(apm_->kBadParameterError, 557 apm_->echo_cancellation()->set_device_sample_rate_hz(100000)); 558 559 int rate[] = {16000, 44100, 48000}; 560 for (size_t i = 0; i < sizeof(rate)/sizeof(*rate); i++) { 561 EXPECT_EQ(apm_->kNoError, 562 apm_->echo_cancellation()->set_device_sample_rate_hz(rate[i])); 563 EXPECT_EQ(rate[i], 564 apm_->echo_cancellation()->device_sample_rate_hz()); 565 } 566 567 EXPECT_EQ(apm_->kBadParameterError, 568 apm_->echo_cancellation()->set_suppression_level( 569 static_cast<EchoCancellation::SuppressionLevel>(-1))); 570 571 EXPECT_EQ(apm_->kBadParameterError, 572 apm_->echo_cancellation()->set_suppression_level( 573 static_cast<EchoCancellation::SuppressionLevel>(4))); 574 575 EchoCancellation::SuppressionLevel level[] = { 576 EchoCancellation::kLowSuppression, 577 EchoCancellation::kModerateSuppression, 578 EchoCancellation::kHighSuppression, 579 }; 580 for (size_t i = 0; i < sizeof(level)/sizeof(*level); i++) { 581 EXPECT_EQ(apm_->kNoError, 582 apm_->echo_cancellation()->set_suppression_level(level[i])); 583 EXPECT_EQ(level[i], 584 apm_->echo_cancellation()->suppression_level()); 585 } 586 587 EchoCancellation::Metrics metrics; 588 EXPECT_EQ(apm_->kNotEnabledError, 589 apm_->echo_cancellation()->GetMetrics(&metrics)); 590 591 EXPECT_EQ(apm_->kNoError, 592 apm_->echo_cancellation()->enable_metrics(true)); 593 EXPECT_TRUE(apm_->echo_cancellation()->are_metrics_enabled()); 594 EXPECT_EQ(apm_->kNoError, 595 apm_->echo_cancellation()->enable_metrics(false)); 596 EXPECT_FALSE(apm_->echo_cancellation()->are_metrics_enabled()); 597 598 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true)); 599 EXPECT_TRUE(apm_->echo_cancellation()->is_enabled()); 600 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false)); 601 EXPECT_FALSE(apm_->echo_cancellation()->is_enabled()); 602} 603 604TEST_F(ApmTest, EchoControlMobile) { 605 // AECM won't use super-wideband. 606 EXPECT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(32000)); 607 EXPECT_EQ(apm_->kBadSampleRateError, apm_->echo_control_mobile()->Enable(true)); 608 EXPECT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(16000)); 609 // Turn AECM on (and AEC off) 610 EXPECT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(true)); 611 EXPECT_TRUE(apm_->echo_control_mobile()->is_enabled()); 612 613 EXPECT_EQ(apm_->kBadParameterError, 614 apm_->echo_control_mobile()->set_routing_mode( 615 static_cast<EchoControlMobile::RoutingMode>(-1))); 616 EXPECT_EQ(apm_->kBadParameterError, 617 apm_->echo_control_mobile()->set_routing_mode( 618 static_cast<EchoControlMobile::RoutingMode>(5))); 619 620 // Toggle routing modes 621 EchoControlMobile::RoutingMode mode[] = { 622 EchoControlMobile::kQuietEarpieceOrHeadset, 623 EchoControlMobile::kEarpiece, 624 EchoControlMobile::kLoudEarpiece, 625 EchoControlMobile::kSpeakerphone, 626 EchoControlMobile::kLoudSpeakerphone, 627 }; 628 for (size_t i = 0; i < sizeof(mode)/sizeof(*mode); i++) { 629 EXPECT_EQ(apm_->kNoError, 630 apm_->echo_control_mobile()->set_routing_mode(mode[i])); 631 EXPECT_EQ(mode[i], 632 apm_->echo_control_mobile()->routing_mode()); 633 } 634 // Turn comfort noise off/on 635 EXPECT_EQ(apm_->kNoError, 636 apm_->echo_control_mobile()->enable_comfort_noise(false)); 637 EXPECT_FALSE(apm_->echo_control_mobile()->is_comfort_noise_enabled()); 638 EXPECT_EQ(apm_->kNoError, 639 apm_->echo_control_mobile()->enable_comfort_noise(true)); 640 EXPECT_TRUE(apm_->echo_control_mobile()->is_comfort_noise_enabled()); 641 // Turn AECM off 642 EXPECT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(false)); 643 EXPECT_FALSE(apm_->echo_control_mobile()->is_enabled()); 644} 645 646TEST_F(ApmTest, GainControl) { 647 // Testing gain modes 648 EXPECT_EQ(apm_->kBadParameterError, 649 apm_->gain_control()->set_mode(static_cast<GainControl::Mode>(-1))); 650 651 EXPECT_EQ(apm_->kBadParameterError, 652 apm_->gain_control()->set_mode(static_cast<GainControl::Mode>(3))); 653 654 EXPECT_EQ(apm_->kNoError, 655 apm_->gain_control()->set_mode( 656 apm_->gain_control()->mode())); 657 658 GainControl::Mode mode[] = { 659 GainControl::kAdaptiveAnalog, 660 GainControl::kAdaptiveDigital, 661 GainControl::kFixedDigital 662 }; 663 for (size_t i = 0; i < sizeof(mode)/sizeof(*mode); i++) { 664 EXPECT_EQ(apm_->kNoError, 665 apm_->gain_control()->set_mode(mode[i])); 666 EXPECT_EQ(mode[i], apm_->gain_control()->mode()); 667 } 668 // Testing invalid target levels 669 EXPECT_EQ(apm_->kBadParameterError, 670 apm_->gain_control()->set_target_level_dbfs(-3)); 671 EXPECT_EQ(apm_->kBadParameterError, 672 apm_->gain_control()->set_target_level_dbfs(-40)); 673 // Testing valid target levels 674 EXPECT_EQ(apm_->kNoError, 675 apm_->gain_control()->set_target_level_dbfs( 676 apm_->gain_control()->target_level_dbfs())); 677 678 int level_dbfs[] = {0, 6, 31}; 679 for (size_t i = 0; i < sizeof(level_dbfs)/sizeof(*level_dbfs); i++) { 680 EXPECT_EQ(apm_->kNoError, 681 apm_->gain_control()->set_target_level_dbfs(level_dbfs[i])); 682 EXPECT_EQ(level_dbfs[i], apm_->gain_control()->target_level_dbfs()); 683 } 684 685 // Testing invalid compression gains 686 EXPECT_EQ(apm_->kBadParameterError, 687 apm_->gain_control()->set_compression_gain_db(-1)); 688 EXPECT_EQ(apm_->kBadParameterError, 689 apm_->gain_control()->set_compression_gain_db(100)); 690 691 // Testing valid compression gains 692 EXPECT_EQ(apm_->kNoError, 693 apm_->gain_control()->set_compression_gain_db( 694 apm_->gain_control()->compression_gain_db())); 695 696 int gain_db[] = {0, 10, 90}; 697 for (size_t i = 0; i < sizeof(gain_db)/sizeof(*gain_db); i++) { 698 EXPECT_EQ(apm_->kNoError, 699 apm_->gain_control()->set_compression_gain_db(gain_db[i])); 700 EXPECT_EQ(gain_db[i], apm_->gain_control()->compression_gain_db()); 701 } 702 703 // Testing limiter off/on 704 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->enable_limiter(false)); 705 EXPECT_FALSE(apm_->gain_control()->is_limiter_enabled()); 706 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->enable_limiter(true)); 707 EXPECT_TRUE(apm_->gain_control()->is_limiter_enabled()); 708 709 // Testing invalid level limits 710 EXPECT_EQ(apm_->kBadParameterError, 711 apm_->gain_control()->set_analog_level_limits(-1, 512)); 712 EXPECT_EQ(apm_->kBadParameterError, 713 apm_->gain_control()->set_analog_level_limits(100000, 512)); 714 EXPECT_EQ(apm_->kBadParameterError, 715 apm_->gain_control()->set_analog_level_limits(512, -1)); 716 EXPECT_EQ(apm_->kBadParameterError, 717 apm_->gain_control()->set_analog_level_limits(512, 100000)); 718 EXPECT_EQ(apm_->kBadParameterError, 719 apm_->gain_control()->set_analog_level_limits(512, 255)); 720 721 // Testing valid level limits 722 EXPECT_EQ(apm_->kNoError, 723 apm_->gain_control()->set_analog_level_limits( 724 apm_->gain_control()->analog_level_minimum(), 725 apm_->gain_control()->analog_level_maximum())); 726 727 int min_level[] = {0, 255, 1024}; 728 for (size_t i = 0; i < sizeof(min_level)/sizeof(*min_level); i++) { 729 EXPECT_EQ(apm_->kNoError, 730 apm_->gain_control()->set_analog_level_limits(min_level[i], 1024)); 731 EXPECT_EQ(min_level[i], apm_->gain_control()->analog_level_minimum()); 732 } 733 734 int max_level[] = {0, 1024, 65535}; 735 for (size_t i = 0; i < sizeof(min_level)/sizeof(*min_level); i++) { 736 EXPECT_EQ(apm_->kNoError, 737 apm_->gain_control()->set_analog_level_limits(0, max_level[i])); 738 EXPECT_EQ(max_level[i], apm_->gain_control()->analog_level_maximum()); 739 } 740 741 // TODO(ajm): stream_is_saturated() and stream_analog_level() 742 743 // Turn AGC off 744 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(false)); 745 EXPECT_FALSE(apm_->gain_control()->is_enabled()); 746} 747 748TEST_F(ApmTest, NoiseSuppression) { 749 // Tesing invalid suppression levels 750 EXPECT_EQ(apm_->kBadParameterError, 751 apm_->noise_suppression()->set_level( 752 static_cast<NoiseSuppression::Level>(-1))); 753 754 EXPECT_EQ(apm_->kBadParameterError, 755 apm_->noise_suppression()->set_level( 756 static_cast<NoiseSuppression::Level>(5))); 757 758 // Tesing valid suppression levels 759 NoiseSuppression::Level level[] = { 760 NoiseSuppression::kLow, 761 NoiseSuppression::kModerate, 762 NoiseSuppression::kHigh, 763 NoiseSuppression::kVeryHigh 764 }; 765 for (size_t i = 0; i < sizeof(level)/sizeof(*level); i++) { 766 EXPECT_EQ(apm_->kNoError, 767 apm_->noise_suppression()->set_level(level[i])); 768 EXPECT_EQ(level[i], apm_->noise_suppression()->level()); 769 } 770 771 // Turing NS on/off 772 EXPECT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(true)); 773 EXPECT_TRUE(apm_->noise_suppression()->is_enabled()); 774 EXPECT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(false)); 775 EXPECT_FALSE(apm_->noise_suppression()->is_enabled()); 776} 777 778TEST_F(ApmTest, HighPassFilter) { 779 // Turing HP filter on/off 780 EXPECT_EQ(apm_->kNoError, apm_->high_pass_filter()->Enable(true)); 781 EXPECT_TRUE(apm_->high_pass_filter()->is_enabled()); 782 EXPECT_EQ(apm_->kNoError, apm_->high_pass_filter()->Enable(false)); 783 EXPECT_FALSE(apm_->high_pass_filter()->is_enabled()); 784} 785 786TEST_F(ApmTest, LevelEstimator) { 787 // Turing Level estimator on/off 788 EXPECT_EQ(apm_->kUnsupportedComponentError, 789 apm_->level_estimator()->Enable(true)); 790 EXPECT_FALSE(apm_->level_estimator()->is_enabled()); 791 EXPECT_EQ(apm_->kUnsupportedComponentError, 792 apm_->level_estimator()->Enable(false)); 793 EXPECT_FALSE(apm_->level_estimator()->is_enabled()); 794} 795 796TEST_F(ApmTest, VoiceDetection) { 797 // Test external VAD 798 EXPECT_EQ(apm_->kNoError, 799 apm_->voice_detection()->set_stream_has_voice(true)); 800 EXPECT_TRUE(apm_->voice_detection()->stream_has_voice()); 801 EXPECT_EQ(apm_->kNoError, 802 apm_->voice_detection()->set_stream_has_voice(false)); 803 EXPECT_FALSE(apm_->voice_detection()->stream_has_voice()); 804 805 // Tesing invalid likelihoods 806 EXPECT_EQ(apm_->kBadParameterError, 807 apm_->voice_detection()->set_likelihood( 808 static_cast<VoiceDetection::Likelihood>(-1))); 809 810 EXPECT_EQ(apm_->kBadParameterError, 811 apm_->voice_detection()->set_likelihood( 812 static_cast<VoiceDetection::Likelihood>(5))); 813 814 // Tesing valid likelihoods 815 VoiceDetection::Likelihood likelihood[] = { 816 VoiceDetection::kVeryLowLikelihood, 817 VoiceDetection::kLowLikelihood, 818 VoiceDetection::kModerateLikelihood, 819 VoiceDetection::kHighLikelihood 820 }; 821 for (size_t i = 0; i < sizeof(likelihood)/sizeof(*likelihood); i++) { 822 EXPECT_EQ(apm_->kNoError, 823 apm_->voice_detection()->set_likelihood(likelihood[i])); 824 EXPECT_EQ(likelihood[i], apm_->voice_detection()->likelihood()); 825 } 826 827 /* TODO(bjornv): Enable once VAD supports other frame lengths than 10 ms 828 // Tesing invalid frame sizes 829 EXPECT_EQ(apm_->kBadParameterError, 830 apm_->voice_detection()->set_frame_size_ms(12)); 831 832 // Tesing valid frame sizes 833 for (int i = 10; i <= 30; i += 10) { 834 EXPECT_EQ(apm_->kNoError, 835 apm_->voice_detection()->set_frame_size_ms(i)); 836 EXPECT_EQ(i, apm_->voice_detection()->frame_size_ms()); 837 } 838 */ 839 840 // Turing VAD on/off 841 EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true)); 842 EXPECT_TRUE(apm_->voice_detection()->is_enabled()); 843 EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(false)); 844 EXPECT_FALSE(apm_->voice_detection()->is_enabled()); 845 846 // TODO(bjornv): Add tests for streamed voice; stream_has_voice() 847} 848 849// Below are some ideas for tests from VPM. 850 851/*TEST_F(VideoProcessingModuleTest, GetVersionTest) 852{ 853} 854 855TEST_F(VideoProcessingModuleTest, HandleNullBuffer) 856{ 857} 858 859TEST_F(VideoProcessingModuleTest, HandleBadSize) 860{ 861} 862 863TEST_F(VideoProcessingModuleTest, IdenticalResultsAfterReset) 864{ 865} 866*/ 867} // namespace 868 869int main(int argc, char** argv) { 870 ::testing::InitGoogleTest(&argc, argv); 871 ApmEnvironment* env = new ApmEnvironment; // GTest takes ownership. 872 ::testing::AddGlobalTestEnvironment(env); 873 874 for (int i = 1; i < argc; i++) { 875 if (strcmp(argv[i], "--write_output_data") == 0) { 876 global_read_output_data = false; 877 } 878 } 879 880 return RUN_ALL_TESTS(); 881} 882