1 /* 2 * Copyright (c) 2012 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 <math.h> 12 #include <stdio.h> 13 #include <algorithm> 14 #include <limits> 15 #include <queue> 16 17 #include "webrtc/base/arraysize.h" 18 #include "webrtc/base/scoped_ptr.h" 19 #include "webrtc/common_audio/include/audio_util.h" 20 #include "webrtc/common_audio/resampler/include/push_resampler.h" 21 #include "webrtc/common_audio/resampler/push_sinc_resampler.h" 22 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" 23 #include "webrtc/modules/audio_processing/common.h" 24 #include "webrtc/modules/audio_processing/include/audio_processing.h" 25 #include "webrtc/modules/audio_processing/test/protobuf_utils.h" 26 #include "webrtc/modules/audio_processing/test/test_utils.h" 27 #include "webrtc/modules/include/module_common_types.h" 28 #include "webrtc/system_wrappers/include/event_wrapper.h" 29 #include "webrtc/system_wrappers/include/trace.h" 30 #include "webrtc/test/testsupport/fileutils.h" 31 #ifdef WEBRTC_ANDROID_PLATFORM_BUILD 32 #include "gtest/gtest.h" 33 #include "external/webrtc/webrtc/modules/audio_processing/test/unittest.pb.h" 34 #else 35 #include "testing/gtest/include/gtest/gtest.h" 36 #include "webrtc/audio_processing/unittest.pb.h" 37 #endif 38 39 #if !defined(WEBRTC_ANDROID) && !defined(WEBRTC_IOS) 40 #include "webrtc/modules/audio_processing/beamformer/mock_nonlinear_beamformer.h" 41 #endif 42 43 namespace webrtc { 44 namespace { 45 46 // TODO(ekmeyerson): Switch to using StreamConfig and ProcessingConfig where 47 // applicable. 48 49 // TODO(bjornv): This is not feasible until the functionality has been 50 // re-implemented; see comment at the bottom of this file. For now, the user has 51 // to hard code the |write_ref_data| value. 52 // When false, this will compare the output data with the results stored to 53 // file. This is the typical case. When the file should be updated, it can 54 // be set to true with the command-line switch --write_ref_data. 55 bool write_ref_data = false; 56 const google::protobuf::int32 kChannels[] = {1, 2}; 57 const int kSampleRates[] = {8000, 16000, 32000, 48000}; 58 59 #if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE) 60 // AECM doesn't support super-wb. 61 const int kProcessSampleRates[] = {8000, 16000}; 62 #elif defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE) 63 const int kProcessSampleRates[] = {8000, 16000, 32000, 48000}; 64 #endif 65 66 enum StreamDirection { kForward = 0, kReverse }; 67 68 void ConvertToFloat(const int16_t* int_data, ChannelBuffer<float>* cb) { 69 ChannelBuffer<int16_t> cb_int(cb->num_frames(), 70 cb->num_channels()); 71 Deinterleave(int_data, 72 cb->num_frames(), 73 cb->num_channels(), 74 cb_int.channels()); 75 for (size_t i = 0; i < cb->num_channels(); ++i) { 76 S16ToFloat(cb_int.channels()[i], 77 cb->num_frames(), 78 cb->channels()[i]); 79 } 80 } 81 82 void ConvertToFloat(const AudioFrame& frame, ChannelBuffer<float>* cb) { 83 ConvertToFloat(frame.data_, cb); 84 } 85 86 // Number of channels including the keyboard channel. 87 size_t TotalChannelsFromLayout(AudioProcessing::ChannelLayout layout) { 88 switch (layout) { 89 case AudioProcessing::kMono: 90 return 1; 91 case AudioProcessing::kMonoAndKeyboard: 92 case AudioProcessing::kStereo: 93 return 2; 94 case AudioProcessing::kStereoAndKeyboard: 95 return 3; 96 } 97 assert(false); 98 return 0; 99 } 100 101 int TruncateToMultipleOf10(int value) { 102 return (value / 10) * 10; 103 } 104 105 void MixStereoToMono(const float* stereo, float* mono, 106 size_t samples_per_channel) { 107 for (size_t i = 0; i < samples_per_channel; ++i) 108 mono[i] = (stereo[i * 2] + stereo[i * 2 + 1]) / 2; 109 } 110 111 void MixStereoToMono(const int16_t* stereo, int16_t* mono, 112 size_t samples_per_channel) { 113 for (size_t i = 0; i < samples_per_channel; ++i) 114 mono[i] = (stereo[i * 2] + stereo[i * 2 + 1]) >> 1; 115 } 116 117 void CopyLeftToRightChannel(int16_t* stereo, size_t samples_per_channel) { 118 for (size_t i = 0; i < samples_per_channel; i++) { 119 stereo[i * 2 + 1] = stereo[i * 2]; 120 } 121 } 122 123 void VerifyChannelsAreEqual(int16_t* stereo, size_t samples_per_channel) { 124 for (size_t i = 0; i < samples_per_channel; i++) { 125 EXPECT_EQ(stereo[i * 2 + 1], stereo[i * 2]); 126 } 127 } 128 129 void SetFrameTo(AudioFrame* frame, int16_t value) { 130 for (size_t i = 0; i < frame->samples_per_channel_ * frame->num_channels_; 131 ++i) { 132 frame->data_[i] = value; 133 } 134 } 135 136 void SetFrameTo(AudioFrame* frame, int16_t left, int16_t right) { 137 ASSERT_EQ(2u, frame->num_channels_); 138 for (size_t i = 0; i < frame->samples_per_channel_ * 2; i += 2) { 139 frame->data_[i] = left; 140 frame->data_[i + 1] = right; 141 } 142 } 143 144 void ScaleFrame(AudioFrame* frame, float scale) { 145 for (size_t i = 0; i < frame->samples_per_channel_ * frame->num_channels_; 146 ++i) { 147 frame->data_[i] = FloatS16ToS16(frame->data_[i] * scale); 148 } 149 } 150 151 bool FrameDataAreEqual(const AudioFrame& frame1, const AudioFrame& frame2) { 152 if (frame1.samples_per_channel_ != frame2.samples_per_channel_) { 153 return false; 154 } 155 if (frame1.num_channels_ != frame2.num_channels_) { 156 return false; 157 } 158 if (memcmp(frame1.data_, frame2.data_, 159 frame1.samples_per_channel_ * frame1.num_channels_ * 160 sizeof(int16_t))) { 161 return false; 162 } 163 return true; 164 } 165 166 void EnableAllAPComponents(AudioProcessing* ap) { 167 #if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE) 168 EXPECT_NOERR(ap->echo_control_mobile()->Enable(true)); 169 170 EXPECT_NOERR(ap->gain_control()->set_mode(GainControl::kAdaptiveDigital)); 171 EXPECT_NOERR(ap->gain_control()->Enable(true)); 172 #elif defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE) 173 EXPECT_NOERR(ap->echo_cancellation()->enable_drift_compensation(true)); 174 EXPECT_NOERR(ap->echo_cancellation()->enable_metrics(true)); 175 EXPECT_NOERR(ap->echo_cancellation()->enable_delay_logging(true)); 176 EXPECT_NOERR(ap->echo_cancellation()->Enable(true)); 177 178 EXPECT_NOERR(ap->gain_control()->set_mode(GainControl::kAdaptiveAnalog)); 179 EXPECT_NOERR(ap->gain_control()->set_analog_level_limits(0, 255)); 180 EXPECT_NOERR(ap->gain_control()->Enable(true)); 181 #endif 182 183 EXPECT_NOERR(ap->high_pass_filter()->Enable(true)); 184 EXPECT_NOERR(ap->level_estimator()->Enable(true)); 185 EXPECT_NOERR(ap->noise_suppression()->Enable(true)); 186 187 EXPECT_NOERR(ap->voice_detection()->Enable(true)); 188 } 189 190 // These functions are only used by ApmTest.Process. 191 template <class T> 192 T AbsValue(T a) { 193 return a > 0 ? a: -a; 194 } 195 196 int16_t MaxAudioFrame(const AudioFrame& frame) { 197 const size_t length = frame.samples_per_channel_ * frame.num_channels_; 198 int16_t max_data = AbsValue(frame.data_[0]); 199 for (size_t i = 1; i < length; i++) { 200 max_data = std::max(max_data, AbsValue(frame.data_[i])); 201 } 202 203 return max_data; 204 } 205 206 #if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE) 207 void TestStats(const AudioProcessing::Statistic& test, 208 const audioproc::Test::Statistic& reference) { 209 EXPECT_EQ(reference.instant(), test.instant); 210 EXPECT_EQ(reference.average(), test.average); 211 EXPECT_EQ(reference.maximum(), test.maximum); 212 EXPECT_EQ(reference.minimum(), test.minimum); 213 } 214 215 void WriteStatsMessage(const AudioProcessing::Statistic& output, 216 audioproc::Test::Statistic* msg) { 217 msg->set_instant(output.instant); 218 msg->set_average(output.average); 219 msg->set_maximum(output.maximum); 220 msg->set_minimum(output.minimum); 221 } 222 #endif 223 224 void OpenFileAndWriteMessage(const std::string filename, 225 const ::google::protobuf::MessageLite& msg) { 226 #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) 227 FILE* file = fopen(filename.c_str(), "wb"); 228 ASSERT_TRUE(file != NULL); 229 230 int32_t size = msg.ByteSize(); 231 ASSERT_GT(size, 0); 232 rtc::scoped_ptr<uint8_t[]> array(new uint8_t[size]); 233 ASSERT_TRUE(msg.SerializeToArray(array.get(), size)); 234 235 ASSERT_EQ(1u, fwrite(&size, sizeof(size), 1, file)); 236 ASSERT_EQ(static_cast<size_t>(size), 237 fwrite(array.get(), sizeof(array[0]), size, file)); 238 fclose(file); 239 #else 240 std::cout << "Warning: Writing new reference is only allowed on Linux!" 241 << std::endl; 242 #endif 243 } 244 245 std::string ResourceFilePath(std::string name, int sample_rate_hz) { 246 std::ostringstream ss; 247 // Resource files are all stereo. 248 ss << name << sample_rate_hz / 1000 << "_stereo"; 249 return test::ResourcePath(ss.str(), "pcm"); 250 } 251 252 // Temporary filenames unique to this process. Used to be able to run these 253 // tests in parallel as each process needs to be running in isolation they can't 254 // have competing filenames. 255 std::map<std::string, std::string> temp_filenames; 256 257 std::string OutputFilePath(std::string name, 258 int input_rate, 259 int output_rate, 260 int reverse_input_rate, 261 int reverse_output_rate, 262 size_t num_input_channels, 263 size_t num_output_channels, 264 size_t num_reverse_input_channels, 265 size_t num_reverse_output_channels, 266 StreamDirection file_direction) { 267 std::ostringstream ss; 268 ss << name << "_i" << num_input_channels << "_" << input_rate / 1000 << "_ir" 269 << num_reverse_input_channels << "_" << reverse_input_rate / 1000 << "_"; 270 if (num_output_channels == 1) { 271 ss << "mono"; 272 } else if (num_output_channels == 2) { 273 ss << "stereo"; 274 } else { 275 assert(false); 276 } 277 ss << output_rate / 1000; 278 if (num_reverse_output_channels == 1) { 279 ss << "_rmono"; 280 } else if (num_reverse_output_channels == 2) { 281 ss << "_rstereo"; 282 } else { 283 assert(false); 284 } 285 ss << reverse_output_rate / 1000; 286 ss << "_d" << file_direction << "_pcm"; 287 288 std::string filename = ss.str(); 289 if (temp_filenames[filename].empty()) 290 temp_filenames[filename] = test::TempFilename(test::OutputPath(), filename); 291 return temp_filenames[filename]; 292 } 293 294 void ClearTempFiles() { 295 for (auto& kv : temp_filenames) 296 remove(kv.second.c_str()); 297 } 298 299 void OpenFileAndReadMessage(const std::string filename, 300 ::google::protobuf::MessageLite* msg) { 301 FILE* file = fopen(filename.c_str(), "rb"); 302 ASSERT_TRUE(file != NULL); 303 ReadMessageFromFile(file, msg); 304 fclose(file); 305 } 306 307 // Reads a 10 ms chunk of int16 interleaved audio from the given (assumed 308 // stereo) file, converts to deinterleaved float (optionally downmixing) and 309 // returns the result in |cb|. Returns false if the file ended (or on error) and 310 // true otherwise. 311 // 312 // |int_data| and |float_data| are just temporary space that must be 313 // sufficiently large to hold the 10 ms chunk. 314 bool ReadChunk(FILE* file, int16_t* int_data, float* float_data, 315 ChannelBuffer<float>* cb) { 316 // The files always contain stereo audio. 317 size_t frame_size = cb->num_frames() * 2; 318 size_t read_count = fread(int_data, sizeof(int16_t), frame_size, file); 319 if (read_count != frame_size) { 320 // Check that the file really ended. 321 assert(feof(file)); 322 return false; // This is expected. 323 } 324 325 S16ToFloat(int_data, frame_size, float_data); 326 if (cb->num_channels() == 1) { 327 MixStereoToMono(float_data, cb->channels()[0], cb->num_frames()); 328 } else { 329 Deinterleave(float_data, cb->num_frames(), 2, 330 cb->channels()); 331 } 332 333 return true; 334 } 335 336 class ApmTest : public ::testing::Test { 337 protected: 338 ApmTest(); 339 virtual void SetUp(); 340 virtual void TearDown(); 341 342 static void SetUpTestCase() { 343 Trace::CreateTrace(); 344 } 345 346 static void TearDownTestCase() { 347 Trace::ReturnTrace(); 348 ClearTempFiles(); 349 } 350 351 // Used to select between int and float interface tests. 352 enum Format { 353 kIntFormat, 354 kFloatFormat 355 }; 356 357 void Init(int sample_rate_hz, 358 int output_sample_rate_hz, 359 int reverse_sample_rate_hz, 360 size_t num_input_channels, 361 size_t num_output_channels, 362 size_t num_reverse_channels, 363 bool open_output_file); 364 void Init(AudioProcessing* ap); 365 void EnableAllComponents(); 366 bool ReadFrame(FILE* file, AudioFrame* frame); 367 bool ReadFrame(FILE* file, AudioFrame* frame, ChannelBuffer<float>* cb); 368 void ReadFrameWithRewind(FILE* file, AudioFrame* frame); 369 void ReadFrameWithRewind(FILE* file, AudioFrame* frame, 370 ChannelBuffer<float>* cb); 371 void ProcessWithDefaultStreamParameters(AudioFrame* frame); 372 void ProcessDelayVerificationTest(int delay_ms, int system_delay_ms, 373 int delay_min, int delay_max); 374 void TestChangingChannelsInt16Interface( 375 size_t num_channels, 376 AudioProcessing::Error expected_return); 377 void TestChangingForwardChannels(size_t num_in_channels, 378 size_t num_out_channels, 379 AudioProcessing::Error expected_return); 380 void TestChangingReverseChannels(size_t num_rev_channels, 381 AudioProcessing::Error expected_return); 382 void RunQuantizedVolumeDoesNotGetStuckTest(int sample_rate); 383 void RunManualVolumeChangeIsPossibleTest(int sample_rate); 384 void StreamParametersTest(Format format); 385 int ProcessStreamChooser(Format format); 386 int AnalyzeReverseStreamChooser(Format format); 387 void ProcessDebugDump(const std::string& in_filename, 388 const std::string& out_filename, 389 Format format); 390 void VerifyDebugDumpTest(Format format); 391 392 const std::string output_path_; 393 const std::string ref_path_; 394 const std::string ref_filename_; 395 rtc::scoped_ptr<AudioProcessing> apm_; 396 AudioFrame* frame_; 397 AudioFrame* revframe_; 398 rtc::scoped_ptr<ChannelBuffer<float> > float_cb_; 399 rtc::scoped_ptr<ChannelBuffer<float> > revfloat_cb_; 400 int output_sample_rate_hz_; 401 size_t num_output_channels_; 402 FILE* far_file_; 403 FILE* near_file_; 404 FILE* out_file_; 405 }; 406 407 ApmTest::ApmTest() 408 : output_path_(test::OutputPath()), 409 ref_path_(test::ProjectRootPath() + "data/audio_processing/"), 410 #if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE) 411 ref_filename_(ref_path_ + "output_data_fixed.pb"), 412 #elif defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE) 413 #if defined(WEBRTC_MAC) 414 // A different file for Mac is needed because on this platform the AEC 415 // constant |kFixedDelayMs| value is 20 and not 50 as it is on the rest. 416 ref_filename_(ref_path_ + "output_data_mac.pb"), 417 #else 418 ref_filename_(ref_path_ + "output_data_float.pb"), 419 #endif 420 #endif 421 frame_(NULL), 422 revframe_(NULL), 423 output_sample_rate_hz_(0), 424 num_output_channels_(0), 425 far_file_(NULL), 426 near_file_(NULL), 427 out_file_(NULL) { 428 Config config; 429 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); 430 apm_.reset(AudioProcessing::Create(config)); 431 } 432 433 void ApmTest::SetUp() { 434 ASSERT_TRUE(apm_.get() != NULL); 435 436 frame_ = new AudioFrame(); 437 revframe_ = new AudioFrame(); 438 439 #if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE) 440 Init(16000, 16000, 16000, 2, 2, 2, false); 441 #else 442 Init(32000, 32000, 32000, 2, 2, 2, false); 443 #endif 444 } 445 446 void ApmTest::TearDown() { 447 if (frame_) { 448 delete frame_; 449 } 450 frame_ = NULL; 451 452 if (revframe_) { 453 delete revframe_; 454 } 455 revframe_ = NULL; 456 457 if (far_file_) { 458 ASSERT_EQ(0, fclose(far_file_)); 459 } 460 far_file_ = NULL; 461 462 if (near_file_) { 463 ASSERT_EQ(0, fclose(near_file_)); 464 } 465 near_file_ = NULL; 466 467 if (out_file_) { 468 ASSERT_EQ(0, fclose(out_file_)); 469 } 470 out_file_ = NULL; 471 } 472 473 void ApmTest::Init(AudioProcessing* ap) { 474 ASSERT_EQ(kNoErr, 475 ap->Initialize( 476 {{{frame_->sample_rate_hz_, frame_->num_channels_}, 477 {output_sample_rate_hz_, num_output_channels_}, 478 {revframe_->sample_rate_hz_, revframe_->num_channels_}, 479 {revframe_->sample_rate_hz_, revframe_->num_channels_}}})); 480 } 481 482 void ApmTest::Init(int sample_rate_hz, 483 int output_sample_rate_hz, 484 int reverse_sample_rate_hz, 485 size_t num_input_channels, 486 size_t num_output_channels, 487 size_t num_reverse_channels, 488 bool open_output_file) { 489 SetContainerFormat(sample_rate_hz, num_input_channels, frame_, &float_cb_); 490 output_sample_rate_hz_ = output_sample_rate_hz; 491 num_output_channels_ = num_output_channels; 492 493 SetContainerFormat(reverse_sample_rate_hz, num_reverse_channels, revframe_, 494 &revfloat_cb_); 495 Init(apm_.get()); 496 497 if (far_file_) { 498 ASSERT_EQ(0, fclose(far_file_)); 499 } 500 std::string filename = ResourceFilePath("far", sample_rate_hz); 501 far_file_ = fopen(filename.c_str(), "rb"); 502 ASSERT_TRUE(far_file_ != NULL) << "Could not open file " << 503 filename << "\n"; 504 505 if (near_file_) { 506 ASSERT_EQ(0, fclose(near_file_)); 507 } 508 filename = ResourceFilePath("near", sample_rate_hz); 509 near_file_ = fopen(filename.c_str(), "rb"); 510 ASSERT_TRUE(near_file_ != NULL) << "Could not open file " << 511 filename << "\n"; 512 513 if (open_output_file) { 514 if (out_file_) { 515 ASSERT_EQ(0, fclose(out_file_)); 516 } 517 filename = OutputFilePath( 518 "out", sample_rate_hz, output_sample_rate_hz, reverse_sample_rate_hz, 519 reverse_sample_rate_hz, num_input_channels, num_output_channels, 520 num_reverse_channels, num_reverse_channels, kForward); 521 out_file_ = fopen(filename.c_str(), "wb"); 522 ASSERT_TRUE(out_file_ != NULL) << "Could not open file " << 523 filename << "\n"; 524 } 525 } 526 527 void ApmTest::EnableAllComponents() { 528 EnableAllAPComponents(apm_.get()); 529 } 530 531 bool ApmTest::ReadFrame(FILE* file, AudioFrame* frame, 532 ChannelBuffer<float>* cb) { 533 // The files always contain stereo audio. 534 size_t frame_size = frame->samples_per_channel_ * 2; 535 size_t read_count = fread(frame->data_, 536 sizeof(int16_t), 537 frame_size, 538 file); 539 if (read_count != frame_size) { 540 // Check that the file really ended. 541 EXPECT_NE(0, feof(file)); 542 return false; // This is expected. 543 } 544 545 if (frame->num_channels_ == 1) { 546 MixStereoToMono(frame->data_, frame->data_, 547 frame->samples_per_channel_); 548 } 549 550 if (cb) { 551 ConvertToFloat(*frame, cb); 552 } 553 return true; 554 } 555 556 bool ApmTest::ReadFrame(FILE* file, AudioFrame* frame) { 557 return ReadFrame(file, frame, NULL); 558 } 559 560 // If the end of the file has been reached, rewind it and attempt to read the 561 // frame again. 562 void ApmTest::ReadFrameWithRewind(FILE* file, AudioFrame* frame, 563 ChannelBuffer<float>* cb) { 564 if (!ReadFrame(near_file_, frame_, cb)) { 565 rewind(near_file_); 566 ASSERT_TRUE(ReadFrame(near_file_, frame_, cb)); 567 } 568 } 569 570 void ApmTest::ReadFrameWithRewind(FILE* file, AudioFrame* frame) { 571 ReadFrameWithRewind(file, frame, NULL); 572 } 573 574 void ApmTest::ProcessWithDefaultStreamParameters(AudioFrame* frame) { 575 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0)); 576 apm_->echo_cancellation()->set_stream_drift_samples(0); 577 EXPECT_EQ(apm_->kNoError, 578 apm_->gain_control()->set_stream_analog_level(127)); 579 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame)); 580 } 581 582 int ApmTest::ProcessStreamChooser(Format format) { 583 if (format == kIntFormat) { 584 return apm_->ProcessStream(frame_); 585 } 586 return apm_->ProcessStream(float_cb_->channels(), 587 frame_->samples_per_channel_, 588 frame_->sample_rate_hz_, 589 LayoutFromChannels(frame_->num_channels_), 590 output_sample_rate_hz_, 591 LayoutFromChannels(num_output_channels_), 592 float_cb_->channels()); 593 } 594 595 int ApmTest::AnalyzeReverseStreamChooser(Format format) { 596 if (format == kIntFormat) { 597 return apm_->AnalyzeReverseStream(revframe_); 598 } 599 return apm_->AnalyzeReverseStream( 600 revfloat_cb_->channels(), 601 revframe_->samples_per_channel_, 602 revframe_->sample_rate_hz_, 603 LayoutFromChannels(revframe_->num_channels_)); 604 } 605 606 void ApmTest::ProcessDelayVerificationTest(int delay_ms, int system_delay_ms, 607 int delay_min, int delay_max) { 608 // The |revframe_| and |frame_| should include the proper frame information, 609 // hence can be used for extracting information. 610 AudioFrame tmp_frame; 611 std::queue<AudioFrame*> frame_queue; 612 bool causal = true; 613 614 tmp_frame.CopyFrom(*revframe_); 615 SetFrameTo(&tmp_frame, 0); 616 617 EXPECT_EQ(apm_->kNoError, apm_->Initialize()); 618 // Initialize the |frame_queue| with empty frames. 619 int frame_delay = delay_ms / 10; 620 while (frame_delay < 0) { 621 AudioFrame* frame = new AudioFrame(); 622 frame->CopyFrom(tmp_frame); 623 frame_queue.push(frame); 624 frame_delay++; 625 causal = false; 626 } 627 while (frame_delay > 0) { 628 AudioFrame* frame = new AudioFrame(); 629 frame->CopyFrom(tmp_frame); 630 frame_queue.push(frame); 631 frame_delay--; 632 } 633 // Run for 4.5 seconds, skipping statistics from the first 2.5 seconds. We 634 // need enough frames with audio to have reliable estimates, but as few as 635 // possible to keep processing time down. 4.5 seconds seemed to be a good 636 // compromise for this recording. 637 for (int frame_count = 0; frame_count < 450; ++frame_count) { 638 AudioFrame* frame = new AudioFrame(); 639 frame->CopyFrom(tmp_frame); 640 // Use the near end recording, since that has more speech in it. 641 ASSERT_TRUE(ReadFrame(near_file_, frame)); 642 frame_queue.push(frame); 643 AudioFrame* reverse_frame = frame; 644 AudioFrame* process_frame = frame_queue.front(); 645 if (!causal) { 646 reverse_frame = frame_queue.front(); 647 // When we call ProcessStream() the frame is modified, so we can't use the 648 // pointer directly when things are non-causal. Use an intermediate frame 649 // and copy the data. 650 process_frame = &tmp_frame; 651 process_frame->CopyFrom(*frame); 652 } 653 EXPECT_EQ(apm_->kNoError, apm_->AnalyzeReverseStream(reverse_frame)); 654 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(system_delay_ms)); 655 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(process_frame)); 656 frame = frame_queue.front(); 657 frame_queue.pop(); 658 delete frame; 659 660 if (frame_count == 250) { 661 int median; 662 int std; 663 float poor_fraction; 664 // Discard the first delay metrics to avoid convergence effects. 665 EXPECT_EQ(apm_->kNoError, 666 apm_->echo_cancellation()->GetDelayMetrics(&median, &std, 667 &poor_fraction)); 668 } 669 } 670 671 rewind(near_file_); 672 while (!frame_queue.empty()) { 673 AudioFrame* frame = frame_queue.front(); 674 frame_queue.pop(); 675 delete frame; 676 } 677 // Calculate expected delay estimate and acceptable regions. Further, 678 // limit them w.r.t. AEC delay estimation support. 679 const size_t samples_per_ms = 680 std::min(static_cast<size_t>(16), frame_->samples_per_channel_ / 10); 681 int expected_median = std::min(std::max(delay_ms - system_delay_ms, 682 delay_min), delay_max); 683 int expected_median_high = std::min( 684 std::max(expected_median + static_cast<int>(96 / samples_per_ms), 685 delay_min), 686 delay_max); 687 int expected_median_low = std::min( 688 std::max(expected_median - static_cast<int>(96 / samples_per_ms), 689 delay_min), 690 delay_max); 691 // Verify delay metrics. 692 int median; 693 int std; 694 float poor_fraction; 695 EXPECT_EQ(apm_->kNoError, 696 apm_->echo_cancellation()->GetDelayMetrics(&median, &std, 697 &poor_fraction)); 698 EXPECT_GE(expected_median_high, median); 699 EXPECT_LE(expected_median_low, median); 700 } 701 702 void ApmTest::StreamParametersTest(Format format) { 703 // No errors when the components are disabled. 704 EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format)); 705 706 // -- Missing AGC level -- 707 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true)); 708 EXPECT_EQ(apm_->kStreamParameterNotSetError, 709 ProcessStreamChooser(format)); 710 711 // Resets after successful ProcessStream(). 712 EXPECT_EQ(apm_->kNoError, 713 apm_->gain_control()->set_stream_analog_level(127)); 714 EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format)); 715 EXPECT_EQ(apm_->kStreamParameterNotSetError, 716 ProcessStreamChooser(format)); 717 718 // Other stream parameters set correctly. 719 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true)); 720 EXPECT_EQ(apm_->kNoError, 721 apm_->echo_cancellation()->enable_drift_compensation(true)); 722 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100)); 723 apm_->echo_cancellation()->set_stream_drift_samples(0); 724 EXPECT_EQ(apm_->kStreamParameterNotSetError, 725 ProcessStreamChooser(format)); 726 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(false)); 727 EXPECT_EQ(apm_->kNoError, 728 apm_->echo_cancellation()->enable_drift_compensation(false)); 729 730 // -- Missing delay -- 731 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true)); 732 EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format)); 733 EXPECT_EQ(apm_->kStreamParameterNotSetError, 734 ProcessStreamChooser(format)); 735 736 // Resets after successful ProcessStream(). 737 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100)); 738 EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format)); 739 EXPECT_EQ(apm_->kStreamParameterNotSetError, 740 ProcessStreamChooser(format)); 741 742 // Other stream parameters set correctly. 743 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true)); 744 EXPECT_EQ(apm_->kNoError, 745 apm_->echo_cancellation()->enable_drift_compensation(true)); 746 apm_->echo_cancellation()->set_stream_drift_samples(0); 747 EXPECT_EQ(apm_->kNoError, 748 apm_->gain_control()->set_stream_analog_level(127)); 749 EXPECT_EQ(apm_->kStreamParameterNotSetError, 750 ProcessStreamChooser(format)); 751 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(false)); 752 753 // -- Missing drift -- 754 EXPECT_EQ(apm_->kStreamParameterNotSetError, 755 ProcessStreamChooser(format)); 756 757 // Resets after successful ProcessStream(). 758 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100)); 759 apm_->echo_cancellation()->set_stream_drift_samples(0); 760 EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format)); 761 EXPECT_EQ(apm_->kStreamParameterNotSetError, 762 ProcessStreamChooser(format)); 763 764 // Other stream parameters set correctly. 765 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true)); 766 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100)); 767 EXPECT_EQ(apm_->kNoError, 768 apm_->gain_control()->set_stream_analog_level(127)); 769 EXPECT_EQ(apm_->kStreamParameterNotSetError, 770 ProcessStreamChooser(format)); 771 772 // -- No stream parameters -- 773 EXPECT_EQ(apm_->kNoError, 774 AnalyzeReverseStreamChooser(format)); 775 EXPECT_EQ(apm_->kStreamParameterNotSetError, 776 ProcessStreamChooser(format)); 777 778 // -- All there -- 779 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100)); 780 apm_->echo_cancellation()->set_stream_drift_samples(0); 781 EXPECT_EQ(apm_->kNoError, 782 apm_->gain_control()->set_stream_analog_level(127)); 783 EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format)); 784 } 785 786 TEST_F(ApmTest, StreamParametersInt) { 787 StreamParametersTest(kIntFormat); 788 } 789 790 TEST_F(ApmTest, StreamParametersFloat) { 791 StreamParametersTest(kFloatFormat); 792 } 793 794 TEST_F(ApmTest, DefaultDelayOffsetIsZero) { 795 EXPECT_EQ(0, apm_->delay_offset_ms()); 796 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(50)); 797 EXPECT_EQ(50, apm_->stream_delay_ms()); 798 } 799 800 TEST_F(ApmTest, DelayOffsetWithLimitsIsSetProperly) { 801 // High limit of 500 ms. 802 apm_->set_delay_offset_ms(100); 803 EXPECT_EQ(100, apm_->delay_offset_ms()); 804 EXPECT_EQ(apm_->kBadStreamParameterWarning, apm_->set_stream_delay_ms(450)); 805 EXPECT_EQ(500, apm_->stream_delay_ms()); 806 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100)); 807 EXPECT_EQ(200, apm_->stream_delay_ms()); 808 809 // Low limit of 0 ms. 810 apm_->set_delay_offset_ms(-50); 811 EXPECT_EQ(-50, apm_->delay_offset_ms()); 812 EXPECT_EQ(apm_->kBadStreamParameterWarning, apm_->set_stream_delay_ms(20)); 813 EXPECT_EQ(0, apm_->stream_delay_ms()); 814 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100)); 815 EXPECT_EQ(50, apm_->stream_delay_ms()); 816 } 817 818 void ApmTest::TestChangingChannelsInt16Interface( 819 size_t num_channels, 820 AudioProcessing::Error expected_return) { 821 frame_->num_channels_ = num_channels; 822 EXPECT_EQ(expected_return, apm_->ProcessStream(frame_)); 823 EXPECT_EQ(expected_return, apm_->AnalyzeReverseStream(frame_)); 824 } 825 826 void ApmTest::TestChangingForwardChannels( 827 size_t num_in_channels, 828 size_t num_out_channels, 829 AudioProcessing::Error expected_return) { 830 const StreamConfig input_stream = {frame_->sample_rate_hz_, num_in_channels}; 831 const StreamConfig output_stream = {output_sample_rate_hz_, num_out_channels}; 832 833 EXPECT_EQ(expected_return, 834 apm_->ProcessStream(float_cb_->channels(), input_stream, 835 output_stream, float_cb_->channels())); 836 } 837 838 void ApmTest::TestChangingReverseChannels( 839 size_t num_rev_channels, 840 AudioProcessing::Error expected_return) { 841 const ProcessingConfig processing_config = { 842 {{frame_->sample_rate_hz_, apm_->num_input_channels()}, 843 {output_sample_rate_hz_, apm_->num_output_channels()}, 844 {frame_->sample_rate_hz_, num_rev_channels}, 845 {frame_->sample_rate_hz_, num_rev_channels}}}; 846 847 EXPECT_EQ( 848 expected_return, 849 apm_->ProcessReverseStream( 850 float_cb_->channels(), processing_config.reverse_input_stream(), 851 processing_config.reverse_output_stream(), float_cb_->channels())); 852 } 853 854 TEST_F(ApmTest, ChannelsInt16Interface) { 855 // Testing number of invalid and valid channels. 856 Init(16000, 16000, 16000, 4, 4, 4, false); 857 858 TestChangingChannelsInt16Interface(0, apm_->kBadNumberChannelsError); 859 860 for (size_t i = 1; i < 4; i++) { 861 TestChangingChannelsInt16Interface(i, kNoErr); 862 EXPECT_EQ(i, apm_->num_input_channels()); 863 // We always force the number of reverse channels used for processing to 1. 864 EXPECT_EQ(1u, apm_->num_reverse_channels()); 865 } 866 } 867 868 TEST_F(ApmTest, Channels) { 869 // Testing number of invalid and valid channels. 870 Init(16000, 16000, 16000, 4, 4, 4, false); 871 872 TestChangingForwardChannels(0, 1, apm_->kBadNumberChannelsError); 873 TestChangingReverseChannels(0, apm_->kBadNumberChannelsError); 874 875 for (size_t i = 1; i < 4; ++i) { 876 for (size_t j = 0; j < 1; ++j) { 877 // Output channels much be one or match input channels. 878 if (j == 1 || i == j) { 879 TestChangingForwardChannels(i, j, kNoErr); 880 TestChangingReverseChannels(i, kNoErr); 881 882 EXPECT_EQ(i, apm_->num_input_channels()); 883 EXPECT_EQ(j, apm_->num_output_channels()); 884 // The number of reverse channels used for processing to is always 1. 885 EXPECT_EQ(1u, apm_->num_reverse_channels()); 886 } else { 887 TestChangingForwardChannels(i, j, 888 AudioProcessing::kBadNumberChannelsError); 889 } 890 } 891 } 892 } 893 894 TEST_F(ApmTest, SampleRatesInt) { 895 // Testing invalid sample rates 896 SetContainerFormat(10000, 2, frame_, &float_cb_); 897 EXPECT_EQ(apm_->kBadSampleRateError, ProcessStreamChooser(kIntFormat)); 898 // Testing valid sample rates 899 int fs[] = {8000, 16000, 32000, 48000}; 900 for (size_t i = 0; i < arraysize(fs); i++) { 901 SetContainerFormat(fs[i], 2, frame_, &float_cb_); 902 EXPECT_NOERR(ProcessStreamChooser(kIntFormat)); 903 } 904 } 905 906 TEST_F(ApmTest, EchoCancellation) { 907 EXPECT_EQ(apm_->kNoError, 908 apm_->echo_cancellation()->enable_drift_compensation(true)); 909 EXPECT_TRUE(apm_->echo_cancellation()->is_drift_compensation_enabled()); 910 EXPECT_EQ(apm_->kNoError, 911 apm_->echo_cancellation()->enable_drift_compensation(false)); 912 EXPECT_FALSE(apm_->echo_cancellation()->is_drift_compensation_enabled()); 913 914 EchoCancellation::SuppressionLevel level[] = { 915 EchoCancellation::kLowSuppression, 916 EchoCancellation::kModerateSuppression, 917 EchoCancellation::kHighSuppression, 918 }; 919 for (size_t i = 0; i < arraysize(level); i++) { 920 EXPECT_EQ(apm_->kNoError, 921 apm_->echo_cancellation()->set_suppression_level(level[i])); 922 EXPECT_EQ(level[i], 923 apm_->echo_cancellation()->suppression_level()); 924 } 925 926 EchoCancellation::Metrics metrics; 927 EXPECT_EQ(apm_->kNotEnabledError, 928 apm_->echo_cancellation()->GetMetrics(&metrics)); 929 930 EXPECT_EQ(apm_->kNoError, 931 apm_->echo_cancellation()->enable_metrics(true)); 932 EXPECT_TRUE(apm_->echo_cancellation()->are_metrics_enabled()); 933 EXPECT_EQ(apm_->kNoError, 934 apm_->echo_cancellation()->enable_metrics(false)); 935 EXPECT_FALSE(apm_->echo_cancellation()->are_metrics_enabled()); 936 937 int median = 0; 938 int std = 0; 939 float poor_fraction = 0; 940 EXPECT_EQ(apm_->kNotEnabledError, 941 apm_->echo_cancellation()->GetDelayMetrics(&median, &std, 942 &poor_fraction)); 943 944 EXPECT_EQ(apm_->kNoError, 945 apm_->echo_cancellation()->enable_delay_logging(true)); 946 EXPECT_TRUE(apm_->echo_cancellation()->is_delay_logging_enabled()); 947 EXPECT_EQ(apm_->kNoError, 948 apm_->echo_cancellation()->enable_delay_logging(false)); 949 EXPECT_FALSE(apm_->echo_cancellation()->is_delay_logging_enabled()); 950 951 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true)); 952 EXPECT_TRUE(apm_->echo_cancellation()->is_enabled()); 953 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false)); 954 EXPECT_FALSE(apm_->echo_cancellation()->is_enabled()); 955 956 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true)); 957 EXPECT_TRUE(apm_->echo_cancellation()->is_enabled()); 958 EXPECT_TRUE(apm_->echo_cancellation()->aec_core() != NULL); 959 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false)); 960 EXPECT_FALSE(apm_->echo_cancellation()->is_enabled()); 961 EXPECT_FALSE(apm_->echo_cancellation()->aec_core() != NULL); 962 } 963 964 TEST_F(ApmTest, DISABLED_EchoCancellationReportsCorrectDelays) { 965 // TODO(bjornv): Fix this test to work with DA-AEC. 966 // Enable AEC only. 967 EXPECT_EQ(apm_->kNoError, 968 apm_->echo_cancellation()->enable_drift_compensation(false)); 969 EXPECT_EQ(apm_->kNoError, 970 apm_->echo_cancellation()->enable_metrics(false)); 971 EXPECT_EQ(apm_->kNoError, 972 apm_->echo_cancellation()->enable_delay_logging(true)); 973 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true)); 974 Config config; 975 config.Set<DelayAgnostic>(new DelayAgnostic(false)); 976 apm_->SetExtraOptions(config); 977 978 // Internally in the AEC the amount of lookahead the delay estimation can 979 // handle is 15 blocks and the maximum delay is set to 60 blocks. 980 const int kLookaheadBlocks = 15; 981 const int kMaxDelayBlocks = 60; 982 // The AEC has a startup time before it actually starts to process. This 983 // procedure can flush the internal far-end buffer, which of course affects 984 // the delay estimation. Therefore, we set a system_delay high enough to 985 // avoid that. The smallest system_delay you can report without flushing the 986 // buffer is 66 ms in 8 kHz. 987 // 988 // It is known that for 16 kHz (and 32 kHz) sampling frequency there is an 989 // additional stuffing of 8 ms on the fly, but it seems to have no impact on 990 // delay estimation. This should be noted though. In case of test failure, 991 // this could be the cause. 992 const int kSystemDelayMs = 66; 993 // Test a couple of corner cases and verify that the estimated delay is 994 // within a valid region (set to +-1.5 blocks). Note that these cases are 995 // sampling frequency dependent. 996 for (size_t i = 0; i < arraysize(kProcessSampleRates); i++) { 997 Init(kProcessSampleRates[i], 998 kProcessSampleRates[i], 999 kProcessSampleRates[i], 1000 2, 1001 2, 1002 2, 1003 false); 1004 // Sampling frequency dependent variables. 1005 const int num_ms_per_block = 1006 std::max(4, static_cast<int>(640 / frame_->samples_per_channel_)); 1007 const int delay_min_ms = -kLookaheadBlocks * num_ms_per_block; 1008 const int delay_max_ms = (kMaxDelayBlocks - 1) * num_ms_per_block; 1009 1010 // 1) Verify correct delay estimate at lookahead boundary. 1011 int delay_ms = TruncateToMultipleOf10(kSystemDelayMs + delay_min_ms); 1012 ProcessDelayVerificationTest(delay_ms, kSystemDelayMs, delay_min_ms, 1013 delay_max_ms); 1014 // 2) A delay less than maximum lookahead should give an delay estimate at 1015 // the boundary (= -kLookaheadBlocks * num_ms_per_block). 1016 delay_ms -= 20; 1017 ProcessDelayVerificationTest(delay_ms, kSystemDelayMs, delay_min_ms, 1018 delay_max_ms); 1019 // 3) Three values around zero delay. Note that we need to compensate for 1020 // the fake system_delay. 1021 delay_ms = TruncateToMultipleOf10(kSystemDelayMs - 10); 1022 ProcessDelayVerificationTest(delay_ms, kSystemDelayMs, delay_min_ms, 1023 delay_max_ms); 1024 delay_ms = TruncateToMultipleOf10(kSystemDelayMs); 1025 ProcessDelayVerificationTest(delay_ms, kSystemDelayMs, delay_min_ms, 1026 delay_max_ms); 1027 delay_ms = TruncateToMultipleOf10(kSystemDelayMs + 10); 1028 ProcessDelayVerificationTest(delay_ms, kSystemDelayMs, delay_min_ms, 1029 delay_max_ms); 1030 // 4) Verify correct delay estimate at maximum delay boundary. 1031 delay_ms = TruncateToMultipleOf10(kSystemDelayMs + delay_max_ms); 1032 ProcessDelayVerificationTest(delay_ms, kSystemDelayMs, delay_min_ms, 1033 delay_max_ms); 1034 // 5) A delay above the maximum delay should give an estimate at the 1035 // boundary (= (kMaxDelayBlocks - 1) * num_ms_per_block). 1036 delay_ms += 20; 1037 ProcessDelayVerificationTest(delay_ms, kSystemDelayMs, delay_min_ms, 1038 delay_max_ms); 1039 } 1040 } 1041 1042 TEST_F(ApmTest, EchoControlMobile) { 1043 // AECM won't use super-wideband. 1044 SetFrameSampleRate(frame_, 32000); 1045 EXPECT_NOERR(apm_->ProcessStream(frame_)); 1046 EXPECT_EQ(apm_->kBadSampleRateError, 1047 apm_->echo_control_mobile()->Enable(true)); 1048 SetFrameSampleRate(frame_, 16000); 1049 EXPECT_NOERR(apm_->ProcessStream(frame_)); 1050 EXPECT_EQ(apm_->kNoError, 1051 apm_->echo_control_mobile()->Enable(true)); 1052 SetFrameSampleRate(frame_, 32000); 1053 EXPECT_EQ(apm_->kUnsupportedComponentError, apm_->ProcessStream(frame_)); 1054 1055 // Turn AECM on (and AEC off) 1056 Init(16000, 16000, 16000, 2, 2, 2, false); 1057 EXPECT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(true)); 1058 EXPECT_TRUE(apm_->echo_control_mobile()->is_enabled()); 1059 1060 // Toggle routing modes 1061 EchoControlMobile::RoutingMode mode[] = { 1062 EchoControlMobile::kQuietEarpieceOrHeadset, 1063 EchoControlMobile::kEarpiece, 1064 EchoControlMobile::kLoudEarpiece, 1065 EchoControlMobile::kSpeakerphone, 1066 EchoControlMobile::kLoudSpeakerphone, 1067 }; 1068 for (size_t i = 0; i < arraysize(mode); i++) { 1069 EXPECT_EQ(apm_->kNoError, 1070 apm_->echo_control_mobile()->set_routing_mode(mode[i])); 1071 EXPECT_EQ(mode[i], 1072 apm_->echo_control_mobile()->routing_mode()); 1073 } 1074 // Turn comfort noise off/on 1075 EXPECT_EQ(apm_->kNoError, 1076 apm_->echo_control_mobile()->enable_comfort_noise(false)); 1077 EXPECT_FALSE(apm_->echo_control_mobile()->is_comfort_noise_enabled()); 1078 EXPECT_EQ(apm_->kNoError, 1079 apm_->echo_control_mobile()->enable_comfort_noise(true)); 1080 EXPECT_TRUE(apm_->echo_control_mobile()->is_comfort_noise_enabled()); 1081 // Set and get echo path 1082 const size_t echo_path_size = 1083 apm_->echo_control_mobile()->echo_path_size_bytes(); 1084 rtc::scoped_ptr<char[]> echo_path_in(new char[echo_path_size]); 1085 rtc::scoped_ptr<char[]> echo_path_out(new char[echo_path_size]); 1086 EXPECT_EQ(apm_->kNullPointerError, 1087 apm_->echo_control_mobile()->SetEchoPath(NULL, echo_path_size)); 1088 EXPECT_EQ(apm_->kNullPointerError, 1089 apm_->echo_control_mobile()->GetEchoPath(NULL, echo_path_size)); 1090 EXPECT_EQ(apm_->kBadParameterError, 1091 apm_->echo_control_mobile()->GetEchoPath(echo_path_out.get(), 1)); 1092 EXPECT_EQ(apm_->kNoError, 1093 apm_->echo_control_mobile()->GetEchoPath(echo_path_out.get(), 1094 echo_path_size)); 1095 for (size_t i = 0; i < echo_path_size; i++) { 1096 echo_path_in[i] = echo_path_out[i] + 1; 1097 } 1098 EXPECT_EQ(apm_->kBadParameterError, 1099 apm_->echo_control_mobile()->SetEchoPath(echo_path_in.get(), 1)); 1100 EXPECT_EQ(apm_->kNoError, 1101 apm_->echo_control_mobile()->SetEchoPath(echo_path_in.get(), 1102 echo_path_size)); 1103 EXPECT_EQ(apm_->kNoError, 1104 apm_->echo_control_mobile()->GetEchoPath(echo_path_out.get(), 1105 echo_path_size)); 1106 for (size_t i = 0; i < echo_path_size; i++) { 1107 EXPECT_EQ(echo_path_in[i], echo_path_out[i]); 1108 } 1109 1110 // Process a few frames with NS in the default disabled state. This exercises 1111 // a different codepath than with it enabled. 1112 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0)); 1113 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1114 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0)); 1115 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1116 1117 // Turn AECM off 1118 EXPECT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(false)); 1119 EXPECT_FALSE(apm_->echo_control_mobile()->is_enabled()); 1120 } 1121 1122 TEST_F(ApmTest, GainControl) { 1123 // Testing gain modes 1124 EXPECT_EQ(apm_->kNoError, 1125 apm_->gain_control()->set_mode( 1126 apm_->gain_control()->mode())); 1127 1128 GainControl::Mode mode[] = { 1129 GainControl::kAdaptiveAnalog, 1130 GainControl::kAdaptiveDigital, 1131 GainControl::kFixedDigital 1132 }; 1133 for (size_t i = 0; i < arraysize(mode); i++) { 1134 EXPECT_EQ(apm_->kNoError, 1135 apm_->gain_control()->set_mode(mode[i])); 1136 EXPECT_EQ(mode[i], apm_->gain_control()->mode()); 1137 } 1138 // Testing invalid target levels 1139 EXPECT_EQ(apm_->kBadParameterError, 1140 apm_->gain_control()->set_target_level_dbfs(-3)); 1141 EXPECT_EQ(apm_->kBadParameterError, 1142 apm_->gain_control()->set_target_level_dbfs(-40)); 1143 // Testing valid target levels 1144 EXPECT_EQ(apm_->kNoError, 1145 apm_->gain_control()->set_target_level_dbfs( 1146 apm_->gain_control()->target_level_dbfs())); 1147 1148 int level_dbfs[] = {0, 6, 31}; 1149 for (size_t i = 0; i < arraysize(level_dbfs); i++) { 1150 EXPECT_EQ(apm_->kNoError, 1151 apm_->gain_control()->set_target_level_dbfs(level_dbfs[i])); 1152 EXPECT_EQ(level_dbfs[i], apm_->gain_control()->target_level_dbfs()); 1153 } 1154 1155 // Testing invalid compression gains 1156 EXPECT_EQ(apm_->kBadParameterError, 1157 apm_->gain_control()->set_compression_gain_db(-1)); 1158 EXPECT_EQ(apm_->kBadParameterError, 1159 apm_->gain_control()->set_compression_gain_db(100)); 1160 1161 // Testing valid compression gains 1162 EXPECT_EQ(apm_->kNoError, 1163 apm_->gain_control()->set_compression_gain_db( 1164 apm_->gain_control()->compression_gain_db())); 1165 1166 int gain_db[] = {0, 10, 90}; 1167 for (size_t i = 0; i < arraysize(gain_db); i++) { 1168 EXPECT_EQ(apm_->kNoError, 1169 apm_->gain_control()->set_compression_gain_db(gain_db[i])); 1170 EXPECT_EQ(gain_db[i], apm_->gain_control()->compression_gain_db()); 1171 } 1172 1173 // Testing limiter off/on 1174 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->enable_limiter(false)); 1175 EXPECT_FALSE(apm_->gain_control()->is_limiter_enabled()); 1176 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->enable_limiter(true)); 1177 EXPECT_TRUE(apm_->gain_control()->is_limiter_enabled()); 1178 1179 // Testing invalid level limits 1180 EXPECT_EQ(apm_->kBadParameterError, 1181 apm_->gain_control()->set_analog_level_limits(-1, 512)); 1182 EXPECT_EQ(apm_->kBadParameterError, 1183 apm_->gain_control()->set_analog_level_limits(100000, 512)); 1184 EXPECT_EQ(apm_->kBadParameterError, 1185 apm_->gain_control()->set_analog_level_limits(512, -1)); 1186 EXPECT_EQ(apm_->kBadParameterError, 1187 apm_->gain_control()->set_analog_level_limits(512, 100000)); 1188 EXPECT_EQ(apm_->kBadParameterError, 1189 apm_->gain_control()->set_analog_level_limits(512, 255)); 1190 1191 // Testing valid level limits 1192 EXPECT_EQ(apm_->kNoError, 1193 apm_->gain_control()->set_analog_level_limits( 1194 apm_->gain_control()->analog_level_minimum(), 1195 apm_->gain_control()->analog_level_maximum())); 1196 1197 int min_level[] = {0, 255, 1024}; 1198 for (size_t i = 0; i < arraysize(min_level); i++) { 1199 EXPECT_EQ(apm_->kNoError, 1200 apm_->gain_control()->set_analog_level_limits(min_level[i], 1024)); 1201 EXPECT_EQ(min_level[i], apm_->gain_control()->analog_level_minimum()); 1202 } 1203 1204 int max_level[] = {0, 1024, 65535}; 1205 for (size_t i = 0; i < arraysize(min_level); i++) { 1206 EXPECT_EQ(apm_->kNoError, 1207 apm_->gain_control()->set_analog_level_limits(0, max_level[i])); 1208 EXPECT_EQ(max_level[i], apm_->gain_control()->analog_level_maximum()); 1209 } 1210 1211 // TODO(ajm): stream_is_saturated() and stream_analog_level() 1212 1213 // Turn AGC off 1214 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(false)); 1215 EXPECT_FALSE(apm_->gain_control()->is_enabled()); 1216 } 1217 1218 void ApmTest::RunQuantizedVolumeDoesNotGetStuckTest(int sample_rate) { 1219 Init(sample_rate, sample_rate, sample_rate, 2, 2, 2, false); 1220 EXPECT_EQ(apm_->kNoError, 1221 apm_->gain_control()->set_mode(GainControl::kAdaptiveAnalog)); 1222 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true)); 1223 1224 int out_analog_level = 0; 1225 for (int i = 0; i < 2000; ++i) { 1226 ReadFrameWithRewind(near_file_, frame_); 1227 // Ensure the audio is at a low level, so the AGC will try to increase it. 1228 ScaleFrame(frame_, 0.25); 1229 1230 // Always pass in the same volume. 1231 EXPECT_EQ(apm_->kNoError, 1232 apm_->gain_control()->set_stream_analog_level(100)); 1233 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1234 out_analog_level = apm_->gain_control()->stream_analog_level(); 1235 } 1236 1237 // Ensure the AGC is still able to reach the maximum. 1238 EXPECT_EQ(255, out_analog_level); 1239 } 1240 1241 // Verifies that despite volume slider quantization, the AGC can continue to 1242 // increase its volume. 1243 TEST_F(ApmTest, QuantizedVolumeDoesNotGetStuck) { 1244 for (size_t i = 0; i < arraysize(kSampleRates); ++i) { 1245 RunQuantizedVolumeDoesNotGetStuckTest(kSampleRates[i]); 1246 } 1247 } 1248 1249 void ApmTest::RunManualVolumeChangeIsPossibleTest(int sample_rate) { 1250 Init(sample_rate, sample_rate, sample_rate, 2, 2, 2, false); 1251 EXPECT_EQ(apm_->kNoError, 1252 apm_->gain_control()->set_mode(GainControl::kAdaptiveAnalog)); 1253 EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true)); 1254 1255 int out_analog_level = 100; 1256 for (int i = 0; i < 1000; ++i) { 1257 ReadFrameWithRewind(near_file_, frame_); 1258 // Ensure the audio is at a low level, so the AGC will try to increase it. 1259 ScaleFrame(frame_, 0.25); 1260 1261 EXPECT_EQ(apm_->kNoError, 1262 apm_->gain_control()->set_stream_analog_level(out_analog_level)); 1263 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1264 out_analog_level = apm_->gain_control()->stream_analog_level(); 1265 } 1266 1267 // Ensure the volume was raised. 1268 EXPECT_GT(out_analog_level, 100); 1269 int highest_level_reached = out_analog_level; 1270 // Simulate a user manual volume change. 1271 out_analog_level = 100; 1272 1273 for (int i = 0; i < 300; ++i) { 1274 ReadFrameWithRewind(near_file_, frame_); 1275 ScaleFrame(frame_, 0.25); 1276 1277 EXPECT_EQ(apm_->kNoError, 1278 apm_->gain_control()->set_stream_analog_level(out_analog_level)); 1279 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1280 out_analog_level = apm_->gain_control()->stream_analog_level(); 1281 // Check that AGC respected the manually adjusted volume. 1282 EXPECT_LT(out_analog_level, highest_level_reached); 1283 } 1284 // Check that the volume was still raised. 1285 EXPECT_GT(out_analog_level, 100); 1286 } 1287 1288 TEST_F(ApmTest, ManualVolumeChangeIsPossible) { 1289 for (size_t i = 0; i < arraysize(kSampleRates); ++i) { 1290 RunManualVolumeChangeIsPossibleTest(kSampleRates[i]); 1291 } 1292 } 1293 1294 #if !defined(WEBRTC_ANDROID) && !defined(WEBRTC_IOS) 1295 TEST_F(ApmTest, AgcOnlyAdaptsWhenTargetSignalIsPresent) { 1296 const int kSampleRateHz = 16000; 1297 const size_t kSamplesPerChannel = 1298 static_cast<size_t>(AudioProcessing::kChunkSizeMs * kSampleRateHz / 1000); 1299 const size_t kNumInputChannels = 2; 1300 const size_t kNumOutputChannels = 1; 1301 const size_t kNumChunks = 700; 1302 const float kScaleFactor = 0.25f; 1303 Config config; 1304 std::vector<webrtc::Point> geometry; 1305 geometry.push_back(webrtc::Point(0.f, 0.f, 0.f)); 1306 geometry.push_back(webrtc::Point(0.05f, 0.f, 0.f)); 1307 config.Set<Beamforming>(new Beamforming(true, geometry)); 1308 testing::NiceMock<MockNonlinearBeamformer>* beamformer = 1309 new testing::NiceMock<MockNonlinearBeamformer>(geometry); 1310 rtc::scoped_ptr<AudioProcessing> apm( 1311 AudioProcessing::Create(config, beamformer)); 1312 EXPECT_EQ(kNoErr, apm->gain_control()->Enable(true)); 1313 ChannelBuffer<float> src_buf(kSamplesPerChannel, kNumInputChannels); 1314 ChannelBuffer<float> dest_buf(kSamplesPerChannel, kNumOutputChannels); 1315 const size_t max_length = kSamplesPerChannel * std::max(kNumInputChannels, 1316 kNumOutputChannels); 1317 rtc::scoped_ptr<int16_t[]> int_data(new int16_t[max_length]); 1318 rtc::scoped_ptr<float[]> float_data(new float[max_length]); 1319 std::string filename = ResourceFilePath("far", kSampleRateHz); 1320 FILE* far_file = fopen(filename.c_str(), "rb"); 1321 ASSERT_TRUE(far_file != NULL) << "Could not open file " << filename << "\n"; 1322 const int kDefaultVolume = apm->gain_control()->stream_analog_level(); 1323 const int kDefaultCompressionGain = 1324 apm->gain_control()->compression_gain_db(); 1325 bool is_target = false; 1326 EXPECT_CALL(*beamformer, is_target_present()) 1327 .WillRepeatedly(testing::ReturnPointee(&is_target)); 1328 for (size_t i = 0; i < kNumChunks; ++i) { 1329 ASSERT_TRUE(ReadChunk(far_file, 1330 int_data.get(), 1331 float_data.get(), 1332 &src_buf)); 1333 for (size_t j = 0; j < kNumInputChannels; ++j) { 1334 for (size_t k = 0; k < kSamplesPerChannel; ++k) { 1335 src_buf.channels()[j][k] *= kScaleFactor; 1336 } 1337 } 1338 EXPECT_EQ(kNoErr, 1339 apm->ProcessStream(src_buf.channels(), 1340 src_buf.num_frames(), 1341 kSampleRateHz, 1342 LayoutFromChannels(src_buf.num_channels()), 1343 kSampleRateHz, 1344 LayoutFromChannels(dest_buf.num_channels()), 1345 dest_buf.channels())); 1346 } 1347 EXPECT_EQ(kDefaultVolume, 1348 apm->gain_control()->stream_analog_level()); 1349 EXPECT_EQ(kDefaultCompressionGain, 1350 apm->gain_control()->compression_gain_db()); 1351 rewind(far_file); 1352 is_target = true; 1353 for (size_t i = 0; i < kNumChunks; ++i) { 1354 ASSERT_TRUE(ReadChunk(far_file, 1355 int_data.get(), 1356 float_data.get(), 1357 &src_buf)); 1358 for (size_t j = 0; j < kNumInputChannels; ++j) { 1359 for (size_t k = 0; k < kSamplesPerChannel; ++k) { 1360 src_buf.channels()[j][k] *= kScaleFactor; 1361 } 1362 } 1363 EXPECT_EQ(kNoErr, 1364 apm->ProcessStream(src_buf.channels(), 1365 src_buf.num_frames(), 1366 kSampleRateHz, 1367 LayoutFromChannels(src_buf.num_channels()), 1368 kSampleRateHz, 1369 LayoutFromChannels(dest_buf.num_channels()), 1370 dest_buf.channels())); 1371 } 1372 EXPECT_LT(kDefaultVolume, 1373 apm->gain_control()->stream_analog_level()); 1374 EXPECT_LT(kDefaultCompressionGain, 1375 apm->gain_control()->compression_gain_db()); 1376 ASSERT_EQ(0, fclose(far_file)); 1377 } 1378 #endif 1379 1380 TEST_F(ApmTest, NoiseSuppression) { 1381 // Test valid suppression levels. 1382 NoiseSuppression::Level level[] = { 1383 NoiseSuppression::kLow, 1384 NoiseSuppression::kModerate, 1385 NoiseSuppression::kHigh, 1386 NoiseSuppression::kVeryHigh 1387 }; 1388 for (size_t i = 0; i < arraysize(level); i++) { 1389 EXPECT_EQ(apm_->kNoError, 1390 apm_->noise_suppression()->set_level(level[i])); 1391 EXPECT_EQ(level[i], apm_->noise_suppression()->level()); 1392 } 1393 1394 // Turn NS on/off 1395 EXPECT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(true)); 1396 EXPECT_TRUE(apm_->noise_suppression()->is_enabled()); 1397 EXPECT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(false)); 1398 EXPECT_FALSE(apm_->noise_suppression()->is_enabled()); 1399 } 1400 1401 TEST_F(ApmTest, HighPassFilter) { 1402 // Turn HP filter on/off 1403 EXPECT_EQ(apm_->kNoError, apm_->high_pass_filter()->Enable(true)); 1404 EXPECT_TRUE(apm_->high_pass_filter()->is_enabled()); 1405 EXPECT_EQ(apm_->kNoError, apm_->high_pass_filter()->Enable(false)); 1406 EXPECT_FALSE(apm_->high_pass_filter()->is_enabled()); 1407 } 1408 1409 TEST_F(ApmTest, LevelEstimator) { 1410 // Turn level estimator on/off 1411 EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(false)); 1412 EXPECT_FALSE(apm_->level_estimator()->is_enabled()); 1413 1414 EXPECT_EQ(apm_->kNotEnabledError, apm_->level_estimator()->RMS()); 1415 1416 EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true)); 1417 EXPECT_TRUE(apm_->level_estimator()->is_enabled()); 1418 1419 // Run this test in wideband; in super-wb, the splitting filter distorts the 1420 // audio enough to cause deviation from the expectation for small values. 1421 frame_->samples_per_channel_ = 160; 1422 frame_->num_channels_ = 2; 1423 frame_->sample_rate_hz_ = 16000; 1424 1425 // Min value if no frames have been processed. 1426 EXPECT_EQ(127, apm_->level_estimator()->RMS()); 1427 1428 // Min value on zero frames. 1429 SetFrameTo(frame_, 0); 1430 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1431 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1432 EXPECT_EQ(127, apm_->level_estimator()->RMS()); 1433 1434 // Try a few RMS values. 1435 // (These also test that the value resets after retrieving it.) 1436 SetFrameTo(frame_, 32767); 1437 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1438 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1439 EXPECT_EQ(0, apm_->level_estimator()->RMS()); 1440 1441 SetFrameTo(frame_, 30000); 1442 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1443 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1444 EXPECT_EQ(1, apm_->level_estimator()->RMS()); 1445 1446 SetFrameTo(frame_, 10000); 1447 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1448 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1449 EXPECT_EQ(10, apm_->level_estimator()->RMS()); 1450 1451 SetFrameTo(frame_, 10); 1452 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1453 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1454 EXPECT_EQ(70, apm_->level_estimator()->RMS()); 1455 1456 // Verify reset after enable/disable. 1457 SetFrameTo(frame_, 32767); 1458 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1459 EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(false)); 1460 EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true)); 1461 SetFrameTo(frame_, 1); 1462 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1463 EXPECT_EQ(90, apm_->level_estimator()->RMS()); 1464 1465 // Verify reset after initialize. 1466 SetFrameTo(frame_, 32767); 1467 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1468 EXPECT_EQ(apm_->kNoError, apm_->Initialize()); 1469 SetFrameTo(frame_, 1); 1470 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1471 EXPECT_EQ(90, apm_->level_estimator()->RMS()); 1472 } 1473 1474 TEST_F(ApmTest, VoiceDetection) { 1475 // Test external VAD 1476 EXPECT_EQ(apm_->kNoError, 1477 apm_->voice_detection()->set_stream_has_voice(true)); 1478 EXPECT_TRUE(apm_->voice_detection()->stream_has_voice()); 1479 EXPECT_EQ(apm_->kNoError, 1480 apm_->voice_detection()->set_stream_has_voice(false)); 1481 EXPECT_FALSE(apm_->voice_detection()->stream_has_voice()); 1482 1483 // Test valid likelihoods 1484 VoiceDetection::Likelihood likelihood[] = { 1485 VoiceDetection::kVeryLowLikelihood, 1486 VoiceDetection::kLowLikelihood, 1487 VoiceDetection::kModerateLikelihood, 1488 VoiceDetection::kHighLikelihood 1489 }; 1490 for (size_t i = 0; i < arraysize(likelihood); i++) { 1491 EXPECT_EQ(apm_->kNoError, 1492 apm_->voice_detection()->set_likelihood(likelihood[i])); 1493 EXPECT_EQ(likelihood[i], apm_->voice_detection()->likelihood()); 1494 } 1495 1496 /* TODO(bjornv): Enable once VAD supports other frame lengths than 10 ms 1497 // Test invalid frame sizes 1498 EXPECT_EQ(apm_->kBadParameterError, 1499 apm_->voice_detection()->set_frame_size_ms(12)); 1500 1501 // Test valid frame sizes 1502 for (int i = 10; i <= 30; i += 10) { 1503 EXPECT_EQ(apm_->kNoError, 1504 apm_->voice_detection()->set_frame_size_ms(i)); 1505 EXPECT_EQ(i, apm_->voice_detection()->frame_size_ms()); 1506 } 1507 */ 1508 1509 // Turn VAD on/off 1510 EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true)); 1511 EXPECT_TRUE(apm_->voice_detection()->is_enabled()); 1512 EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(false)); 1513 EXPECT_FALSE(apm_->voice_detection()->is_enabled()); 1514 1515 // Test that AudioFrame activity is maintained when VAD is disabled. 1516 EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(false)); 1517 AudioFrame::VADActivity activity[] = { 1518 AudioFrame::kVadActive, 1519 AudioFrame::kVadPassive, 1520 AudioFrame::kVadUnknown 1521 }; 1522 for (size_t i = 0; i < arraysize(activity); i++) { 1523 frame_->vad_activity_ = activity[i]; 1524 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1525 EXPECT_EQ(activity[i], frame_->vad_activity_); 1526 } 1527 1528 // Test that AudioFrame activity is set when VAD is enabled. 1529 EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true)); 1530 frame_->vad_activity_ = AudioFrame::kVadUnknown; 1531 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1532 EXPECT_NE(AudioFrame::kVadUnknown, frame_->vad_activity_); 1533 1534 // TODO(bjornv): Add tests for streamed voice; stream_has_voice() 1535 } 1536 1537 TEST_F(ApmTest, AllProcessingDisabledByDefault) { 1538 EXPECT_FALSE(apm_->echo_cancellation()->is_enabled()); 1539 EXPECT_FALSE(apm_->echo_control_mobile()->is_enabled()); 1540 EXPECT_FALSE(apm_->gain_control()->is_enabled()); 1541 EXPECT_FALSE(apm_->high_pass_filter()->is_enabled()); 1542 EXPECT_FALSE(apm_->level_estimator()->is_enabled()); 1543 EXPECT_FALSE(apm_->noise_suppression()->is_enabled()); 1544 EXPECT_FALSE(apm_->voice_detection()->is_enabled()); 1545 } 1546 1547 TEST_F(ApmTest, NoProcessingWhenAllComponentsDisabled) { 1548 for (size_t i = 0; i < arraysize(kSampleRates); i++) { 1549 Init(kSampleRates[i], kSampleRates[i], kSampleRates[i], 2, 2, 2, false); 1550 SetFrameTo(frame_, 1000, 2000); 1551 AudioFrame frame_copy; 1552 frame_copy.CopyFrom(*frame_); 1553 for (int j = 0; j < 1000; j++) { 1554 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1555 EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy)); 1556 EXPECT_EQ(apm_->kNoError, apm_->ProcessReverseStream(frame_)); 1557 EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy)); 1558 } 1559 } 1560 } 1561 1562 TEST_F(ApmTest, NoProcessingWhenAllComponentsDisabledFloat) { 1563 // Test that ProcessStream copies input to output even with no processing. 1564 const size_t kSamples = 80; 1565 const int sample_rate = 8000; 1566 const float src[kSamples] = { 1567 -1.0f, 0.0f, 1.0f 1568 }; 1569 float dest[kSamples] = {}; 1570 1571 auto src_channels = &src[0]; 1572 auto dest_channels = &dest[0]; 1573 1574 apm_.reset(AudioProcessing::Create()); 1575 EXPECT_NOERR(apm_->ProcessStream( 1576 &src_channels, kSamples, sample_rate, LayoutFromChannels(1), 1577 sample_rate, LayoutFromChannels(1), &dest_channels)); 1578 1579 for (size_t i = 0; i < kSamples; ++i) { 1580 EXPECT_EQ(src[i], dest[i]); 1581 } 1582 1583 // Same for ProcessReverseStream. 1584 float rev_dest[kSamples] = {}; 1585 auto rev_dest_channels = &rev_dest[0]; 1586 1587 StreamConfig input_stream = {sample_rate, 1}; 1588 StreamConfig output_stream = {sample_rate, 1}; 1589 EXPECT_NOERR(apm_->ProcessReverseStream(&src_channels, input_stream, 1590 output_stream, &rev_dest_channels)); 1591 1592 for (size_t i = 0; i < kSamples; ++i) { 1593 EXPECT_EQ(src[i], rev_dest[i]); 1594 } 1595 } 1596 1597 TEST_F(ApmTest, IdenticalInputChannelsResultInIdenticalOutputChannels) { 1598 EnableAllComponents(); 1599 1600 for (size_t i = 0; i < arraysize(kProcessSampleRates); i++) { 1601 Init(kProcessSampleRates[i], 1602 kProcessSampleRates[i], 1603 kProcessSampleRates[i], 1604 2, 1605 2, 1606 2, 1607 false); 1608 int analog_level = 127; 1609 ASSERT_EQ(0, feof(far_file_)); 1610 ASSERT_EQ(0, feof(near_file_)); 1611 while (ReadFrame(far_file_, revframe_) && ReadFrame(near_file_, frame_)) { 1612 CopyLeftToRightChannel(revframe_->data_, revframe_->samples_per_channel_); 1613 1614 ASSERT_EQ(kNoErr, apm_->AnalyzeReverseStream(revframe_)); 1615 1616 CopyLeftToRightChannel(frame_->data_, frame_->samples_per_channel_); 1617 frame_->vad_activity_ = AudioFrame::kVadUnknown; 1618 1619 ASSERT_EQ(kNoErr, apm_->set_stream_delay_ms(0)); 1620 apm_->echo_cancellation()->set_stream_drift_samples(0); 1621 ASSERT_EQ(kNoErr, 1622 apm_->gain_control()->set_stream_analog_level(analog_level)); 1623 ASSERT_EQ(kNoErr, apm_->ProcessStream(frame_)); 1624 analog_level = apm_->gain_control()->stream_analog_level(); 1625 1626 VerifyChannelsAreEqual(frame_->data_, frame_->samples_per_channel_); 1627 } 1628 rewind(far_file_); 1629 rewind(near_file_); 1630 } 1631 } 1632 1633 TEST_F(ApmTest, SplittingFilter) { 1634 // Verify the filter is not active through undistorted audio when: 1635 // 1. No components are enabled... 1636 SetFrameTo(frame_, 1000); 1637 AudioFrame frame_copy; 1638 frame_copy.CopyFrom(*frame_); 1639 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1640 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1641 EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy)); 1642 1643 // 2. Only the level estimator is enabled... 1644 SetFrameTo(frame_, 1000); 1645 frame_copy.CopyFrom(*frame_); 1646 EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true)); 1647 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1648 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1649 EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy)); 1650 EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(false)); 1651 1652 // 3. Only VAD is enabled... 1653 SetFrameTo(frame_, 1000); 1654 frame_copy.CopyFrom(*frame_); 1655 EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true)); 1656 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1657 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1658 EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy)); 1659 EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(false)); 1660 1661 // 4. Both VAD and the level estimator are enabled... 1662 SetFrameTo(frame_, 1000); 1663 frame_copy.CopyFrom(*frame_); 1664 EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true)); 1665 EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true)); 1666 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1667 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1668 EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy)); 1669 EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(false)); 1670 EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(false)); 1671 1672 // TODO(aluebs): Figure out exactly why the AEC affects the audio on Android. 1673 /*// 5. Not using super-wb. 1674 frame_->samples_per_channel_ = 160; 1675 frame_->num_channels_ = 2; 1676 frame_->sample_rate_hz_ = 16000; 1677 // Enable AEC, which would require the filter in super-wb. We rely on the 1678 // first few frames of data being unaffected by the AEC. 1679 // TODO(andrew): This test, and the one below, rely rather tenuously on the 1680 // behavior of the AEC. Think of something more robust. 1681 EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true)); 1682 // Make sure we have extended filter enabled. This makes sure nothing is 1683 // touched until we have a farend frame. 1684 Config config; 1685 config.Set<ExtendedFilter>(new ExtendedFilter(true)); 1686 apm_->SetExtraOptions(config); 1687 SetFrameTo(frame_, 1000); 1688 frame_copy.CopyFrom(*frame_); 1689 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0)); 1690 apm_->echo_cancellation()->set_stream_drift_samples(0); 1691 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1692 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0)); 1693 apm_->echo_cancellation()->set_stream_drift_samples(0); 1694 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1695 EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy)); 1696 1697 // Check the test is valid. We should have distortion from the filter 1698 // when AEC is enabled (which won't affect the audio). 1699 frame_->samples_per_channel_ = 320; 1700 frame_->num_channels_ = 2; 1701 frame_->sample_rate_hz_ = 32000; 1702 SetFrameTo(frame_, 1000); 1703 frame_copy.CopyFrom(*frame_); 1704 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0)); 1705 apm_->echo_cancellation()->set_stream_drift_samples(0); 1706 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1707 EXPECT_FALSE(FrameDataAreEqual(*frame_, frame_copy));*/ 1708 } 1709 1710 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP 1711 void ApmTest::ProcessDebugDump(const std::string& in_filename, 1712 const std::string& out_filename, 1713 Format format) { 1714 FILE* in_file = fopen(in_filename.c_str(), "rb"); 1715 ASSERT_TRUE(in_file != NULL); 1716 audioproc::Event event_msg; 1717 bool first_init = true; 1718 1719 while (ReadMessageFromFile(in_file, &event_msg)) { 1720 if (event_msg.type() == audioproc::Event::INIT) { 1721 const audioproc::Init msg = event_msg.init(); 1722 int reverse_sample_rate = msg.sample_rate(); 1723 if (msg.has_reverse_sample_rate()) { 1724 reverse_sample_rate = msg.reverse_sample_rate(); 1725 } 1726 int output_sample_rate = msg.sample_rate(); 1727 if (msg.has_output_sample_rate()) { 1728 output_sample_rate = msg.output_sample_rate(); 1729 } 1730 1731 Init(msg.sample_rate(), 1732 output_sample_rate, 1733 reverse_sample_rate, 1734 msg.num_input_channels(), 1735 msg.num_output_channels(), 1736 msg.num_reverse_channels(), 1737 false); 1738 if (first_init) { 1739 // StartDebugRecording() writes an additional init message. Don't start 1740 // recording until after the first init to avoid the extra message. 1741 EXPECT_NOERR(apm_->StartDebugRecording(out_filename.c_str())); 1742 first_init = false; 1743 } 1744 1745 } else if (event_msg.type() == audioproc::Event::REVERSE_STREAM) { 1746 const audioproc::ReverseStream msg = event_msg.reverse_stream(); 1747 1748 if (msg.channel_size() > 0) { 1749 ASSERT_EQ(revframe_->num_channels_, 1750 static_cast<size_t>(msg.channel_size())); 1751 for (int i = 0; i < msg.channel_size(); ++i) { 1752 memcpy(revfloat_cb_->channels()[i], 1753 msg.channel(i).data(), 1754 msg.channel(i).size()); 1755 } 1756 } else { 1757 memcpy(revframe_->data_, msg.data().data(), msg.data().size()); 1758 if (format == kFloatFormat) { 1759 // We're using an int16 input file; convert to float. 1760 ConvertToFloat(*revframe_, revfloat_cb_.get()); 1761 } 1762 } 1763 AnalyzeReverseStreamChooser(format); 1764 1765 } else if (event_msg.type() == audioproc::Event::STREAM) { 1766 const audioproc::Stream msg = event_msg.stream(); 1767 // ProcessStream could have changed this for the output frame. 1768 frame_->num_channels_ = apm_->num_input_channels(); 1769 1770 EXPECT_NOERR(apm_->gain_control()->set_stream_analog_level(msg.level())); 1771 EXPECT_NOERR(apm_->set_stream_delay_ms(msg.delay())); 1772 apm_->echo_cancellation()->set_stream_drift_samples(msg.drift()); 1773 if (msg.has_keypress()) { 1774 apm_->set_stream_key_pressed(msg.keypress()); 1775 } else { 1776 apm_->set_stream_key_pressed(true); 1777 } 1778 1779 if (msg.input_channel_size() > 0) { 1780 ASSERT_EQ(frame_->num_channels_, 1781 static_cast<size_t>(msg.input_channel_size())); 1782 for (int i = 0; i < msg.input_channel_size(); ++i) { 1783 memcpy(float_cb_->channels()[i], 1784 msg.input_channel(i).data(), 1785 msg.input_channel(i).size()); 1786 } 1787 } else { 1788 memcpy(frame_->data_, msg.input_data().data(), msg.input_data().size()); 1789 if (format == kFloatFormat) { 1790 // We're using an int16 input file; convert to float. 1791 ConvertToFloat(*frame_, float_cb_.get()); 1792 } 1793 } 1794 ProcessStreamChooser(format); 1795 } 1796 } 1797 EXPECT_NOERR(apm_->StopDebugRecording()); 1798 fclose(in_file); 1799 } 1800 1801 void ApmTest::VerifyDebugDumpTest(Format format) { 1802 const std::string in_filename = test::ResourcePath("ref03", "aecdump"); 1803 std::string format_string; 1804 switch (format) { 1805 case kIntFormat: 1806 format_string = "_int"; 1807 break; 1808 case kFloatFormat: 1809 format_string = "_float"; 1810 break; 1811 } 1812 const std::string ref_filename = test::TempFilename( 1813 test::OutputPath(), std::string("ref") + format_string + "_aecdump"); 1814 const std::string out_filename = test::TempFilename( 1815 test::OutputPath(), std::string("out") + format_string + "_aecdump"); 1816 EnableAllComponents(); 1817 ProcessDebugDump(in_filename, ref_filename, format); 1818 ProcessDebugDump(ref_filename, out_filename, format); 1819 1820 FILE* ref_file = fopen(ref_filename.c_str(), "rb"); 1821 FILE* out_file = fopen(out_filename.c_str(), "rb"); 1822 ASSERT_TRUE(ref_file != NULL); 1823 ASSERT_TRUE(out_file != NULL); 1824 rtc::scoped_ptr<uint8_t[]> ref_bytes; 1825 rtc::scoped_ptr<uint8_t[]> out_bytes; 1826 1827 size_t ref_size = ReadMessageBytesFromFile(ref_file, &ref_bytes); 1828 size_t out_size = ReadMessageBytesFromFile(out_file, &out_bytes); 1829 size_t bytes_read = 0; 1830 while (ref_size > 0 && out_size > 0) { 1831 bytes_read += ref_size; 1832 EXPECT_EQ(ref_size, out_size); 1833 EXPECT_EQ(0, memcmp(ref_bytes.get(), out_bytes.get(), ref_size)); 1834 ref_size = ReadMessageBytesFromFile(ref_file, &ref_bytes); 1835 out_size = ReadMessageBytesFromFile(out_file, &out_bytes); 1836 } 1837 EXPECT_GT(bytes_read, 0u); 1838 EXPECT_NE(0, feof(ref_file)); 1839 EXPECT_NE(0, feof(out_file)); 1840 ASSERT_EQ(0, fclose(ref_file)); 1841 ASSERT_EQ(0, fclose(out_file)); 1842 remove(ref_filename.c_str()); 1843 remove(out_filename.c_str()); 1844 } 1845 1846 TEST_F(ApmTest, VerifyDebugDumpInt) { 1847 VerifyDebugDumpTest(kIntFormat); 1848 } 1849 1850 TEST_F(ApmTest, VerifyDebugDumpFloat) { 1851 VerifyDebugDumpTest(kFloatFormat); 1852 } 1853 #endif 1854 1855 // TODO(andrew): expand test to verify output. 1856 TEST_F(ApmTest, DebugDump) { 1857 const std::string filename = 1858 test::TempFilename(test::OutputPath(), "debug_aec"); 1859 EXPECT_EQ(apm_->kNullPointerError, 1860 apm_->StartDebugRecording(static_cast<const char*>(NULL))); 1861 1862 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP 1863 // Stopping without having started should be OK. 1864 EXPECT_EQ(apm_->kNoError, apm_->StopDebugRecording()); 1865 1866 EXPECT_EQ(apm_->kNoError, apm_->StartDebugRecording(filename.c_str())); 1867 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1868 EXPECT_EQ(apm_->kNoError, apm_->AnalyzeReverseStream(revframe_)); 1869 EXPECT_EQ(apm_->kNoError, apm_->StopDebugRecording()); 1870 1871 // Verify the file has been written. 1872 FILE* fid = fopen(filename.c_str(), "r"); 1873 ASSERT_TRUE(fid != NULL); 1874 1875 // Clean it up. 1876 ASSERT_EQ(0, fclose(fid)); 1877 ASSERT_EQ(0, remove(filename.c_str())); 1878 #else 1879 EXPECT_EQ(apm_->kUnsupportedFunctionError, 1880 apm_->StartDebugRecording(filename.c_str())); 1881 EXPECT_EQ(apm_->kUnsupportedFunctionError, apm_->StopDebugRecording()); 1882 1883 // Verify the file has NOT been written. 1884 ASSERT_TRUE(fopen(filename.c_str(), "r") == NULL); 1885 #endif // WEBRTC_AUDIOPROC_DEBUG_DUMP 1886 } 1887 1888 // TODO(andrew): expand test to verify output. 1889 TEST_F(ApmTest, DebugDumpFromFileHandle) { 1890 FILE* fid = NULL; 1891 EXPECT_EQ(apm_->kNullPointerError, apm_->StartDebugRecording(fid)); 1892 const std::string filename = 1893 test::TempFilename(test::OutputPath(), "debug_aec"); 1894 fid = fopen(filename.c_str(), "w"); 1895 ASSERT_TRUE(fid); 1896 1897 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP 1898 // Stopping without having started should be OK. 1899 EXPECT_EQ(apm_->kNoError, apm_->StopDebugRecording()); 1900 1901 EXPECT_EQ(apm_->kNoError, apm_->StartDebugRecording(fid)); 1902 EXPECT_EQ(apm_->kNoError, apm_->AnalyzeReverseStream(revframe_)); 1903 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 1904 EXPECT_EQ(apm_->kNoError, apm_->StopDebugRecording()); 1905 1906 // Verify the file has been written. 1907 fid = fopen(filename.c_str(), "r"); 1908 ASSERT_TRUE(fid != NULL); 1909 1910 // Clean it up. 1911 ASSERT_EQ(0, fclose(fid)); 1912 ASSERT_EQ(0, remove(filename.c_str())); 1913 #else 1914 EXPECT_EQ(apm_->kUnsupportedFunctionError, 1915 apm_->StartDebugRecording(fid)); 1916 EXPECT_EQ(apm_->kUnsupportedFunctionError, apm_->StopDebugRecording()); 1917 1918 ASSERT_EQ(0, fclose(fid)); 1919 #endif // WEBRTC_AUDIOPROC_DEBUG_DUMP 1920 } 1921 1922 TEST_F(ApmTest, FloatAndIntInterfacesGiveSimilarResults) { 1923 audioproc::OutputData ref_data; 1924 OpenFileAndReadMessage(ref_filename_, &ref_data); 1925 1926 Config config; 1927 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); 1928 rtc::scoped_ptr<AudioProcessing> fapm(AudioProcessing::Create(config)); 1929 EnableAllComponents(); 1930 EnableAllAPComponents(fapm.get()); 1931 for (int i = 0; i < ref_data.test_size(); i++) { 1932 printf("Running test %d of %d...\n", i + 1, ref_data.test_size()); 1933 1934 audioproc::Test* test = ref_data.mutable_test(i); 1935 // TODO(ajm): Restore downmixing test cases. 1936 if (test->num_input_channels() != test->num_output_channels()) 1937 continue; 1938 1939 const size_t num_render_channels = 1940 static_cast<size_t>(test->num_reverse_channels()); 1941 const size_t num_input_channels = 1942 static_cast<size_t>(test->num_input_channels()); 1943 const size_t num_output_channels = 1944 static_cast<size_t>(test->num_output_channels()); 1945 const size_t samples_per_channel = static_cast<size_t>( 1946 test->sample_rate() * AudioProcessing::kChunkSizeMs / 1000); 1947 1948 Init(test->sample_rate(), test->sample_rate(), test->sample_rate(), 1949 num_input_channels, num_output_channels, num_render_channels, true); 1950 Init(fapm.get()); 1951 1952 ChannelBuffer<int16_t> output_cb(samples_per_channel, num_input_channels); 1953 ChannelBuffer<int16_t> output_int16(samples_per_channel, 1954 num_input_channels); 1955 1956 int analog_level = 127; 1957 while (ReadFrame(far_file_, revframe_, revfloat_cb_.get()) && 1958 ReadFrame(near_file_, frame_, float_cb_.get())) { 1959 frame_->vad_activity_ = AudioFrame::kVadUnknown; 1960 1961 EXPECT_NOERR(apm_->AnalyzeReverseStream(revframe_)); 1962 EXPECT_NOERR(fapm->AnalyzeReverseStream( 1963 revfloat_cb_->channels(), 1964 samples_per_channel, 1965 test->sample_rate(), 1966 LayoutFromChannels(num_render_channels))); 1967 1968 EXPECT_NOERR(apm_->set_stream_delay_ms(0)); 1969 EXPECT_NOERR(fapm->set_stream_delay_ms(0)); 1970 apm_->echo_cancellation()->set_stream_drift_samples(0); 1971 fapm->echo_cancellation()->set_stream_drift_samples(0); 1972 EXPECT_NOERR(apm_->gain_control()->set_stream_analog_level(analog_level)); 1973 EXPECT_NOERR(fapm->gain_control()->set_stream_analog_level(analog_level)); 1974 1975 EXPECT_NOERR(apm_->ProcessStream(frame_)); 1976 Deinterleave(frame_->data_, samples_per_channel, num_output_channels, 1977 output_int16.channels()); 1978 1979 EXPECT_NOERR(fapm->ProcessStream( 1980 float_cb_->channels(), 1981 samples_per_channel, 1982 test->sample_rate(), 1983 LayoutFromChannels(num_input_channels), 1984 test->sample_rate(), 1985 LayoutFromChannels(num_output_channels), 1986 float_cb_->channels())); 1987 for (size_t j = 0; j < num_output_channels; ++j) { 1988 FloatToS16(float_cb_->channels()[j], 1989 samples_per_channel, 1990 output_cb.channels()[j]); 1991 float variance = 0; 1992 float snr = ComputeSNR(output_int16.channels()[j], 1993 output_cb.channels()[j], 1994 samples_per_channel, &variance); 1995 #if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE) 1996 // There are a few chunks in the fixed-point profile that give low SNR. 1997 // Listening confirmed the difference is acceptable. 1998 const float kVarianceThreshold = 150; 1999 const float kSNRThreshold = 10; 2000 #else 2001 const float kVarianceThreshold = 20; 2002 const float kSNRThreshold = 20; 2003 #endif 2004 // Skip frames with low energy. 2005 if (sqrt(variance) > kVarianceThreshold) { 2006 EXPECT_LT(kSNRThreshold, snr); 2007 } 2008 } 2009 2010 analog_level = fapm->gain_control()->stream_analog_level(); 2011 EXPECT_EQ(apm_->gain_control()->stream_analog_level(), 2012 fapm->gain_control()->stream_analog_level()); 2013 EXPECT_EQ(apm_->echo_cancellation()->stream_has_echo(), 2014 fapm->echo_cancellation()->stream_has_echo()); 2015 EXPECT_NEAR(apm_->noise_suppression()->speech_probability(), 2016 fapm->noise_suppression()->speech_probability(), 2017 0.01); 2018 2019 // Reset in case of downmixing. 2020 frame_->num_channels_ = static_cast<size_t>(test->num_input_channels()); 2021 } 2022 rewind(far_file_); 2023 rewind(near_file_); 2024 } 2025 } 2026 2027 // TODO(andrew): Add a test to process a few frames with different combinations 2028 // of enabled components. 2029 2030 TEST_F(ApmTest, Process) { 2031 GOOGLE_PROTOBUF_VERIFY_VERSION; 2032 audioproc::OutputData ref_data; 2033 2034 if (!write_ref_data) { 2035 OpenFileAndReadMessage(ref_filename_, &ref_data); 2036 } else { 2037 // Write the desired tests to the protobuf reference file. 2038 for (size_t i = 0; i < arraysize(kChannels); i++) { 2039 for (size_t j = 0; j < arraysize(kChannels); j++) { 2040 for (size_t l = 0; l < arraysize(kProcessSampleRates); l++) { 2041 audioproc::Test* test = ref_data.add_test(); 2042 test->set_num_reverse_channels(kChannels[i]); 2043 test->set_num_input_channels(kChannels[j]); 2044 test->set_num_output_channels(kChannels[j]); 2045 test->set_sample_rate(kProcessSampleRates[l]); 2046 test->set_use_aec_extended_filter(false); 2047 } 2048 } 2049 } 2050 #if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE) 2051 // To test the extended filter mode. 2052 audioproc::Test* test = ref_data.add_test(); 2053 test->set_num_reverse_channels(2); 2054 test->set_num_input_channels(2); 2055 test->set_num_output_channels(2); 2056 test->set_sample_rate(AudioProcessing::kSampleRate32kHz); 2057 test->set_use_aec_extended_filter(true); 2058 #endif 2059 } 2060 2061 for (int i = 0; i < ref_data.test_size(); i++) { 2062 printf("Running test %d of %d...\n", i + 1, ref_data.test_size()); 2063 2064 audioproc::Test* test = ref_data.mutable_test(i); 2065 // TODO(ajm): We no longer allow different input and output channels. Skip 2066 // these tests for now, but they should be removed from the set. 2067 if (test->num_input_channels() != test->num_output_channels()) 2068 continue; 2069 2070 Config config; 2071 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); 2072 config.Set<ExtendedFilter>( 2073 new ExtendedFilter(test->use_aec_extended_filter())); 2074 apm_.reset(AudioProcessing::Create(config)); 2075 2076 EnableAllComponents(); 2077 2078 Init(test->sample_rate(), 2079 test->sample_rate(), 2080 test->sample_rate(), 2081 static_cast<size_t>(test->num_input_channels()), 2082 static_cast<size_t>(test->num_output_channels()), 2083 static_cast<size_t>(test->num_reverse_channels()), 2084 true); 2085 2086 int frame_count = 0; 2087 int has_echo_count = 0; 2088 int has_voice_count = 0; 2089 int is_saturated_count = 0; 2090 int analog_level = 127; 2091 int analog_level_average = 0; 2092 int max_output_average = 0; 2093 float ns_speech_prob_average = 0.0f; 2094 2095 while (ReadFrame(far_file_, revframe_) && ReadFrame(near_file_, frame_)) { 2096 EXPECT_EQ(apm_->kNoError, apm_->AnalyzeReverseStream(revframe_)); 2097 2098 frame_->vad_activity_ = AudioFrame::kVadUnknown; 2099 2100 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0)); 2101 apm_->echo_cancellation()->set_stream_drift_samples(0); 2102 EXPECT_EQ(apm_->kNoError, 2103 apm_->gain_control()->set_stream_analog_level(analog_level)); 2104 2105 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); 2106 2107 // Ensure the frame was downmixed properly. 2108 EXPECT_EQ(static_cast<size_t>(test->num_output_channels()), 2109 frame_->num_channels_); 2110 2111 max_output_average += MaxAudioFrame(*frame_); 2112 2113 if (apm_->echo_cancellation()->stream_has_echo()) { 2114 has_echo_count++; 2115 } 2116 2117 analog_level = apm_->gain_control()->stream_analog_level(); 2118 analog_level_average += analog_level; 2119 if (apm_->gain_control()->stream_is_saturated()) { 2120 is_saturated_count++; 2121 } 2122 if (apm_->voice_detection()->stream_has_voice()) { 2123 has_voice_count++; 2124 EXPECT_EQ(AudioFrame::kVadActive, frame_->vad_activity_); 2125 } else { 2126 EXPECT_EQ(AudioFrame::kVadPassive, frame_->vad_activity_); 2127 } 2128 2129 ns_speech_prob_average += apm_->noise_suppression()->speech_probability(); 2130 2131 size_t frame_size = frame_->samples_per_channel_ * frame_->num_channels_; 2132 size_t write_count = fwrite(frame_->data_, 2133 sizeof(int16_t), 2134 frame_size, 2135 out_file_); 2136 ASSERT_EQ(frame_size, write_count); 2137 2138 // Reset in case of downmixing. 2139 frame_->num_channels_ = static_cast<size_t>(test->num_input_channels()); 2140 frame_count++; 2141 } 2142 max_output_average /= frame_count; 2143 analog_level_average /= frame_count; 2144 ns_speech_prob_average /= frame_count; 2145 2146 #if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE) 2147 EchoCancellation::Metrics echo_metrics; 2148 EXPECT_EQ(apm_->kNoError, 2149 apm_->echo_cancellation()->GetMetrics(&echo_metrics)); 2150 int median = 0; 2151 int std = 0; 2152 float fraction_poor_delays = 0; 2153 EXPECT_EQ(apm_->kNoError, 2154 apm_->echo_cancellation()->GetDelayMetrics( 2155 &median, &std, &fraction_poor_delays)); 2156 2157 int rms_level = apm_->level_estimator()->RMS(); 2158 EXPECT_LE(0, rms_level); 2159 EXPECT_GE(127, rms_level); 2160 #endif 2161 2162 if (!write_ref_data) { 2163 const int kIntNear = 1; 2164 // When running the test on a N7 we get a {2, 6} difference of 2165 // |has_voice_count| and |max_output_average| is up to 18 higher. 2166 // All numbers being consistently higher on N7 compare to ref_data. 2167 // TODO(bjornv): If we start getting more of these offsets on Android we 2168 // should consider a different approach. Either using one slack for all, 2169 // or generate a separate android reference. 2170 #if defined(WEBRTC_ANDROID) 2171 const int kHasVoiceCountOffset = 3; 2172 const int kHasVoiceCountNear = 3; 2173 const int kMaxOutputAverageOffset = 9; 2174 const int kMaxOutputAverageNear = 9; 2175 #else 2176 const int kHasVoiceCountOffset = 0; 2177 const int kHasVoiceCountNear = kIntNear; 2178 const int kMaxOutputAverageOffset = 0; 2179 const int kMaxOutputAverageNear = kIntNear; 2180 #endif 2181 EXPECT_NEAR(test->has_echo_count(), has_echo_count, kIntNear); 2182 EXPECT_NEAR(test->has_voice_count(), 2183 has_voice_count - kHasVoiceCountOffset, 2184 kHasVoiceCountNear); 2185 EXPECT_NEAR(test->is_saturated_count(), is_saturated_count, kIntNear); 2186 2187 EXPECT_NEAR(test->analog_level_average(), analog_level_average, kIntNear); 2188 EXPECT_NEAR(test->max_output_average(), 2189 max_output_average - kMaxOutputAverageOffset, 2190 kMaxOutputAverageNear); 2191 2192 #if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE) 2193 audioproc::Test::EchoMetrics reference = test->echo_metrics(); 2194 TestStats(echo_metrics.residual_echo_return_loss, 2195 reference.residual_echo_return_loss()); 2196 TestStats(echo_metrics.echo_return_loss, 2197 reference.echo_return_loss()); 2198 TestStats(echo_metrics.echo_return_loss_enhancement, 2199 reference.echo_return_loss_enhancement()); 2200 TestStats(echo_metrics.a_nlp, 2201 reference.a_nlp()); 2202 2203 const double kFloatNear = 0.0005; 2204 audioproc::Test::DelayMetrics reference_delay = test->delay_metrics(); 2205 EXPECT_NEAR(reference_delay.median(), median, kIntNear); 2206 EXPECT_NEAR(reference_delay.std(), std, kIntNear); 2207 EXPECT_NEAR(reference_delay.fraction_poor_delays(), fraction_poor_delays, 2208 kFloatNear); 2209 2210 EXPECT_NEAR(test->rms_level(), rms_level, kIntNear); 2211 2212 EXPECT_NEAR(test->ns_speech_probability_average(), 2213 ns_speech_prob_average, 2214 kFloatNear); 2215 #endif 2216 } else { 2217 test->set_has_echo_count(has_echo_count); 2218 test->set_has_voice_count(has_voice_count); 2219 test->set_is_saturated_count(is_saturated_count); 2220 2221 test->set_analog_level_average(analog_level_average); 2222 test->set_max_output_average(max_output_average); 2223 2224 #if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE) 2225 audioproc::Test::EchoMetrics* message = test->mutable_echo_metrics(); 2226 WriteStatsMessage(echo_metrics.residual_echo_return_loss, 2227 message->mutable_residual_echo_return_loss()); 2228 WriteStatsMessage(echo_metrics.echo_return_loss, 2229 message->mutable_echo_return_loss()); 2230 WriteStatsMessage(echo_metrics.echo_return_loss_enhancement, 2231 message->mutable_echo_return_loss_enhancement()); 2232 WriteStatsMessage(echo_metrics.a_nlp, 2233 message->mutable_a_nlp()); 2234 2235 audioproc::Test::DelayMetrics* message_delay = 2236 test->mutable_delay_metrics(); 2237 message_delay->set_median(median); 2238 message_delay->set_std(std); 2239 message_delay->set_fraction_poor_delays(fraction_poor_delays); 2240 2241 test->set_rms_level(rms_level); 2242 2243 EXPECT_LE(0.0f, ns_speech_prob_average); 2244 EXPECT_GE(1.0f, ns_speech_prob_average); 2245 test->set_ns_speech_probability_average(ns_speech_prob_average); 2246 #endif 2247 } 2248 2249 rewind(far_file_); 2250 rewind(near_file_); 2251 } 2252 2253 if (write_ref_data) { 2254 OpenFileAndWriteMessage(ref_filename_, ref_data); 2255 } 2256 } 2257 2258 TEST_F(ApmTest, NoErrorsWithKeyboardChannel) { 2259 struct ChannelFormat { 2260 AudioProcessing::ChannelLayout in_layout; 2261 AudioProcessing::ChannelLayout out_layout; 2262 }; 2263 ChannelFormat cf[] = { 2264 {AudioProcessing::kMonoAndKeyboard, AudioProcessing::kMono}, 2265 {AudioProcessing::kStereoAndKeyboard, AudioProcessing::kMono}, 2266 {AudioProcessing::kStereoAndKeyboard, AudioProcessing::kStereo}, 2267 }; 2268 2269 rtc::scoped_ptr<AudioProcessing> ap(AudioProcessing::Create()); 2270 // Enable one component just to ensure some processing takes place. 2271 ap->noise_suppression()->Enable(true); 2272 for (size_t i = 0; i < arraysize(cf); ++i) { 2273 const int in_rate = 44100; 2274 const int out_rate = 48000; 2275 ChannelBuffer<float> in_cb(SamplesFromRate(in_rate), 2276 TotalChannelsFromLayout(cf[i].in_layout)); 2277 ChannelBuffer<float> out_cb(SamplesFromRate(out_rate), 2278 ChannelsFromLayout(cf[i].out_layout)); 2279 2280 // Run over a few chunks. 2281 for (int j = 0; j < 10; ++j) { 2282 EXPECT_NOERR(ap->ProcessStream( 2283 in_cb.channels(), 2284 in_cb.num_frames(), 2285 in_rate, 2286 cf[i].in_layout, 2287 out_rate, 2288 cf[i].out_layout, 2289 out_cb.channels())); 2290 } 2291 } 2292 } 2293 2294 // Compares the reference and test arrays over a region around the expected 2295 // delay. Finds the highest SNR in that region and adds the variance and squared 2296 // error results to the supplied accumulators. 2297 void UpdateBestSNR(const float* ref, 2298 const float* test, 2299 size_t length, 2300 int expected_delay, 2301 double* variance_acc, 2302 double* sq_error_acc) { 2303 double best_snr = std::numeric_limits<double>::min(); 2304 double best_variance = 0; 2305 double best_sq_error = 0; 2306 // Search over a region of eight samples around the expected delay. 2307 for (int delay = std::max(expected_delay - 4, 0); delay <= expected_delay + 4; 2308 ++delay) { 2309 double sq_error = 0; 2310 double variance = 0; 2311 for (size_t i = 0; i < length - delay; ++i) { 2312 double error = test[i + delay] - ref[i]; 2313 sq_error += error * error; 2314 variance += ref[i] * ref[i]; 2315 } 2316 2317 if (sq_error == 0) { 2318 *variance_acc += variance; 2319 return; 2320 } 2321 double snr = variance / sq_error; 2322 if (snr > best_snr) { 2323 best_snr = snr; 2324 best_variance = variance; 2325 best_sq_error = sq_error; 2326 } 2327 } 2328 2329 *variance_acc += best_variance; 2330 *sq_error_acc += best_sq_error; 2331 } 2332 2333 // Used to test a multitude of sample rate and channel combinations. It works 2334 // by first producing a set of reference files (in SetUpTestCase) that are 2335 // assumed to be correct, as the used parameters are verified by other tests 2336 // in this collection. Primarily the reference files are all produced at 2337 // "native" rates which do not involve any resampling. 2338 2339 // Each test pass produces an output file with a particular format. The output 2340 // is matched against the reference file closest to its internal processing 2341 // format. If necessary the output is resampled back to its process format. 2342 // Due to the resampling distortion, we don't expect identical results, but 2343 // enforce SNR thresholds which vary depending on the format. 0 is a special 2344 // case SNR which corresponds to inf, or zero error. 2345 typedef std::tr1::tuple<int, int, int, int, double, double> 2346 AudioProcessingTestData; 2347 class AudioProcessingTest 2348 : public testing::TestWithParam<AudioProcessingTestData> { 2349 public: 2350 AudioProcessingTest() 2351 : input_rate_(std::tr1::get<0>(GetParam())), 2352 output_rate_(std::tr1::get<1>(GetParam())), 2353 reverse_input_rate_(std::tr1::get<2>(GetParam())), 2354 reverse_output_rate_(std::tr1::get<3>(GetParam())), 2355 expected_snr_(std::tr1::get<4>(GetParam())), 2356 expected_reverse_snr_(std::tr1::get<5>(GetParam())) {} 2357 2358 virtual ~AudioProcessingTest() {} 2359 2360 static void SetUpTestCase() { 2361 // Create all needed output reference files. 2362 const int kNativeRates[] = {8000, 16000, 32000, 48000}; 2363 const size_t kNumChannels[] = {1, 2}; 2364 for (size_t i = 0; i < arraysize(kNativeRates); ++i) { 2365 for (size_t j = 0; j < arraysize(kNumChannels); ++j) { 2366 for (size_t k = 0; k < arraysize(kNumChannels); ++k) { 2367 // The reference files always have matching input and output channels. 2368 ProcessFormat(kNativeRates[i], kNativeRates[i], kNativeRates[i], 2369 kNativeRates[i], kNumChannels[j], kNumChannels[j], 2370 kNumChannels[k], kNumChannels[k], "ref"); 2371 } 2372 } 2373 } 2374 } 2375 2376 static void TearDownTestCase() { 2377 ClearTempFiles(); 2378 } 2379 2380 // Runs a process pass on files with the given parameters and dumps the output 2381 // to a file specified with |output_file_prefix|. Both forward and reverse 2382 // output streams are dumped. 2383 static void ProcessFormat(int input_rate, 2384 int output_rate, 2385 int reverse_input_rate, 2386 int reverse_output_rate, 2387 size_t num_input_channels, 2388 size_t num_output_channels, 2389 size_t num_reverse_input_channels, 2390 size_t num_reverse_output_channels, 2391 std::string output_file_prefix) { 2392 Config config; 2393 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); 2394 rtc::scoped_ptr<AudioProcessing> ap(AudioProcessing::Create(config)); 2395 EnableAllAPComponents(ap.get()); 2396 2397 ProcessingConfig processing_config = { 2398 {{input_rate, num_input_channels}, 2399 {output_rate, num_output_channels}, 2400 {reverse_input_rate, num_reverse_input_channels}, 2401 {reverse_output_rate, num_reverse_output_channels}}}; 2402 ap->Initialize(processing_config); 2403 2404 FILE* far_file = 2405 fopen(ResourceFilePath("far", reverse_input_rate).c_str(), "rb"); 2406 FILE* near_file = fopen(ResourceFilePath("near", input_rate).c_str(), "rb"); 2407 FILE* out_file = 2408 fopen(OutputFilePath(output_file_prefix, input_rate, output_rate, 2409 reverse_input_rate, reverse_output_rate, 2410 num_input_channels, num_output_channels, 2411 num_reverse_input_channels, 2412 num_reverse_output_channels, kForward).c_str(), 2413 "wb"); 2414 FILE* rev_out_file = 2415 fopen(OutputFilePath(output_file_prefix, input_rate, output_rate, 2416 reverse_input_rate, reverse_output_rate, 2417 num_input_channels, num_output_channels, 2418 num_reverse_input_channels, 2419 num_reverse_output_channels, kReverse).c_str(), 2420 "wb"); 2421 ASSERT_TRUE(far_file != NULL); 2422 ASSERT_TRUE(near_file != NULL); 2423 ASSERT_TRUE(out_file != NULL); 2424 ASSERT_TRUE(rev_out_file != NULL); 2425 2426 ChannelBuffer<float> fwd_cb(SamplesFromRate(input_rate), 2427 num_input_channels); 2428 ChannelBuffer<float> rev_cb(SamplesFromRate(reverse_input_rate), 2429 num_reverse_input_channels); 2430 ChannelBuffer<float> out_cb(SamplesFromRate(output_rate), 2431 num_output_channels); 2432 ChannelBuffer<float> rev_out_cb(SamplesFromRate(reverse_output_rate), 2433 num_reverse_output_channels); 2434 2435 // Temporary buffers. 2436 const int max_length = 2437 2 * std::max(std::max(out_cb.num_frames(), rev_out_cb.num_frames()), 2438 std::max(fwd_cb.num_frames(), rev_cb.num_frames())); 2439 rtc::scoped_ptr<float[]> float_data(new float[max_length]); 2440 rtc::scoped_ptr<int16_t[]> int_data(new int16_t[max_length]); 2441 2442 int analog_level = 127; 2443 while (ReadChunk(far_file, int_data.get(), float_data.get(), &rev_cb) && 2444 ReadChunk(near_file, int_data.get(), float_data.get(), &fwd_cb)) { 2445 EXPECT_NOERR(ap->ProcessReverseStream( 2446 rev_cb.channels(), processing_config.reverse_input_stream(), 2447 processing_config.reverse_output_stream(), rev_out_cb.channels())); 2448 2449 EXPECT_NOERR(ap->set_stream_delay_ms(0)); 2450 ap->echo_cancellation()->set_stream_drift_samples(0); 2451 EXPECT_NOERR(ap->gain_control()->set_stream_analog_level(analog_level)); 2452 2453 EXPECT_NOERR(ap->ProcessStream( 2454 fwd_cb.channels(), 2455 fwd_cb.num_frames(), 2456 input_rate, 2457 LayoutFromChannels(num_input_channels), 2458 output_rate, 2459 LayoutFromChannels(num_output_channels), 2460 out_cb.channels())); 2461 2462 // Dump forward output to file. 2463 Interleave(out_cb.channels(), out_cb.num_frames(), out_cb.num_channels(), 2464 float_data.get()); 2465 size_t out_length = out_cb.num_channels() * out_cb.num_frames(); 2466 2467 ASSERT_EQ(out_length, 2468 fwrite(float_data.get(), sizeof(float_data[0]), 2469 out_length, out_file)); 2470 2471 // Dump reverse output to file. 2472 Interleave(rev_out_cb.channels(), rev_out_cb.num_frames(), 2473 rev_out_cb.num_channels(), float_data.get()); 2474 size_t rev_out_length = 2475 rev_out_cb.num_channels() * rev_out_cb.num_frames(); 2476 2477 ASSERT_EQ(rev_out_length, 2478 fwrite(float_data.get(), sizeof(float_data[0]), rev_out_length, 2479 rev_out_file)); 2480 2481 analog_level = ap->gain_control()->stream_analog_level(); 2482 } 2483 fclose(far_file); 2484 fclose(near_file); 2485 fclose(out_file); 2486 fclose(rev_out_file); 2487 } 2488 2489 protected: 2490 int input_rate_; 2491 int output_rate_; 2492 int reverse_input_rate_; 2493 int reverse_output_rate_; 2494 double expected_snr_; 2495 double expected_reverse_snr_; 2496 }; 2497 2498 TEST_P(AudioProcessingTest, Formats) { 2499 struct ChannelFormat { 2500 int num_input; 2501 int num_output; 2502 int num_reverse_input; 2503 int num_reverse_output; 2504 }; 2505 ChannelFormat cf[] = { 2506 {1, 1, 1, 1}, 2507 {1, 1, 2, 1}, 2508 {2, 1, 1, 1}, 2509 {2, 1, 2, 1}, 2510 {2, 2, 1, 1}, 2511 {2, 2, 2, 2}, 2512 }; 2513 2514 for (size_t i = 0; i < arraysize(cf); ++i) { 2515 ProcessFormat(input_rate_, output_rate_, reverse_input_rate_, 2516 reverse_output_rate_, cf[i].num_input, cf[i].num_output, 2517 cf[i].num_reverse_input, cf[i].num_reverse_output, "out"); 2518 2519 // Verify output for both directions. 2520 std::vector<StreamDirection> stream_directions; 2521 stream_directions.push_back(kForward); 2522 stream_directions.push_back(kReverse); 2523 for (StreamDirection file_direction : stream_directions) { 2524 const int in_rate = file_direction ? reverse_input_rate_ : input_rate_; 2525 const int out_rate = file_direction ? reverse_output_rate_ : output_rate_; 2526 const int out_num = 2527 file_direction ? cf[i].num_reverse_output : cf[i].num_output; 2528 const double expected_snr = 2529 file_direction ? expected_reverse_snr_ : expected_snr_; 2530 2531 const int min_ref_rate = std::min(in_rate, out_rate); 2532 int ref_rate; 2533 2534 if (min_ref_rate > 32000) { 2535 ref_rate = 48000; 2536 } else if (min_ref_rate > 16000) { 2537 ref_rate = 32000; 2538 } else if (min_ref_rate > 8000) { 2539 ref_rate = 16000; 2540 } else { 2541 ref_rate = 8000; 2542 } 2543 #ifdef WEBRTC_AUDIOPROC_FIXED_PROFILE 2544 if (file_direction == kForward) { 2545 ref_rate = std::min(ref_rate, 16000); 2546 } 2547 #endif 2548 FILE* out_file = fopen( 2549 OutputFilePath("out", input_rate_, output_rate_, reverse_input_rate_, 2550 reverse_output_rate_, cf[i].num_input, 2551 cf[i].num_output, cf[i].num_reverse_input, 2552 cf[i].num_reverse_output, file_direction).c_str(), 2553 "rb"); 2554 // The reference files always have matching input and output channels. 2555 FILE* ref_file = fopen( 2556 OutputFilePath("ref", ref_rate, ref_rate, ref_rate, ref_rate, 2557 cf[i].num_output, cf[i].num_output, 2558 cf[i].num_reverse_output, cf[i].num_reverse_output, 2559 file_direction).c_str(), 2560 "rb"); 2561 ASSERT_TRUE(out_file != NULL); 2562 ASSERT_TRUE(ref_file != NULL); 2563 2564 const size_t ref_length = SamplesFromRate(ref_rate) * out_num; 2565 const size_t out_length = SamplesFromRate(out_rate) * out_num; 2566 // Data from the reference file. 2567 rtc::scoped_ptr<float[]> ref_data(new float[ref_length]); 2568 // Data from the output file. 2569 rtc::scoped_ptr<float[]> out_data(new float[out_length]); 2570 // Data from the resampled output, in case the reference and output rates 2571 // don't match. 2572 rtc::scoped_ptr<float[]> cmp_data(new float[ref_length]); 2573 2574 PushResampler<float> resampler; 2575 resampler.InitializeIfNeeded(out_rate, ref_rate, out_num); 2576 2577 // Compute the resampling delay of the output relative to the reference, 2578 // to find the region over which we should search for the best SNR. 2579 float expected_delay_sec = 0; 2580 if (in_rate != ref_rate) { 2581 // Input resampling delay. 2582 expected_delay_sec += 2583 PushSincResampler::AlgorithmicDelaySeconds(in_rate); 2584 } 2585 if (out_rate != ref_rate) { 2586 // Output resampling delay. 2587 expected_delay_sec += 2588 PushSincResampler::AlgorithmicDelaySeconds(ref_rate); 2589 // Delay of converting the output back to its processing rate for 2590 // testing. 2591 expected_delay_sec += 2592 PushSincResampler::AlgorithmicDelaySeconds(out_rate); 2593 } 2594 int expected_delay = 2595 floor(expected_delay_sec * ref_rate + 0.5f) * out_num; 2596 2597 double variance = 0; 2598 double sq_error = 0; 2599 while (fread(out_data.get(), sizeof(out_data[0]), out_length, out_file) && 2600 fread(ref_data.get(), sizeof(ref_data[0]), ref_length, ref_file)) { 2601 float* out_ptr = out_data.get(); 2602 if (out_rate != ref_rate) { 2603 // Resample the output back to its internal processing rate if 2604 // necssary. 2605 ASSERT_EQ(ref_length, 2606 static_cast<size_t>(resampler.Resample( 2607 out_ptr, out_length, cmp_data.get(), ref_length))); 2608 out_ptr = cmp_data.get(); 2609 } 2610 2611 // Update the |sq_error| and |variance| accumulators with the highest 2612 // SNR of reference vs output. 2613 UpdateBestSNR(ref_data.get(), out_ptr, ref_length, expected_delay, 2614 &variance, &sq_error); 2615 } 2616 2617 std::cout << "(" << input_rate_ << ", " << output_rate_ << ", " 2618 << reverse_input_rate_ << ", " << reverse_output_rate_ << ", " 2619 << cf[i].num_input << ", " << cf[i].num_output << ", " 2620 << cf[i].num_reverse_input << ", " << cf[i].num_reverse_output 2621 << ", " << file_direction << "): "; 2622 if (sq_error > 0) { 2623 double snr = 10 * log10(variance / sq_error); 2624 EXPECT_GE(snr, expected_snr); 2625 EXPECT_NE(0, expected_snr); 2626 std::cout << "SNR=" << snr << " dB" << std::endl; 2627 } else { 2628 EXPECT_EQ(expected_snr, 0); 2629 std::cout << "SNR=" 2630 << "inf dB" << std::endl; 2631 } 2632 2633 fclose(out_file); 2634 fclose(ref_file); 2635 } 2636 } 2637 } 2638 2639 #if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE) 2640 INSTANTIATE_TEST_CASE_P( 2641 CommonFormats, 2642 AudioProcessingTest, 2643 testing::Values(std::tr1::make_tuple(48000, 48000, 48000, 48000, 0, 0), 2644 std::tr1::make_tuple(48000, 48000, 32000, 48000, 40, 30), 2645 std::tr1::make_tuple(48000, 48000, 16000, 48000, 40, 20), 2646 std::tr1::make_tuple(48000, 44100, 48000, 44100, 20, 20), 2647 std::tr1::make_tuple(48000, 44100, 32000, 44100, 20, 15), 2648 std::tr1::make_tuple(48000, 44100, 16000, 44100, 20, 15), 2649 std::tr1::make_tuple(48000, 32000, 48000, 32000, 30, 35), 2650 std::tr1::make_tuple(48000, 32000, 32000, 32000, 30, 0), 2651 std::tr1::make_tuple(48000, 32000, 16000, 32000, 30, 20), 2652 std::tr1::make_tuple(48000, 16000, 48000, 16000, 25, 20), 2653 std::tr1::make_tuple(48000, 16000, 32000, 16000, 25, 20), 2654 std::tr1::make_tuple(48000, 16000, 16000, 16000, 25, 0), 2655 2656 std::tr1::make_tuple(44100, 48000, 48000, 48000, 30, 0), 2657 std::tr1::make_tuple(44100, 48000, 32000, 48000, 30, 30), 2658 std::tr1::make_tuple(44100, 48000, 16000, 48000, 30, 20), 2659 std::tr1::make_tuple(44100, 44100, 48000, 44100, 20, 20), 2660 std::tr1::make_tuple(44100, 44100, 32000, 44100, 20, 15), 2661 std::tr1::make_tuple(44100, 44100, 16000, 44100, 20, 15), 2662 std::tr1::make_tuple(44100, 32000, 48000, 32000, 30, 35), 2663 std::tr1::make_tuple(44100, 32000, 32000, 32000, 30, 0), 2664 std::tr1::make_tuple(44100, 32000, 16000, 32000, 30, 20), 2665 std::tr1::make_tuple(44100, 16000, 48000, 16000, 25, 20), 2666 std::tr1::make_tuple(44100, 16000, 32000, 16000, 25, 20), 2667 std::tr1::make_tuple(44100, 16000, 16000, 16000, 25, 0), 2668 2669 std::tr1::make_tuple(32000, 48000, 48000, 48000, 30, 0), 2670 std::tr1::make_tuple(32000, 48000, 32000, 48000, 35, 30), 2671 std::tr1::make_tuple(32000, 48000, 16000, 48000, 30, 20), 2672 std::tr1::make_tuple(32000, 44100, 48000, 44100, 20, 20), 2673 std::tr1::make_tuple(32000, 44100, 32000, 44100, 20, 15), 2674 std::tr1::make_tuple(32000, 44100, 16000, 44100, 20, 15), 2675 std::tr1::make_tuple(32000, 32000, 48000, 32000, 40, 35), 2676 std::tr1::make_tuple(32000, 32000, 32000, 32000, 0, 0), 2677 std::tr1::make_tuple(32000, 32000, 16000, 32000, 40, 20), 2678 std::tr1::make_tuple(32000, 16000, 48000, 16000, 25, 20), 2679 std::tr1::make_tuple(32000, 16000, 32000, 16000, 25, 20), 2680 std::tr1::make_tuple(32000, 16000, 16000, 16000, 25, 0), 2681 2682 std::tr1::make_tuple(16000, 48000, 48000, 48000, 25, 0), 2683 std::tr1::make_tuple(16000, 48000, 32000, 48000, 25, 30), 2684 std::tr1::make_tuple(16000, 48000, 16000, 48000, 25, 20), 2685 std::tr1::make_tuple(16000, 44100, 48000, 44100, 15, 20), 2686 std::tr1::make_tuple(16000, 44100, 32000, 44100, 15, 15), 2687 std::tr1::make_tuple(16000, 44100, 16000, 44100, 15, 15), 2688 std::tr1::make_tuple(16000, 32000, 48000, 32000, 25, 35), 2689 std::tr1::make_tuple(16000, 32000, 32000, 32000, 25, 0), 2690 std::tr1::make_tuple(16000, 32000, 16000, 32000, 25, 20), 2691 std::tr1::make_tuple(16000, 16000, 48000, 16000, 40, 20), 2692 std::tr1::make_tuple(16000, 16000, 32000, 16000, 50, 20), 2693 std::tr1::make_tuple(16000, 16000, 16000, 16000, 0, 0))); 2694 2695 #elif defined(WEBRTC_AUDIOPROC_FIXED_PROFILE) 2696 INSTANTIATE_TEST_CASE_P( 2697 CommonFormats, 2698 AudioProcessingTest, 2699 testing::Values(std::tr1::make_tuple(48000, 48000, 48000, 48000, 20, 0), 2700 std::tr1::make_tuple(48000, 48000, 32000, 48000, 20, 30), 2701 std::tr1::make_tuple(48000, 48000, 16000, 48000, 20, 20), 2702 std::tr1::make_tuple(48000, 44100, 48000, 44100, 15, 20), 2703 std::tr1::make_tuple(48000, 44100, 32000, 44100, 15, 15), 2704 std::tr1::make_tuple(48000, 44100, 16000, 44100, 15, 15), 2705 std::tr1::make_tuple(48000, 32000, 48000, 32000, 20, 35), 2706 std::tr1::make_tuple(48000, 32000, 32000, 32000, 20, 0), 2707 std::tr1::make_tuple(48000, 32000, 16000, 32000, 20, 20), 2708 std::tr1::make_tuple(48000, 16000, 48000, 16000, 20, 20), 2709 std::tr1::make_tuple(48000, 16000, 32000, 16000, 20, 20), 2710 std::tr1::make_tuple(48000, 16000, 16000, 16000, 20, 0), 2711 2712 std::tr1::make_tuple(44100, 48000, 48000, 48000, 20, 0), 2713 std::tr1::make_tuple(44100, 48000, 32000, 48000, 20, 30), 2714 std::tr1::make_tuple(44100, 48000, 16000, 48000, 20, 20), 2715 std::tr1::make_tuple(44100, 44100, 48000, 44100, 15, 20), 2716 std::tr1::make_tuple(44100, 44100, 32000, 44100, 15, 15), 2717 std::tr1::make_tuple(44100, 44100, 16000, 44100, 15, 15), 2718 std::tr1::make_tuple(44100, 32000, 48000, 32000, 20, 35), 2719 std::tr1::make_tuple(44100, 32000, 32000, 32000, 20, 0), 2720 std::tr1::make_tuple(44100, 32000, 16000, 32000, 20, 20), 2721 std::tr1::make_tuple(44100, 16000, 48000, 16000, 20, 20), 2722 std::tr1::make_tuple(44100, 16000, 32000, 16000, 20, 20), 2723 std::tr1::make_tuple(44100, 16000, 16000, 16000, 20, 0), 2724 2725 std::tr1::make_tuple(32000, 48000, 48000, 48000, 20, 0), 2726 std::tr1::make_tuple(32000, 48000, 32000, 48000, 20, 30), 2727 std::tr1::make_tuple(32000, 48000, 16000, 48000, 20, 20), 2728 std::tr1::make_tuple(32000, 44100, 48000, 44100, 15, 20), 2729 std::tr1::make_tuple(32000, 44100, 32000, 44100, 15, 15), 2730 std::tr1::make_tuple(32000, 44100, 16000, 44100, 15, 15), 2731 std::tr1::make_tuple(32000, 32000, 48000, 32000, 20, 35), 2732 std::tr1::make_tuple(32000, 32000, 32000, 32000, 20, 0), 2733 std::tr1::make_tuple(32000, 32000, 16000, 32000, 20, 20), 2734 std::tr1::make_tuple(32000, 16000, 48000, 16000, 20, 20), 2735 std::tr1::make_tuple(32000, 16000, 32000, 16000, 20, 20), 2736 std::tr1::make_tuple(32000, 16000, 16000, 16000, 20, 0), 2737 2738 std::tr1::make_tuple(16000, 48000, 48000, 48000, 25, 0), 2739 std::tr1::make_tuple(16000, 48000, 32000, 48000, 25, 30), 2740 std::tr1::make_tuple(16000, 48000, 16000, 48000, 25, 20), 2741 std::tr1::make_tuple(16000, 44100, 48000, 44100, 15, 20), 2742 std::tr1::make_tuple(16000, 44100, 32000, 44100, 15, 15), 2743 std::tr1::make_tuple(16000, 44100, 16000, 44100, 15, 15), 2744 std::tr1::make_tuple(16000, 32000, 48000, 32000, 25, 35), 2745 std::tr1::make_tuple(16000, 32000, 32000, 32000, 25, 0), 2746 std::tr1::make_tuple(16000, 32000, 16000, 32000, 25, 20), 2747 std::tr1::make_tuple(16000, 16000, 48000, 16000, 35, 20), 2748 std::tr1::make_tuple(16000, 16000, 32000, 16000, 40, 20), 2749 std::tr1::make_tuple(16000, 16000, 16000, 16000, 0, 0))); 2750 #endif 2751 2752 } // namespace 2753 } // namespace webrtc 2754