| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 #include "gtest/gtest.h" | 33 #include "gtest/gtest.h" |
| 34 #include "external/webrtc/webrtc/modules/audio_processing/test/unittest.pb.h" | 34 #include "external/webrtc/webrtc/modules/audio_processing/test/unittest.pb.h" |
| 35 #else | 35 #else |
| 36 #include "testing/gtest/include/gtest/gtest.h" | 36 #include "testing/gtest/include/gtest/gtest.h" |
| 37 #include "webrtc/audio_processing/unittest.pb.h" | 37 #include "webrtc/audio_processing/unittest.pb.h" |
| 38 #endif | 38 #endif |
| 39 | 39 |
| 40 namespace webrtc { | 40 namespace webrtc { |
| 41 namespace { | 41 namespace { |
| 42 | 42 |
| 43 // TODO(ekmeyerson): Switch to using StreamConfig and ProcessingConfig where |
| 44 // applicable. |
| 45 |
| 43 // TODO(bjornv): This is not feasible until the functionality has been | 46 // TODO(bjornv): This is not feasible until the functionality has been |
| 44 // re-implemented; see comment at the bottom of this file. For now, the user has | 47 // re-implemented; see comment at the bottom of this file. For now, the user has |
| 45 // to hard code the |write_ref_data| value. | 48 // to hard code the |write_ref_data| value. |
| 46 // When false, this will compare the output data with the results stored to | 49 // When false, this will compare the output data with the results stored to |
| 47 // file. This is the typical case. When the file should be updated, it can | 50 // file. This is the typical case. When the file should be updated, it can |
| 48 // be set to true with the command-line switch --write_ref_data. | 51 // be set to true with the command-line switch --write_ref_data. |
| 49 bool write_ref_data = false; | 52 bool write_ref_data = false; |
| 50 const int kChannels[] = {1, 2}; | 53 const int kChannels[] = {1, 2}; |
| 51 const size_t kChannelsSize = sizeof(kChannels) / sizeof(*kChannels); | 54 const size_t kChannelsSize = sizeof(kChannels) / sizeof(*kChannels); |
| 52 | 55 |
| 53 const int kSampleRates[] = {8000, 16000, 32000, 48000}; | 56 const int kSampleRates[] = {8000, 16000, 32000, 48000}; |
| 54 const size_t kSampleRatesSize = sizeof(kSampleRates) / sizeof(*kSampleRates); | 57 const size_t kSampleRatesSize = sizeof(kSampleRates) / sizeof(*kSampleRates); |
| 55 | 58 |
| 56 #if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE) | 59 #if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE) |
| 57 // AECM doesn't support super-wb. | 60 // AECM doesn't support super-wb. |
| 58 const int kProcessSampleRates[] = {8000, 16000}; | 61 const int kProcessSampleRates[] = {8000, 16000}; |
| 59 #elif defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE) | 62 #elif defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE) |
| 60 const int kProcessSampleRates[] = {8000, 16000, 32000, 48000}; | 63 const int kProcessSampleRates[] = {8000, 16000, 32000, 48000}; |
| 61 #endif | 64 #endif |
| 62 const size_t kProcessSampleRatesSize = sizeof(kProcessSampleRates) / | 65 const size_t kProcessSampleRatesSize = sizeof(kProcessSampleRates) / |
| 63 sizeof(*kProcessSampleRates); | 66 sizeof(*kProcessSampleRates); |
| 64 | 67 |
| 68 enum StreamDirection { kForward = 0, kReverse }; |
| 69 |
| 65 void ConvertToFloat(const int16_t* int_data, ChannelBuffer<float>* cb) { | 70 void ConvertToFloat(const int16_t* int_data, ChannelBuffer<float>* cb) { |
| 66 ChannelBuffer<int16_t> cb_int(cb->num_frames(), | 71 ChannelBuffer<int16_t> cb_int(cb->num_frames(), |
| 67 cb->num_channels()); | 72 cb->num_channels()); |
| 68 Deinterleave(int_data, | 73 Deinterleave(int_data, |
| 69 cb->num_frames(), | 74 cb->num_frames(), |
| 70 cb->num_channels(), | 75 cb->num_channels(), |
| 71 cb_int.channels()); | 76 cb_int.channels()); |
| 72 for (int i = 0; i < cb->num_channels(); ++i) { | 77 for (int i = 0; i < cb->num_channels(); ++i) { |
| 73 S16ToFloat(cb_int.channels()[i], | 78 S16ToFloat(cb_int.channels()[i], |
| 74 cb->num_frames(), | 79 cb->num_frames(), |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 } | 250 } |
| 246 | 251 |
| 247 // Temporary filenames unique to this process. Used to be able to run these | 252 // Temporary filenames unique to this process. Used to be able to run these |
| 248 // tests in parallel as each process needs to be running in isolation they can't | 253 // tests in parallel as each process needs to be running in isolation they can't |
| 249 // have competing filenames. | 254 // have competing filenames. |
| 250 std::map<std::string, std::string> temp_filenames; | 255 std::map<std::string, std::string> temp_filenames; |
| 251 | 256 |
| 252 std::string OutputFilePath(std::string name, | 257 std::string OutputFilePath(std::string name, |
| 253 int input_rate, | 258 int input_rate, |
| 254 int output_rate, | 259 int output_rate, |
| 255 int reverse_rate, | 260 int reverse_input_rate, |
| 261 int reverse_output_rate, |
| 256 int num_input_channels, | 262 int num_input_channels, |
| 257 int num_output_channels, | 263 int num_output_channels, |
| 258 int num_reverse_channels) { | 264 int num_reverse_input_channels, |
| 265 int num_reverse_output_channels, |
| 266 StreamDirection file_direction) { |
| 259 std::ostringstream ss; | 267 std::ostringstream ss; |
| 260 ss << name << "_i" << num_input_channels << "_" << input_rate / 1000 | 268 ss << name << "_i" << num_input_channels << "_" << input_rate / 1000 << "_ir" |
| 261 << "_r" << num_reverse_channels << "_" << reverse_rate / 1000 << "_"; | 269 << num_reverse_input_channels << "_" << reverse_input_rate / 1000 << "_"; |
| 262 if (num_output_channels == 1) { | 270 if (num_output_channels == 1) { |
| 263 ss << "mono"; | 271 ss << "mono"; |
| 264 } else if (num_output_channels == 2) { | 272 } else if (num_output_channels == 2) { |
| 265 ss << "stereo"; | 273 ss << "stereo"; |
| 266 } else { | 274 } else { |
| 267 assert(false); | 275 assert(false); |
| 268 } | 276 } |
| 269 ss << output_rate / 1000 << "_pcm"; | 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"; |
| 270 | 287 |
| 271 std::string filename = ss.str(); | 288 std::string filename = ss.str(); |
| 272 if (temp_filenames[filename].empty()) | 289 if (temp_filenames[filename].empty()) |
| 273 temp_filenames[filename] = test::TempFilename(test::OutputPath(), filename); | 290 temp_filenames[filename] = test::TempFilename(test::OutputPath(), filename); |
| 274 return temp_filenames[filename]; | 291 return temp_filenames[filename]; |
| 275 } | 292 } |
| 276 | 293 |
| 277 void ClearTempFiles() { | 294 void ClearTempFiles() { |
| 278 for (auto& kv : temp_filenames) | 295 for (auto& kv : temp_filenames) |
| 279 remove(kv.second.c_str()); | 296 remove(kv.second.c_str()); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 | 350 |
| 334 // Used to select between int and float interface tests. | 351 // Used to select between int and float interface tests. |
| 335 enum Format { | 352 enum Format { |
| 336 kIntFormat, | 353 kIntFormat, |
| 337 kFloatFormat | 354 kFloatFormat |
| 338 }; | 355 }; |
| 339 | 356 |
| 340 void Init(int sample_rate_hz, | 357 void Init(int sample_rate_hz, |
| 341 int output_sample_rate_hz, | 358 int output_sample_rate_hz, |
| 342 int reverse_sample_rate_hz, | 359 int reverse_sample_rate_hz, |
| 343 int num_reverse_channels, | |
| 344 int num_input_channels, | 360 int num_input_channels, |
| 345 int num_output_channels, | 361 int num_output_channels, |
| 362 int num_reverse_channels, |
| 346 bool open_output_file); | 363 bool open_output_file); |
| 347 void Init(AudioProcessing* ap); | 364 void Init(AudioProcessing* ap); |
| 348 void EnableAllComponents(); | 365 void EnableAllComponents(); |
| 349 bool ReadFrame(FILE* file, AudioFrame* frame); | 366 bool ReadFrame(FILE* file, AudioFrame* frame); |
| 350 bool ReadFrame(FILE* file, AudioFrame* frame, ChannelBuffer<float>* cb); | 367 bool ReadFrame(FILE* file, AudioFrame* frame, ChannelBuffer<float>* cb); |
| 351 void ReadFrameWithRewind(FILE* file, AudioFrame* frame); | 368 void ReadFrameWithRewind(FILE* file, AudioFrame* frame); |
| 352 void ReadFrameWithRewind(FILE* file, AudioFrame* frame, | 369 void ReadFrameWithRewind(FILE* file, AudioFrame* frame, |
| 353 ChannelBuffer<float>* cb); | 370 ChannelBuffer<float>* cb); |
| 354 void ProcessWithDefaultStreamParameters(AudioFrame* frame); | 371 void ProcessWithDefaultStreamParameters(AudioFrame* frame); |
| 355 void ProcessDelayVerificationTest(int delay_ms, int system_delay_ms, | 372 void ProcessDelayVerificationTest(int delay_ms, int system_delay_ms, |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 ASSERT_EQ(0, fclose(out_file_)); | 468 ASSERT_EQ(0, fclose(out_file_)); |
| 452 } | 469 } |
| 453 out_file_ = NULL; | 470 out_file_ = NULL; |
| 454 } | 471 } |
| 455 | 472 |
| 456 void ApmTest::Init(AudioProcessing* ap) { | 473 void ApmTest::Init(AudioProcessing* ap) { |
| 457 ASSERT_EQ(kNoErr, | 474 ASSERT_EQ(kNoErr, |
| 458 ap->Initialize( | 475 ap->Initialize( |
| 459 {{{frame_->sample_rate_hz_, frame_->num_channels_}, | 476 {{{frame_->sample_rate_hz_, frame_->num_channels_}, |
| 460 {output_sample_rate_hz_, num_output_channels_}, | 477 {output_sample_rate_hz_, num_output_channels_}, |
| 478 {revframe_->sample_rate_hz_, revframe_->num_channels_}, |
| 461 {revframe_->sample_rate_hz_, revframe_->num_channels_}}})); | 479 {revframe_->sample_rate_hz_, revframe_->num_channels_}}})); |
| 462 } | 480 } |
| 463 | 481 |
| 464 void ApmTest::Init(int sample_rate_hz, | 482 void ApmTest::Init(int sample_rate_hz, |
| 465 int output_sample_rate_hz, | 483 int output_sample_rate_hz, |
| 466 int reverse_sample_rate_hz, | 484 int reverse_sample_rate_hz, |
| 467 int num_input_channels, | 485 int num_input_channels, |
| 468 int num_output_channels, | 486 int num_output_channels, |
| 469 int num_reverse_channels, | 487 int num_reverse_channels, |
| 470 bool open_output_file) { | 488 bool open_output_file) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 489 } | 507 } |
| 490 filename = ResourceFilePath("near", sample_rate_hz); | 508 filename = ResourceFilePath("near", sample_rate_hz); |
| 491 near_file_ = fopen(filename.c_str(), "rb"); | 509 near_file_ = fopen(filename.c_str(), "rb"); |
| 492 ASSERT_TRUE(near_file_ != NULL) << "Could not open file " << | 510 ASSERT_TRUE(near_file_ != NULL) << "Could not open file " << |
| 493 filename << "\n"; | 511 filename << "\n"; |
| 494 | 512 |
| 495 if (open_output_file) { | 513 if (open_output_file) { |
| 496 if (out_file_) { | 514 if (out_file_) { |
| 497 ASSERT_EQ(0, fclose(out_file_)); | 515 ASSERT_EQ(0, fclose(out_file_)); |
| 498 } | 516 } |
| 499 filename = OutputFilePath("out", | 517 filename = OutputFilePath( |
| 500 sample_rate_hz, | 518 "out", sample_rate_hz, output_sample_rate_hz, reverse_sample_rate_hz, |
| 501 output_sample_rate_hz, | 519 reverse_sample_rate_hz, num_input_channels, num_output_channels, |
| 502 reverse_sample_rate_hz, | 520 num_reverse_channels, num_reverse_channels, kForward); |
| 503 num_input_channels, | |
| 504 num_output_channels, | |
| 505 num_reverse_channels); | |
| 506 out_file_ = fopen(filename.c_str(), "wb"); | 521 out_file_ = fopen(filename.c_str(), "wb"); |
| 507 ASSERT_TRUE(out_file_ != NULL) << "Could not open file " << | 522 ASSERT_TRUE(out_file_ != NULL) << "Could not open file " << |
| 508 filename << "\n"; | 523 filename << "\n"; |
| 509 } | 524 } |
| 510 } | 525 } |
| 511 | 526 |
| 512 void ApmTest::EnableAllComponents() { | 527 void ApmTest::EnableAllComponents() { |
| 513 EnableAllAPComponents(apm_.get()); | 528 EnableAllAPComponents(apm_.get()); |
| 514 } | 529 } |
| 515 | 530 |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 812 | 827 |
| 813 EXPECT_EQ(expected_return, | 828 EXPECT_EQ(expected_return, |
| 814 apm_->ProcessStream(float_cb_->channels(), input_stream, | 829 apm_->ProcessStream(float_cb_->channels(), input_stream, |
| 815 output_stream, float_cb_->channels())); | 830 output_stream, float_cb_->channels())); |
| 816 } | 831 } |
| 817 | 832 |
| 818 void ApmTest::TestChangingReverseChannels( | 833 void ApmTest::TestChangingReverseChannels( |
| 819 int num_rev_channels, | 834 int num_rev_channels, |
| 820 AudioProcessing::Error expected_return) { | 835 AudioProcessing::Error expected_return) { |
| 821 const ProcessingConfig processing_config = { | 836 const ProcessingConfig processing_config = { |
| 822 {{ frame_->sample_rate_hz_, apm_->num_input_channels() }, | 837 {{frame_->sample_rate_hz_, apm_->num_input_channels()}, |
| 823 { output_sample_rate_hz_, apm_->num_output_channels() }, | 838 {output_sample_rate_hz_, apm_->num_output_channels()}, |
| 824 { frame_->sample_rate_hz_, num_rev_channels }}}; | 839 {frame_->sample_rate_hz_, num_rev_channels}, |
| 840 {frame_->sample_rate_hz_, num_rev_channels}}}; |
| 825 | 841 |
| 826 EXPECT_EQ(expected_return, | 842 EXPECT_EQ( |
| 827 apm_->AnalyzeReverseStream(float_cb_->channels(), | 843 expected_return, |
| 828 processing_config.reverse_stream())); | 844 apm_->ProcessReverseStream( |
| 845 float_cb_->channels(), processing_config.reverse_input_stream(), |
| 846 processing_config.reverse_output_stream(), float_cb_->channels())); |
| 829 } | 847 } |
| 830 | 848 |
| 831 TEST_F(ApmTest, ChannelsInt16Interface) { | 849 TEST_F(ApmTest, ChannelsInt16Interface) { |
| 832 // Testing number of invalid and valid channels. | 850 // Testing number of invalid and valid channels. |
| 833 Init(16000, 16000, 16000, 4, 4, 4, false); | 851 Init(16000, 16000, 16000, 4, 4, 4, false); |
| 834 | 852 |
| 835 TestChangingChannelsInt16Interface(0, apm_->kBadNumberChannelsError); | 853 TestChangingChannelsInt16Interface(0, apm_->kBadNumberChannelsError); |
| 836 | 854 |
| 837 for (int i = 1; i < 4; i++) { | 855 for (int i = 1; i < 4; i++) { |
| 838 TestChangingChannelsInt16Interface(i, kNoErr); | 856 TestChangingChannelsInt16Interface(i, kNoErr); |
| (...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1524 | 1542 |
| 1525 TEST_F(ApmTest, NoProcessingWhenAllComponentsDisabled) { | 1543 TEST_F(ApmTest, NoProcessingWhenAllComponentsDisabled) { |
| 1526 for (size_t i = 0; i < kSampleRatesSize; i++) { | 1544 for (size_t i = 0; i < kSampleRatesSize; i++) { |
| 1527 Init(kSampleRates[i], kSampleRates[i], kSampleRates[i], 2, 2, 2, false); | 1545 Init(kSampleRates[i], kSampleRates[i], kSampleRates[i], 2, 2, 2, false); |
| 1528 SetFrameTo(frame_, 1000, 2000); | 1546 SetFrameTo(frame_, 1000, 2000); |
| 1529 AudioFrame frame_copy; | 1547 AudioFrame frame_copy; |
| 1530 frame_copy.CopyFrom(*frame_); | 1548 frame_copy.CopyFrom(*frame_); |
| 1531 for (int j = 0; j < 1000; j++) { | 1549 for (int j = 0; j < 1000; j++) { |
| 1532 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); | 1550 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); |
| 1533 EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy)); | 1551 EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy)); |
| 1552 EXPECT_EQ(apm_->kNoError, apm_->ProcessReverseStream(frame_)); |
| 1553 EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy)); |
| 1534 } | 1554 } |
| 1535 } | 1555 } |
| 1536 } | 1556 } |
| 1537 | 1557 |
| 1538 TEST_F(ApmTest, NoProcessingWhenAllComponentsDisabledFloat) { | 1558 TEST_F(ApmTest, NoProcessingWhenAllComponentsDisabledFloat) { |
| 1539 // Test that ProcessStream copies input to output even with no processing. | 1559 // Test that ProcessStream copies input to output even with no processing. |
| 1540 const size_t kSamples = 80; | 1560 const size_t kSamples = 80; |
| 1541 const int sample_rate = 8000; | 1561 const int sample_rate = 8000; |
| 1542 const float src[kSamples] = { | 1562 const float src[kSamples] = { |
| 1543 -1.0f, 0.0f, 1.0f | 1563 -1.0f, 0.0f, 1.0f |
| 1544 }; | 1564 }; |
| 1545 float dest[kSamples] = {}; | 1565 float dest[kSamples] = {}; |
| 1546 | 1566 |
| 1547 auto src_channels = &src[0]; | 1567 auto src_channels = &src[0]; |
| 1548 auto dest_channels = &dest[0]; | 1568 auto dest_channels = &dest[0]; |
| 1549 | 1569 |
| 1550 apm_.reset(AudioProcessing::Create()); | 1570 apm_.reset(AudioProcessing::Create()); |
| 1551 EXPECT_NOERR(apm_->ProcessStream( | 1571 EXPECT_NOERR(apm_->ProcessStream( |
| 1552 &src_channels, kSamples, sample_rate, LayoutFromChannels(1), | 1572 &src_channels, kSamples, sample_rate, LayoutFromChannels(1), |
| 1553 sample_rate, LayoutFromChannels(1), &dest_channels)); | 1573 sample_rate, LayoutFromChannels(1), &dest_channels)); |
| 1554 | 1574 |
| 1555 for (size_t i = 0; i < kSamples; ++i) { | 1575 for (size_t i = 0; i < kSamples; ++i) { |
| 1556 EXPECT_EQ(src[i], dest[i]); | 1576 EXPECT_EQ(src[i], dest[i]); |
| 1557 } | 1577 } |
| 1578 |
| 1579 // Same for ProcessReverseStream. |
| 1580 float rev_dest[kSamples] = {}; |
| 1581 auto rev_dest_channels = &rev_dest[0]; |
| 1582 |
| 1583 StreamConfig input_stream = {sample_rate, 1}; |
| 1584 StreamConfig output_stream = {sample_rate, 1}; |
| 1585 EXPECT_NOERR(apm_->ProcessReverseStream(&src_channels, input_stream, |
| 1586 output_stream, &rev_dest_channels)); |
| 1587 |
| 1588 for (size_t i = 0; i < kSamples; ++i) { |
| 1589 EXPECT_EQ(src[i], rev_dest[i]); |
| 1590 } |
| 1558 } | 1591 } |
| 1559 | 1592 |
| 1560 TEST_F(ApmTest, IdenticalInputChannelsResultInIdenticalOutputChannels) { | 1593 TEST_F(ApmTest, IdenticalInputChannelsResultInIdenticalOutputChannels) { |
| 1561 EnableAllComponents(); | 1594 EnableAllComponents(); |
| 1562 | 1595 |
| 1563 for (size_t i = 0; i < kProcessSampleRatesSize; i++) { | 1596 for (size_t i = 0; i < kProcessSampleRatesSize; i++) { |
| 1564 Init(kProcessSampleRates[i], | 1597 Init(kProcessSampleRates[i], |
| 1565 kProcessSampleRates[i], | 1598 kProcessSampleRates[i], |
| 1566 kProcessSampleRates[i], | 1599 kProcessSampleRates[i], |
| 1567 2, | 1600 2, |
| (...skipping 724 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2292 // assumed to be correct, as the used parameters are verified by other tests | 2325 // assumed to be correct, as the used parameters are verified by other tests |
| 2293 // in this collection. Primarily the reference files are all produced at | 2326 // in this collection. Primarily the reference files are all produced at |
| 2294 // "native" rates which do not involve any resampling. | 2327 // "native" rates which do not involve any resampling. |
| 2295 | 2328 |
| 2296 // Each test pass produces an output file with a particular format. The output | 2329 // Each test pass produces an output file with a particular format. The output |
| 2297 // is matched against the reference file closest to its internal processing | 2330 // is matched against the reference file closest to its internal processing |
| 2298 // format. If necessary the output is resampled back to its process format. | 2331 // format. If necessary the output is resampled back to its process format. |
| 2299 // Due to the resampling distortion, we don't expect identical results, but | 2332 // Due to the resampling distortion, we don't expect identical results, but |
| 2300 // enforce SNR thresholds which vary depending on the format. 0 is a special | 2333 // enforce SNR thresholds which vary depending on the format. 0 is a special |
| 2301 // case SNR which corresponds to inf, or zero error. | 2334 // case SNR which corresponds to inf, or zero error. |
| 2302 typedef std::tr1::tuple<int, int, int, double> AudioProcessingTestData; | 2335 typedef std::tr1::tuple<int, int, int, int, double, double> |
| 2336 AudioProcessingTestData; |
| 2303 class AudioProcessingTest | 2337 class AudioProcessingTest |
| 2304 : public testing::TestWithParam<AudioProcessingTestData> { | 2338 : public testing::TestWithParam<AudioProcessingTestData> { |
| 2305 public: | 2339 public: |
| 2306 AudioProcessingTest() | 2340 AudioProcessingTest() |
| 2307 : input_rate_(std::tr1::get<0>(GetParam())), | 2341 : input_rate_(std::tr1::get<0>(GetParam())), |
| 2308 output_rate_(std::tr1::get<1>(GetParam())), | 2342 output_rate_(std::tr1::get<1>(GetParam())), |
| 2309 reverse_rate_(std::tr1::get<2>(GetParam())), | 2343 reverse_input_rate_(std::tr1::get<2>(GetParam())), |
| 2310 expected_snr_(std::tr1::get<3>(GetParam())) {} | 2344 reverse_output_rate_(std::tr1::get<3>(GetParam())), |
| 2345 expected_snr_(std::tr1::get<4>(GetParam())), |
| 2346 expected_reverse_snr_(std::tr1::get<5>(GetParam())) {} |
| 2311 | 2347 |
| 2312 virtual ~AudioProcessingTest() {} | 2348 virtual ~AudioProcessingTest() {} |
| 2313 | 2349 |
| 2314 static void SetUpTestCase() { | 2350 static void SetUpTestCase() { |
| 2315 // Create all needed output reference files. | 2351 // Create all needed output reference files. |
| 2316 const int kNativeRates[] = {8000, 16000, 32000, 48000}; | 2352 const int kNativeRates[] = {8000, 16000, 32000, 48000}; |
| 2317 const size_t kNativeRatesSize = | 2353 const size_t kNativeRatesSize = |
| 2318 sizeof(kNativeRates) / sizeof(*kNativeRates); | 2354 sizeof(kNativeRates) / sizeof(*kNativeRates); |
| 2319 const int kNumChannels[] = {1, 2}; | 2355 const int kNumChannels[] = {1, 2}; |
| 2320 const size_t kNumChannelsSize = | 2356 const size_t kNumChannelsSize = |
| 2321 sizeof(kNumChannels) / sizeof(*kNumChannels); | 2357 sizeof(kNumChannels) / sizeof(*kNumChannels); |
| 2322 for (size_t i = 0; i < kNativeRatesSize; ++i) { | 2358 for (size_t i = 0; i < kNativeRatesSize; ++i) { |
| 2323 for (size_t j = 0; j < kNumChannelsSize; ++j) { | 2359 for (size_t j = 0; j < kNumChannelsSize; ++j) { |
| 2324 for (size_t k = 0; k < kNumChannelsSize; ++k) { | 2360 for (size_t k = 0; k < kNumChannelsSize; ++k) { |
| 2325 // The reference files always have matching input and output channels. | 2361 // The reference files always have matching input and output channels. |
| 2326 ProcessFormat(kNativeRates[i], | 2362 ProcessFormat(kNativeRates[i], kNativeRates[i], kNativeRates[i], |
| 2327 kNativeRates[i], | 2363 kNativeRates[i], kNumChannels[j], kNumChannels[j], |
| 2328 kNativeRates[i], | 2364 kNumChannels[k], kNumChannels[k], "ref"); |
| 2329 kNumChannels[j], | |
| 2330 kNumChannels[j], | |
| 2331 kNumChannels[k], | |
| 2332 "ref"); | |
| 2333 } | 2365 } |
| 2334 } | 2366 } |
| 2335 } | 2367 } |
| 2336 } | 2368 } |
| 2337 | 2369 |
| 2338 static void TearDownTestCase() { | 2370 static void TearDownTestCase() { |
| 2339 ClearTempFiles(); | 2371 ClearTempFiles(); |
| 2340 } | 2372 } |
| 2373 |
| 2341 // Runs a process pass on files with the given parameters and dumps the output | 2374 // Runs a process pass on files with the given parameters and dumps the output |
| 2342 // to a file specified with |output_file_prefix|. | 2375 // to a file specified with |output_file_prefix|. Both forward and reverse |
| 2376 // output streams are dumped. |
| 2343 static void ProcessFormat(int input_rate, | 2377 static void ProcessFormat(int input_rate, |
| 2344 int output_rate, | 2378 int output_rate, |
| 2345 int reverse_rate, | 2379 int reverse_input_rate, |
| 2380 int reverse_output_rate, |
| 2346 int num_input_channels, | 2381 int num_input_channels, |
| 2347 int num_output_channels, | 2382 int num_output_channels, |
| 2348 int num_reverse_channels, | 2383 int num_reverse_input_channels, |
| 2384 int num_reverse_output_channels, |
| 2349 std::string output_file_prefix) { | 2385 std::string output_file_prefix) { |
| 2350 Config config; | 2386 Config config; |
| 2351 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); | 2387 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); |
| 2352 rtc::scoped_ptr<AudioProcessing> ap(AudioProcessing::Create(config)); | 2388 rtc::scoped_ptr<AudioProcessing> ap(AudioProcessing::Create(config)); |
| 2353 EnableAllAPComponents(ap.get()); | 2389 EnableAllAPComponents(ap.get()); |
| 2354 ap->Initialize({{{input_rate, num_input_channels}, | |
| 2355 {output_rate, num_output_channels}, | |
| 2356 {reverse_rate, num_reverse_channels}}}); | |
| 2357 | 2390 |
| 2358 FILE* far_file = fopen(ResourceFilePath("far", reverse_rate).c_str(), "rb"); | 2391 ProcessingConfig processing_config = { |
| 2392 {{input_rate, num_input_channels}, |
| 2393 {output_rate, num_output_channels}, |
| 2394 {reverse_input_rate, num_reverse_input_channels}, |
| 2395 {reverse_output_rate, num_reverse_output_channels}}}; |
| 2396 ap->Initialize(processing_config); |
| 2397 |
| 2398 FILE* far_file = |
| 2399 fopen(ResourceFilePath("far", reverse_input_rate).c_str(), "rb"); |
| 2359 FILE* near_file = fopen(ResourceFilePath("near", input_rate).c_str(), "rb"); | 2400 FILE* near_file = fopen(ResourceFilePath("near", input_rate).c_str(), "rb"); |
| 2360 FILE* out_file = fopen(OutputFilePath(output_file_prefix, | 2401 FILE* out_file = |
| 2361 input_rate, | 2402 fopen(OutputFilePath(output_file_prefix, input_rate, output_rate, |
| 2362 output_rate, | 2403 reverse_input_rate, reverse_output_rate, |
| 2363 reverse_rate, | 2404 num_input_channels, num_output_channels, |
| 2364 num_input_channels, | 2405 num_reverse_input_channels, |
| 2365 num_output_channels, | 2406 num_reverse_output_channels, kForward).c_str(), |
| 2366 num_reverse_channels).c_str(), "wb"); | 2407 "wb"); |
| 2408 FILE* rev_out_file = |
| 2409 fopen(OutputFilePath(output_file_prefix, input_rate, output_rate, |
| 2410 reverse_input_rate, reverse_output_rate, |
| 2411 num_input_channels, num_output_channels, |
| 2412 num_reverse_input_channels, |
| 2413 num_reverse_output_channels, kReverse).c_str(), |
| 2414 "wb"); |
| 2367 ASSERT_TRUE(far_file != NULL); | 2415 ASSERT_TRUE(far_file != NULL); |
| 2368 ASSERT_TRUE(near_file != NULL); | 2416 ASSERT_TRUE(near_file != NULL); |
| 2369 ASSERT_TRUE(out_file != NULL); | 2417 ASSERT_TRUE(out_file != NULL); |
| 2418 ASSERT_TRUE(rev_out_file != NULL); |
| 2370 | 2419 |
| 2371 ChannelBuffer<float> fwd_cb(SamplesFromRate(input_rate), | 2420 ChannelBuffer<float> fwd_cb(SamplesFromRate(input_rate), |
| 2372 num_input_channels); | 2421 num_input_channels); |
| 2373 ChannelBuffer<float> rev_cb(SamplesFromRate(reverse_rate), | 2422 ChannelBuffer<float> rev_cb(SamplesFromRate(reverse_input_rate), |
| 2374 num_reverse_channels); | 2423 num_reverse_input_channels); |
| 2375 ChannelBuffer<float> out_cb(SamplesFromRate(output_rate), | 2424 ChannelBuffer<float> out_cb(SamplesFromRate(output_rate), |
| 2376 num_output_channels); | 2425 num_output_channels); |
| 2426 ChannelBuffer<float> rev_out_cb(SamplesFromRate(reverse_output_rate), |
| 2427 num_reverse_output_channels); |
| 2377 | 2428 |
| 2378 // Temporary buffers. | 2429 // Temporary buffers. |
| 2379 const int max_length = | 2430 const int max_length = |
| 2380 2 * std::max(out_cb.num_frames(), | 2431 2 * std::max(std::max(out_cb.num_frames(), rev_out_cb.num_frames()), |
| 2381 std::max(fwd_cb.num_frames(), | 2432 std::max(fwd_cb.num_frames(), rev_cb.num_frames())); |
| 2382 rev_cb.num_frames())); | |
| 2383 rtc::scoped_ptr<float[]> float_data(new float[max_length]); | 2433 rtc::scoped_ptr<float[]> float_data(new float[max_length]); |
| 2384 rtc::scoped_ptr<int16_t[]> int_data(new int16_t[max_length]); | 2434 rtc::scoped_ptr<int16_t[]> int_data(new int16_t[max_length]); |
| 2385 | 2435 |
| 2386 int analog_level = 127; | 2436 int analog_level = 127; |
| 2387 while (ReadChunk(far_file, int_data.get(), float_data.get(), &rev_cb) && | 2437 while (ReadChunk(far_file, int_data.get(), float_data.get(), &rev_cb) && |
| 2388 ReadChunk(near_file, int_data.get(), float_data.get(), &fwd_cb)) { | 2438 ReadChunk(near_file, int_data.get(), float_data.get(), &fwd_cb)) { |
| 2389 EXPECT_NOERR(ap->AnalyzeReverseStream( | 2439 EXPECT_NOERR(ap->ProcessReverseStream( |
| 2390 rev_cb.channels(), | 2440 rev_cb.channels(), processing_config.reverse_input_stream(), |
| 2391 rev_cb.num_frames(), | 2441 processing_config.reverse_output_stream(), rev_out_cb.channels())); |
| 2392 reverse_rate, | |
| 2393 LayoutFromChannels(num_reverse_channels))); | |
| 2394 | 2442 |
| 2395 EXPECT_NOERR(ap->set_stream_delay_ms(0)); | 2443 EXPECT_NOERR(ap->set_stream_delay_ms(0)); |
| 2396 ap->echo_cancellation()->set_stream_drift_samples(0); | 2444 ap->echo_cancellation()->set_stream_drift_samples(0); |
| 2397 EXPECT_NOERR(ap->gain_control()->set_stream_analog_level(analog_level)); | 2445 EXPECT_NOERR(ap->gain_control()->set_stream_analog_level(analog_level)); |
| 2398 | 2446 |
| 2399 EXPECT_NOERR(ap->ProcessStream( | 2447 EXPECT_NOERR(ap->ProcessStream( |
| 2400 fwd_cb.channels(), | 2448 fwd_cb.channels(), |
| 2401 fwd_cb.num_frames(), | 2449 fwd_cb.num_frames(), |
| 2402 input_rate, | 2450 input_rate, |
| 2403 LayoutFromChannels(num_input_channels), | 2451 LayoutFromChannels(num_input_channels), |
| 2404 output_rate, | 2452 output_rate, |
| 2405 LayoutFromChannels(num_output_channels), | 2453 LayoutFromChannels(num_output_channels), |
| 2406 out_cb.channels())); | 2454 out_cb.channels())); |
| 2407 | 2455 |
| 2408 Interleave(out_cb.channels(), | 2456 // Dump forward output to file. |
| 2409 out_cb.num_frames(), | 2457 Interleave(out_cb.channels(), out_cb.num_frames(), out_cb.num_channels(), |
| 2410 out_cb.num_channels(), | |
| 2411 float_data.get()); | 2458 float_data.get()); |
| 2412 // Dump output to file. | |
| 2413 int out_length = out_cb.num_channels() * out_cb.num_frames(); | 2459 int out_length = out_cb.num_channels() * out_cb.num_frames(); |
| 2460 |
| 2414 ASSERT_EQ(static_cast<size_t>(out_length), | 2461 ASSERT_EQ(static_cast<size_t>(out_length), |
| 2415 fwrite(float_data.get(), sizeof(float_data[0]), | 2462 fwrite(float_data.get(), sizeof(float_data[0]), |
| 2416 out_length, out_file)); | 2463 out_length, out_file)); |
| 2417 | 2464 |
| 2465 // Dump reverse output to file. |
| 2466 Interleave(rev_out_cb.channels(), rev_out_cb.num_frames(), |
| 2467 rev_out_cb.num_channels(), float_data.get()); |
| 2468 int rev_out_length = rev_out_cb.num_channels() * rev_out_cb.num_frames(); |
| 2469 |
| 2470 ASSERT_EQ(static_cast<size_t>(rev_out_length), |
| 2471 fwrite(float_data.get(), sizeof(float_data[0]), rev_out_length, |
| 2472 rev_out_file)); |
| 2473 |
| 2418 analog_level = ap->gain_control()->stream_analog_level(); | 2474 analog_level = ap->gain_control()->stream_analog_level(); |
| 2419 } | 2475 } |
| 2420 fclose(far_file); | 2476 fclose(far_file); |
| 2421 fclose(near_file); | 2477 fclose(near_file); |
| 2422 fclose(out_file); | 2478 fclose(out_file); |
| 2479 fclose(rev_out_file); |
| 2423 } | 2480 } |
| 2424 | 2481 |
| 2425 protected: | 2482 protected: |
| 2426 int input_rate_; | 2483 int input_rate_; |
| 2427 int output_rate_; | 2484 int output_rate_; |
| 2428 int reverse_rate_; | 2485 int reverse_input_rate_; |
| 2486 int reverse_output_rate_; |
| 2429 double expected_snr_; | 2487 double expected_snr_; |
| 2488 double expected_reverse_snr_; |
| 2430 }; | 2489 }; |
| 2431 | 2490 |
| 2432 TEST_P(AudioProcessingTest, Formats) { | 2491 TEST_P(AudioProcessingTest, Formats) { |
| 2433 struct ChannelFormat { | 2492 struct ChannelFormat { |
| 2434 int num_input; | 2493 int num_input; |
| 2435 int num_output; | 2494 int num_output; |
| 2436 int num_reverse; | 2495 int num_reverse_input; |
| 2496 int num_reverse_output; |
| 2437 }; | 2497 }; |
| 2438 ChannelFormat cf[] = { | 2498 ChannelFormat cf[] = { |
| 2439 {1, 1, 1}, | 2499 {1, 1, 1, 1}, |
| 2440 {1, 1, 2}, | 2500 {1, 1, 2, 1}, |
| 2441 {2, 1, 1}, | 2501 {2, 1, 1, 1}, |
| 2442 {2, 1, 2}, | 2502 {2, 1, 2, 1}, |
| 2443 {2, 2, 1}, | 2503 {2, 2, 1, 1}, |
| 2444 {2, 2, 2}, | 2504 {2, 2, 2, 2}, |
| 2445 }; | 2505 }; |
| 2446 size_t channel_format_size = sizeof(cf) / sizeof(*cf); | 2506 size_t channel_format_size = sizeof(cf) / sizeof(*cf); |
| 2447 | 2507 |
| 2448 for (size_t i = 0; i < channel_format_size; ++i) { | 2508 for (size_t i = 0; i < channel_format_size; ++i) { |
| 2449 ProcessFormat(input_rate_, | 2509 ProcessFormat(input_rate_, output_rate_, reverse_input_rate_, |
| 2450 output_rate_, | 2510 reverse_output_rate_, cf[i].num_input, cf[i].num_output, |
| 2451 reverse_rate_, | 2511 cf[i].num_reverse_input, cf[i].num_reverse_output, "out"); |
| 2452 cf[i].num_input, | 2512 |
| 2453 cf[i].num_output, | 2513 // Verify output for both directions. |
| 2454 cf[i].num_reverse, | 2514 std::vector<StreamDirection> stream_directions; |
| 2455 "out"); | 2515 stream_directions.push_back(kForward); |
| 2456 int min_ref_rate = std::min(input_rate_, output_rate_); | 2516 stream_directions.push_back(kReverse); |
| 2457 int ref_rate; | 2517 for (StreamDirection file_direction : stream_directions) { |
| 2458 | 2518 const int in_rate = file_direction ? reverse_input_rate_ : input_rate_; |
| 2459 if (min_ref_rate > 32000) { | 2519 const int out_rate = file_direction ? reverse_output_rate_ : output_rate_; |
| 2460 ref_rate = 48000; | 2520 const int out_num = |
| 2461 } else if (min_ref_rate > 16000) { | 2521 file_direction ? cf[i].num_reverse_output : cf[i].num_output; |
| 2462 ref_rate = 32000; | 2522 const double expected_snr = |
| 2463 } else if (min_ref_rate > 8000) { | 2523 file_direction ? expected_reverse_snr_ : expected_snr_; |
| 2464 ref_rate = 16000; | 2524 |
| 2465 } else { | 2525 const int min_ref_rate = std::min(in_rate, out_rate); |
| 2466 ref_rate = 8000; | 2526 int ref_rate; |
| 2527 |
| 2528 if (min_ref_rate > 32000) { |
| 2529 ref_rate = 48000; |
| 2530 } else if (min_ref_rate > 16000) { |
| 2531 ref_rate = 32000; |
| 2532 } else if (min_ref_rate > 8000) { |
| 2533 ref_rate = 16000; |
| 2534 } else { |
| 2535 ref_rate = 8000; |
| 2536 } |
| 2537 #ifdef WEBRTC_AUDIOPROC_FIXED_PROFILE |
| 2538 if (file_direction == kForward) { |
| 2539 ref_rate = std::min(ref_rate, 16000); |
| 2540 } |
| 2541 #endif |
| 2542 FILE* out_file = fopen( |
| 2543 OutputFilePath("out", input_rate_, output_rate_, reverse_input_rate_, |
| 2544 reverse_output_rate_, cf[i].num_input, |
| 2545 cf[i].num_output, cf[i].num_reverse_input, |
| 2546 cf[i].num_reverse_output, file_direction).c_str(), |
| 2547 "rb"); |
| 2548 // The reference files always have matching input and output channels. |
| 2549 FILE* ref_file = fopen( |
| 2550 OutputFilePath("ref", ref_rate, ref_rate, ref_rate, ref_rate, |
| 2551 cf[i].num_output, cf[i].num_output, |
| 2552 cf[i].num_reverse_output, cf[i].num_reverse_output, |
| 2553 file_direction).c_str(), |
| 2554 "rb"); |
| 2555 ASSERT_TRUE(out_file != NULL); |
| 2556 ASSERT_TRUE(ref_file != NULL); |
| 2557 |
| 2558 const int ref_length = SamplesFromRate(ref_rate) * out_num; |
| 2559 const int out_length = SamplesFromRate(out_rate) * out_num; |
| 2560 // Data from the reference file. |
| 2561 rtc::scoped_ptr<float[]> ref_data(new float[ref_length]); |
| 2562 // Data from the output file. |
| 2563 rtc::scoped_ptr<float[]> out_data(new float[out_length]); |
| 2564 // Data from the resampled output, in case the reference and output rates |
| 2565 // don't match. |
| 2566 rtc::scoped_ptr<float[]> cmp_data(new float[ref_length]); |
| 2567 |
| 2568 PushResampler<float> resampler; |
| 2569 resampler.InitializeIfNeeded(out_rate, ref_rate, out_num); |
| 2570 |
| 2571 // Compute the resampling delay of the output relative to the reference, |
| 2572 // to find the region over which we should search for the best SNR. |
| 2573 float expected_delay_sec = 0; |
| 2574 if (in_rate != ref_rate) { |
| 2575 // Input resampling delay. |
| 2576 expected_delay_sec += |
| 2577 PushSincResampler::AlgorithmicDelaySeconds(in_rate); |
| 2578 } |
| 2579 if (out_rate != ref_rate) { |
| 2580 // Output resampling delay. |
| 2581 expected_delay_sec += |
| 2582 PushSincResampler::AlgorithmicDelaySeconds(ref_rate); |
| 2583 // Delay of converting the output back to its processing rate for |
| 2584 // testing. |
| 2585 expected_delay_sec += |
| 2586 PushSincResampler::AlgorithmicDelaySeconds(out_rate); |
| 2587 } |
| 2588 int expected_delay = |
| 2589 floor(expected_delay_sec * ref_rate + 0.5f) * out_num; |
| 2590 |
| 2591 double variance = 0; |
| 2592 double sq_error = 0; |
| 2593 while (fread(out_data.get(), sizeof(out_data[0]), out_length, out_file) && |
| 2594 fread(ref_data.get(), sizeof(ref_data[0]), ref_length, ref_file)) { |
| 2595 float* out_ptr = out_data.get(); |
| 2596 if (out_rate != ref_rate) { |
| 2597 // Resample the output back to its internal processing rate if |
| 2598 // necssary. |
| 2599 ASSERT_EQ(ref_length, resampler.Resample(out_ptr, out_length, |
| 2600 cmp_data.get(), ref_length)); |
| 2601 out_ptr = cmp_data.get(); |
| 2602 } |
| 2603 |
| 2604 // Update the |sq_error| and |variance| accumulators with the highest |
| 2605 // SNR of reference vs output. |
| 2606 UpdateBestSNR(ref_data.get(), out_ptr, ref_length, expected_delay, |
| 2607 &variance, &sq_error); |
| 2608 } |
| 2609 |
| 2610 std::cout << "(" << input_rate_ << ", " << output_rate_ << ", " |
| 2611 << reverse_input_rate_ << ", " << reverse_output_rate_ << ", " |
| 2612 << cf[i].num_input << ", " << cf[i].num_output << ", " |
| 2613 << cf[i].num_reverse_input << ", " << cf[i].num_reverse_output |
| 2614 << ", " << file_direction << "): "; |
| 2615 if (sq_error > 0) { |
| 2616 double snr = 10 * log10(variance / sq_error); |
| 2617 EXPECT_GE(snr, expected_snr); |
| 2618 EXPECT_NE(0, expected_snr); |
| 2619 std::cout << "SNR=" << snr << " dB" << std::endl; |
| 2620 } else { |
| 2621 EXPECT_EQ(expected_snr, 0); |
| 2622 std::cout << "SNR=" |
| 2623 << "inf dB" << std::endl; |
| 2624 } |
| 2625 |
| 2626 fclose(out_file); |
| 2627 fclose(ref_file); |
| 2467 } | 2628 } |
| 2468 #ifdef WEBRTC_AUDIOPROC_FIXED_PROFILE | |
| 2469 ref_rate = std::min(ref_rate, 16000); | |
| 2470 #endif | |
| 2471 | |
| 2472 FILE* out_file = fopen(OutputFilePath("out", | |
| 2473 input_rate_, | |
| 2474 output_rate_, | |
| 2475 reverse_rate_, | |
| 2476 cf[i].num_input, | |
| 2477 cf[i].num_output, | |
| 2478 cf[i].num_reverse).c_str(), "rb"); | |
| 2479 // The reference files always have matching input and output channels. | |
| 2480 FILE* ref_file = fopen(OutputFilePath("ref", | |
| 2481 ref_rate, | |
| 2482 ref_rate, | |
| 2483 ref_rate, | |
| 2484 cf[i].num_output, | |
| 2485 cf[i].num_output, | |
| 2486 cf[i].num_reverse).c_str(), "rb"); | |
| 2487 ASSERT_TRUE(out_file != NULL); | |
| 2488 ASSERT_TRUE(ref_file != NULL); | |
| 2489 | |
| 2490 const int ref_length = SamplesFromRate(ref_rate) * cf[i].num_output; | |
| 2491 const int out_length = SamplesFromRate(output_rate_) * cf[i].num_output; | |
| 2492 // Data from the reference file. | |
| 2493 rtc::scoped_ptr<float[]> ref_data(new float[ref_length]); | |
| 2494 // Data from the output file. | |
| 2495 rtc::scoped_ptr<float[]> out_data(new float[out_length]); | |
| 2496 // Data from the resampled output, in case the reference and output rates | |
| 2497 // don't match. | |
| 2498 rtc::scoped_ptr<float[]> cmp_data(new float[ref_length]); | |
| 2499 | |
| 2500 PushResampler<float> resampler; | |
| 2501 resampler.InitializeIfNeeded(output_rate_, ref_rate, cf[i].num_output); | |
| 2502 | |
| 2503 // Compute the resampling delay of the output relative to the reference, | |
| 2504 // to find the region over which we should search for the best SNR. | |
| 2505 float expected_delay_sec = 0; | |
| 2506 if (input_rate_ != ref_rate) { | |
| 2507 // Input resampling delay. | |
| 2508 expected_delay_sec += | |
| 2509 PushSincResampler::AlgorithmicDelaySeconds(input_rate_); | |
| 2510 } | |
| 2511 if (output_rate_ != ref_rate) { | |
| 2512 // Output resampling delay. | |
| 2513 expected_delay_sec += | |
| 2514 PushSincResampler::AlgorithmicDelaySeconds(ref_rate); | |
| 2515 // Delay of converting the output back to its processing rate for testing. | |
| 2516 expected_delay_sec += | |
| 2517 PushSincResampler::AlgorithmicDelaySeconds(output_rate_); | |
| 2518 } | |
| 2519 int expected_delay = floor(expected_delay_sec * ref_rate + 0.5f) * | |
| 2520 cf[i].num_output; | |
| 2521 | |
| 2522 double variance = 0; | |
| 2523 double sq_error = 0; | |
| 2524 while (fread(out_data.get(), sizeof(out_data[0]), out_length, out_file) && | |
| 2525 fread(ref_data.get(), sizeof(ref_data[0]), ref_length, ref_file)) { | |
| 2526 float* out_ptr = out_data.get(); | |
| 2527 if (output_rate_ != ref_rate) { | |
| 2528 // Resample the output back to its internal processing rate if necssary. | |
| 2529 ASSERT_EQ(ref_length, resampler.Resample(out_ptr, | |
| 2530 out_length, | |
| 2531 cmp_data.get(), | |
| 2532 ref_length)); | |
| 2533 out_ptr = cmp_data.get(); | |
| 2534 } | |
| 2535 | |
| 2536 // Update the |sq_error| and |variance| accumulators with the highest SNR | |
| 2537 // of reference vs output. | |
| 2538 UpdateBestSNR(ref_data.get(), | |
| 2539 out_ptr, | |
| 2540 ref_length, | |
| 2541 expected_delay, | |
| 2542 &variance, | |
| 2543 &sq_error); | |
| 2544 } | |
| 2545 | |
| 2546 std::cout << "(" << input_rate_ << ", " | |
| 2547 << output_rate_ << ", " | |
| 2548 << reverse_rate_ << ", " | |
| 2549 << cf[i].num_input << ", " | |
| 2550 << cf[i].num_output << ", " | |
| 2551 << cf[i].num_reverse << "): "; | |
| 2552 if (sq_error > 0) { | |
| 2553 double snr = 10 * log10(variance / sq_error); | |
| 2554 EXPECT_GE(snr, expected_snr_); | |
| 2555 EXPECT_NE(0, expected_snr_); | |
| 2556 std::cout << "SNR=" << snr << " dB" << std::endl; | |
| 2557 } else { | |
| 2558 EXPECT_EQ(expected_snr_, 0); | |
| 2559 std::cout << "SNR=" << "inf dB" << std::endl; | |
| 2560 } | |
| 2561 | |
| 2562 fclose(out_file); | |
| 2563 fclose(ref_file); | |
| 2564 } | 2629 } |
| 2565 } | 2630 } |
| 2566 | 2631 |
| 2567 #if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE) | 2632 #if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE) |
| 2568 INSTANTIATE_TEST_CASE_P( | 2633 INSTANTIATE_TEST_CASE_P( |
| 2569 CommonFormats, AudioProcessingTest, testing::Values( | 2634 CommonFormats, |
| 2570 std::tr1::make_tuple(48000, 48000, 48000, 0), | 2635 AudioProcessingTest, |
| 2571 std::tr1::make_tuple(48000, 48000, 32000, 40), | 2636 testing::Values(std::tr1::make_tuple(48000, 48000, 48000, 48000, 0, 0), |
| 2572 std::tr1::make_tuple(48000, 48000, 16000, 40), | 2637 std::tr1::make_tuple(48000, 48000, 32000, 48000, 40, 30), |
| 2573 std::tr1::make_tuple(48000, 44100, 48000, 20), | 2638 std::tr1::make_tuple(48000, 48000, 16000, 48000, 40, 20), |
| 2574 std::tr1::make_tuple(48000, 44100, 32000, 20), | 2639 std::tr1::make_tuple(48000, 44100, 48000, 44100, 20, 20), |
| 2575 std::tr1::make_tuple(48000, 44100, 16000, 20), | 2640 std::tr1::make_tuple(48000, 44100, 32000, 44100, 20, 15), |
| 2576 std::tr1::make_tuple(48000, 32000, 48000, 30), | 2641 std::tr1::make_tuple(48000, 44100, 16000, 44100, 20, 15), |
| 2577 std::tr1::make_tuple(48000, 32000, 32000, 30), | 2642 std::tr1::make_tuple(48000, 32000, 48000, 32000, 30, 35), |
| 2578 std::tr1::make_tuple(48000, 32000, 16000, 30), | 2643 std::tr1::make_tuple(48000, 32000, 32000, 32000, 30, 0), |
| 2579 std::tr1::make_tuple(48000, 16000, 48000, 25), | 2644 std::tr1::make_tuple(48000, 32000, 16000, 32000, 30, 20), |
| 2580 std::tr1::make_tuple(48000, 16000, 32000, 25), | 2645 std::tr1::make_tuple(48000, 16000, 48000, 16000, 25, 20), |
| 2581 std::tr1::make_tuple(48000, 16000, 16000, 25), | 2646 std::tr1::make_tuple(48000, 16000, 32000, 16000, 25, 20), |
| 2582 | 2647 std::tr1::make_tuple(48000, 16000, 16000, 16000, 25, 0), |
| 2583 std::tr1::make_tuple(44100, 48000, 48000, 30), | 2648 |
| 2584 std::tr1::make_tuple(44100, 48000, 32000, 30), | 2649 std::tr1::make_tuple(44100, 48000, 48000, 48000, 30, 0), |
| 2585 std::tr1::make_tuple(44100, 48000, 16000, 30), | 2650 std::tr1::make_tuple(44100, 48000, 32000, 48000, 30, 30), |
| 2586 std::tr1::make_tuple(44100, 44100, 48000, 20), | 2651 std::tr1::make_tuple(44100, 48000, 16000, 48000, 30, 20), |
| 2587 std::tr1::make_tuple(44100, 44100, 32000, 20), | 2652 std::tr1::make_tuple(44100, 44100, 48000, 44100, 20, 20), |
| 2588 std::tr1::make_tuple(44100, 44100, 16000, 20), | 2653 std::tr1::make_tuple(44100, 44100, 32000, 44100, 20, 15), |
| 2589 std::tr1::make_tuple(44100, 32000, 48000, 30), | 2654 std::tr1::make_tuple(44100, 44100, 16000, 44100, 20, 15), |
| 2590 std::tr1::make_tuple(44100, 32000, 32000, 30), | 2655 std::tr1::make_tuple(44100, 32000, 48000, 32000, 30, 35), |
| 2591 std::tr1::make_tuple(44100, 32000, 16000, 30), | 2656 std::tr1::make_tuple(44100, 32000, 32000, 32000, 30, 0), |
| 2592 std::tr1::make_tuple(44100, 16000, 48000, 25), | 2657 std::tr1::make_tuple(44100, 32000, 16000, 32000, 30, 20), |
| 2593 std::tr1::make_tuple(44100, 16000, 32000, 25), | 2658 std::tr1::make_tuple(44100, 16000, 48000, 16000, 25, 20), |
| 2594 std::tr1::make_tuple(44100, 16000, 16000, 25), | 2659 std::tr1::make_tuple(44100, 16000, 32000, 16000, 25, 20), |
| 2595 | 2660 std::tr1::make_tuple(44100, 16000, 16000, 16000, 25, 0), |
| 2596 std::tr1::make_tuple(32000, 48000, 48000, 30), | 2661 |
| 2597 std::tr1::make_tuple(32000, 48000, 32000, 35), | 2662 std::tr1::make_tuple(32000, 48000, 48000, 48000, 30, 0), |
| 2598 std::tr1::make_tuple(32000, 48000, 16000, 30), | 2663 std::tr1::make_tuple(32000, 48000, 32000, 48000, 35, 30), |
| 2599 std::tr1::make_tuple(32000, 44100, 48000, 20), | 2664 std::tr1::make_tuple(32000, 48000, 16000, 48000, 30, 20), |
| 2600 std::tr1::make_tuple(32000, 44100, 32000, 20), | 2665 std::tr1::make_tuple(32000, 44100, 48000, 44100, 20, 20), |
| 2601 std::tr1::make_tuple(32000, 44100, 16000, 20), | 2666 std::tr1::make_tuple(32000, 44100, 32000, 44100, 20, 15), |
| 2602 std::tr1::make_tuple(32000, 32000, 48000, 40), | 2667 std::tr1::make_tuple(32000, 44100, 16000, 44100, 20, 15), |
| 2603 std::tr1::make_tuple(32000, 32000, 32000, 0), | 2668 std::tr1::make_tuple(32000, 32000, 48000, 32000, 40, 35), |
| 2604 std::tr1::make_tuple(32000, 32000, 16000, 40), | 2669 std::tr1::make_tuple(32000, 32000, 32000, 32000, 0, 0), |
| 2605 std::tr1::make_tuple(32000, 16000, 48000, 25), | 2670 std::tr1::make_tuple(32000, 32000, 16000, 32000, 40, 20), |
| 2606 std::tr1::make_tuple(32000, 16000, 32000, 25), | 2671 std::tr1::make_tuple(32000, 16000, 48000, 16000, 25, 20), |
| 2607 std::tr1::make_tuple(32000, 16000, 16000, 25), | 2672 std::tr1::make_tuple(32000, 16000, 32000, 16000, 25, 20), |
| 2608 | 2673 std::tr1::make_tuple(32000, 16000, 16000, 16000, 25, 0), |
| 2609 std::tr1::make_tuple(16000, 48000, 48000, 25), | 2674 |
| 2610 std::tr1::make_tuple(16000, 48000, 32000, 25), | 2675 std::tr1::make_tuple(16000, 48000, 48000, 48000, 25, 0), |
| 2611 std::tr1::make_tuple(16000, 48000, 16000, 25), | 2676 std::tr1::make_tuple(16000, 48000, 32000, 48000, 25, 30), |
| 2612 std::tr1::make_tuple(16000, 44100, 48000, 15), | 2677 std::tr1::make_tuple(16000, 48000, 16000, 48000, 25, 20), |
| 2613 std::tr1::make_tuple(16000, 44100, 32000, 15), | 2678 std::tr1::make_tuple(16000, 44100, 48000, 44100, 15, 20), |
| 2614 std::tr1::make_tuple(16000, 44100, 16000, 15), | 2679 std::tr1::make_tuple(16000, 44100, 32000, 44100, 15, 15), |
| 2615 std::tr1::make_tuple(16000, 32000, 48000, 25), | 2680 std::tr1::make_tuple(16000, 44100, 16000, 44100, 15, 15), |
| 2616 std::tr1::make_tuple(16000, 32000, 32000, 25), | 2681 std::tr1::make_tuple(16000, 32000, 48000, 32000, 25, 35), |
| 2617 std::tr1::make_tuple(16000, 32000, 16000, 25), | 2682 std::tr1::make_tuple(16000, 32000, 32000, 32000, 25, 0), |
| 2618 std::tr1::make_tuple(16000, 16000, 48000, 40), | 2683 std::tr1::make_tuple(16000, 32000, 16000, 32000, 25, 20), |
| 2619 std::tr1::make_tuple(16000, 16000, 32000, 50), | 2684 std::tr1::make_tuple(16000, 16000, 48000, 16000, 40, 20), |
| 2620 std::tr1::make_tuple(16000, 16000, 16000, 0))); | 2685 std::tr1::make_tuple(16000, 16000, 32000, 16000, 50, 20), |
| 2686 std::tr1::make_tuple(16000, 16000, 16000, 16000, 0, 0))); |
| 2621 | 2687 |
| 2622 #elif defined(WEBRTC_AUDIOPROC_FIXED_PROFILE) | 2688 #elif defined(WEBRTC_AUDIOPROC_FIXED_PROFILE) |
| 2623 INSTANTIATE_TEST_CASE_P( | 2689 INSTANTIATE_TEST_CASE_P( |
| 2624 CommonFormats, AudioProcessingTest, testing::Values( | 2690 CommonFormats, |
| 2625 std::tr1::make_tuple(48000, 48000, 48000, 20), | 2691 AudioProcessingTest, |
| 2626 std::tr1::make_tuple(48000, 48000, 32000, 20), | 2692 testing::Values(std::tr1::make_tuple(48000, 48000, 48000, 48000, 20, 0), |
| 2627 std::tr1::make_tuple(48000, 48000, 16000, 20), | 2693 std::tr1::make_tuple(48000, 48000, 32000, 48000, 20, 30), |
| 2628 std::tr1::make_tuple(48000, 44100, 48000, 15), | 2694 std::tr1::make_tuple(48000, 48000, 16000, 48000, 20, 20), |
| 2629 std::tr1::make_tuple(48000, 44100, 32000, 15), | 2695 std::tr1::make_tuple(48000, 44100, 48000, 44100, 15, 20), |
| 2630 std::tr1::make_tuple(48000, 44100, 16000, 15), | 2696 std::tr1::make_tuple(48000, 44100, 32000, 44100, 15, 15), |
| 2631 std::tr1::make_tuple(48000, 32000, 48000, 20), | 2697 std::tr1::make_tuple(48000, 44100, 16000, 44100, 15, 15), |
| 2632 std::tr1::make_tuple(48000, 32000, 32000, 20), | 2698 std::tr1::make_tuple(48000, 32000, 48000, 32000, 20, 35), |
| 2633 std::tr1::make_tuple(48000, 32000, 16000, 20), | 2699 std::tr1::make_tuple(48000, 32000, 32000, 32000, 20, 0), |
| 2634 std::tr1::make_tuple(48000, 16000, 48000, 20), | 2700 std::tr1::make_tuple(48000, 32000, 16000, 32000, 20, 20), |
| 2635 std::tr1::make_tuple(48000, 16000, 32000, 20), | 2701 std::tr1::make_tuple(48000, 16000, 48000, 16000, 20, 20), |
| 2636 std::tr1::make_tuple(48000, 16000, 16000, 20), | 2702 std::tr1::make_tuple(48000, 16000, 32000, 16000, 20, 20), |
| 2637 | 2703 std::tr1::make_tuple(48000, 16000, 16000, 16000, 20, 0), |
| 2638 std::tr1::make_tuple(44100, 48000, 48000, 20), | 2704 |
| 2639 std::tr1::make_tuple(44100, 48000, 32000, 20), | 2705 std::tr1::make_tuple(44100, 48000, 48000, 48000, 20, 0), |
| 2640 std::tr1::make_tuple(44100, 48000, 16000, 20), | 2706 std::tr1::make_tuple(44100, 48000, 32000, 48000, 20, 30), |
| 2641 std::tr1::make_tuple(44100, 44100, 48000, 15), | 2707 std::tr1::make_tuple(44100, 48000, 16000, 48000, 20, 20), |
| 2642 std::tr1::make_tuple(44100, 44100, 32000, 15), | 2708 std::tr1::make_tuple(44100, 44100, 48000, 44100, 15, 20), |
| 2643 std::tr1::make_tuple(44100, 44100, 16000, 15), | 2709 std::tr1::make_tuple(44100, 44100, 32000, 44100, 15, 15), |
| 2644 std::tr1::make_tuple(44100, 32000, 48000, 20), | 2710 std::tr1::make_tuple(44100, 44100, 16000, 44100, 15, 15), |
| 2645 std::tr1::make_tuple(44100, 32000, 32000, 20), | 2711 std::tr1::make_tuple(44100, 32000, 48000, 32000, 20, 35), |
| 2646 std::tr1::make_tuple(44100, 32000, 16000, 20), | 2712 std::tr1::make_tuple(44100, 32000, 32000, 32000, 20, 0), |
| 2647 std::tr1::make_tuple(44100, 16000, 48000, 20), | 2713 std::tr1::make_tuple(44100, 32000, 16000, 32000, 20, 20), |
| 2648 std::tr1::make_tuple(44100, 16000, 32000, 20), | 2714 std::tr1::make_tuple(44100, 16000, 48000, 16000, 20, 20), |
| 2649 std::tr1::make_tuple(44100, 16000, 16000, 20), | 2715 std::tr1::make_tuple(44100, 16000, 32000, 16000, 20, 20), |
| 2650 | 2716 std::tr1::make_tuple(44100, 16000, 16000, 16000, 20, 0), |
| 2651 std::tr1::make_tuple(32000, 48000, 48000, 20), | 2717 |
| 2652 std::tr1::make_tuple(32000, 48000, 32000, 20), | 2718 std::tr1::make_tuple(32000, 48000, 48000, 48000, 20, 0), |
| 2653 std::tr1::make_tuple(32000, 48000, 16000, 20), | 2719 std::tr1::make_tuple(32000, 48000, 32000, 48000, 20, 30), |
| 2654 std::tr1::make_tuple(32000, 44100, 48000, 15), | 2720 std::tr1::make_tuple(32000, 48000, 16000, 48000, 20, 20), |
| 2655 std::tr1::make_tuple(32000, 44100, 32000, 15), | 2721 std::tr1::make_tuple(32000, 44100, 48000, 44100, 15, 20), |
| 2656 std::tr1::make_tuple(32000, 44100, 16000, 15), | 2722 std::tr1::make_tuple(32000, 44100, 32000, 44100, 15, 15), |
| 2657 std::tr1::make_tuple(32000, 32000, 48000, 20), | 2723 std::tr1::make_tuple(32000, 44100, 16000, 44100, 15, 15), |
| 2658 std::tr1::make_tuple(32000, 32000, 32000, 20), | 2724 std::tr1::make_tuple(32000, 32000, 48000, 32000, 20, 35), |
| 2659 std::tr1::make_tuple(32000, 32000, 16000, 20), | 2725 std::tr1::make_tuple(32000, 32000, 32000, 32000, 20, 0), |
| 2660 std::tr1::make_tuple(32000, 16000, 48000, 20), | 2726 std::tr1::make_tuple(32000, 32000, 16000, 32000, 20, 20), |
| 2661 std::tr1::make_tuple(32000, 16000, 32000, 20), | 2727 std::tr1::make_tuple(32000, 16000, 48000, 16000, 20, 20), |
| 2662 std::tr1::make_tuple(32000, 16000, 16000, 20), | 2728 std::tr1::make_tuple(32000, 16000, 32000, 16000, 20, 20), |
| 2663 | 2729 std::tr1::make_tuple(32000, 16000, 16000, 16000, 20, 0), |
| 2664 std::tr1::make_tuple(16000, 48000, 48000, 25), | 2730 |
| 2665 std::tr1::make_tuple(16000, 48000, 32000, 25), | 2731 std::tr1::make_tuple(16000, 48000, 48000, 48000, 25, 0), |
| 2666 std::tr1::make_tuple(16000, 48000, 16000, 25), | 2732 std::tr1::make_tuple(16000, 48000, 32000, 48000, 25, 30), |
| 2667 std::tr1::make_tuple(16000, 44100, 48000, 15), | 2733 std::tr1::make_tuple(16000, 48000, 16000, 48000, 25, 20), |
| 2668 std::tr1::make_tuple(16000, 44100, 32000, 15), | 2734 std::tr1::make_tuple(16000, 44100, 48000, 44100, 15, 20), |
| 2669 std::tr1::make_tuple(16000, 44100, 16000, 15), | 2735 std::tr1::make_tuple(16000, 44100, 32000, 44100, 15, 15), |
| 2670 std::tr1::make_tuple(16000, 32000, 48000, 25), | 2736 std::tr1::make_tuple(16000, 44100, 16000, 44100, 15, 15), |
| 2671 std::tr1::make_tuple(16000, 32000, 32000, 25), | 2737 std::tr1::make_tuple(16000, 32000, 48000, 32000, 25, 35), |
| 2672 std::tr1::make_tuple(16000, 32000, 16000, 25), | 2738 std::tr1::make_tuple(16000, 32000, 32000, 32000, 25, 0), |
| 2673 std::tr1::make_tuple(16000, 16000, 48000, 35), | 2739 std::tr1::make_tuple(16000, 32000, 16000, 32000, 25, 20), |
| 2674 std::tr1::make_tuple(16000, 16000, 32000, 40), | 2740 std::tr1::make_tuple(16000, 16000, 48000, 16000, 35, 20), |
| 2675 std::tr1::make_tuple(16000, 16000, 16000, 0))); | 2741 std::tr1::make_tuple(16000, 16000, 32000, 16000, 40, 20), |
| 2742 std::tr1::make_tuple(16000, 16000, 16000, 16000, 0, 0))); |
| 2676 #endif | 2743 #endif |
| 2677 | 2744 |
| 2678 // TODO(henrike): re-implement functionality lost when removing the old main | 2745 // TODO(henrike): re-implement functionality lost when removing the old main |
| 2679 // function. See | 2746 // function. See |
| 2680 // https://code.google.com/p/webrtc/issues/detail?id=1981 | 2747 // https://code.google.com/p/webrtc/issues/detail?id=1981 |
| 2681 | 2748 |
| 2682 } // namespace | 2749 } // namespace |
| 2683 } // namespace webrtc | 2750 } // namespace webrtc |
| OLD | NEW |