pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2013 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 | |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 11 | #include "modules/audio_processing/transient/wpd_tree.h" |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 12 | |
kwiberg | 85d8bb0 | 2016-02-16 20:39:36 -0800 | [diff] [blame] | 13 | #include <memory> |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 14 | #include <string> |
| 15 | |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 16 | #include "modules/audio_processing/transient/daubechies_8_wavelet_coeffs.h" |
| 17 | #include "modules/audio_processing/transient/file_utils.h" |
Jonas Olsson | 366a50c | 2018-09-06 13:41:30 +0200 | [diff] [blame] | 18 | #include "rtc_base/strings/string_builder.h" |
Karl Wiberg | 6a4d411 | 2018-03-23 10:39:34 +0100 | [diff] [blame] | 19 | #include "rtc_base/system/file_wrapper.h" |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 20 | #include "test/gtest.h" |
Steve Anton | 10542f2 | 2019-01-11 09:11:00 -0800 | [diff] [blame] | 21 | #include "test/testsupport/file_utils.h" |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 22 | |
| 23 | namespace webrtc { |
| 24 | |
| 25 | TEST(WPDTreeTest, Construction) { |
| 26 | const size_t kTestBufferSize = 100; |
| 27 | const int kLevels = 5; |
| 28 | const int kExpectedNumberOfNodes = (1 << (kLevels + 1)) - 1; |
| 29 | |
| 30 | float test_buffer[kTestBufferSize]; |
| 31 | memset(test_buffer, 0.f, kTestBufferSize * sizeof(*test_buffer)); |
| 32 | float test_coefficients[] = {1.f, 2.f, 3.f, 4.f, 5.f}; |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 33 | const size_t kTestCoefficientsLength = |
| 34 | sizeof(test_coefficients) / sizeof(test_coefficients[0]); |
| 35 | WPDTree tree(kTestBufferSize, test_coefficients, test_coefficients, |
| 36 | kTestCoefficientsLength, kLevels); |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 37 | ASSERT_EQ(kExpectedNumberOfNodes, tree.num_nodes()); |
| 38 | // Checks for NodeAt(level, index). |
| 39 | int nodes_at_level = 0; |
| 40 | for (int level = 0; level <= kLevels; ++level) { |
| 41 | nodes_at_level = 1 << level; |
| 42 | for (int i = 0; i < nodes_at_level; ++i) { |
| 43 | ASSERT_TRUE(NULL != tree.NodeAt(level, i)); |
| 44 | } |
| 45 | // Out of bounds. |
| 46 | EXPECT_EQ(NULL, tree.NodeAt(level, -1)); |
| 47 | EXPECT_EQ(NULL, tree.NodeAt(level, -12)); |
| 48 | EXPECT_EQ(NULL, tree.NodeAt(level, nodes_at_level)); |
| 49 | EXPECT_EQ(NULL, tree.NodeAt(level, nodes_at_level + 5)); |
| 50 | } |
| 51 | // Out of bounds. |
| 52 | EXPECT_EQ(NULL, tree.NodeAt(-1, 0)); |
| 53 | EXPECT_EQ(NULL, tree.NodeAt(-12, 0)); |
| 54 | EXPECT_EQ(NULL, tree.NodeAt(kLevels + 1, 0)); |
| 55 | EXPECT_EQ(NULL, tree.NodeAt(kLevels + 5, 0)); |
| 56 | // Checks for Update(). |
| 57 | EXPECT_EQ(0, tree.Update(test_buffer, kTestBufferSize)); |
| 58 | EXPECT_EQ(-1, tree.Update(NULL, kTestBufferSize)); |
| 59 | EXPECT_EQ(-1, tree.Update(test_buffer, kTestBufferSize - 1)); |
| 60 | } |
| 61 | |
| 62 | // This test is for the correctness of the tree. |
| 63 | // Checks the results from the Matlab equivalent, it is done comparing the |
| 64 | // results that are stored in the output files from Matlab. |
| 65 | // It also writes the results in its own set of files in the out directory. |
| 66 | // Matlab and output files contain all the results in double precision (Little |
| 67 | // endian) appended. |
Peter Boström | e2976c8 | 2016-01-04 22:44:05 +0100 | [diff] [blame] | 68 | #if defined(WEBRTC_IOS) |
| 69 | TEST(WPDTreeTest, DISABLED_CorrectnessBasedOnMatlabFiles) { |
| 70 | #else |
| 71 | TEST(WPDTreeTest, CorrectnessBasedOnMatlabFiles) { |
| 72 | #endif |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 73 | // 10 ms at 16000 Hz. |
| 74 | const size_t kTestBufferSize = 160; |
| 75 | const int kLevels = 3; |
| 76 | const int kLeaves = 1 << kLevels; |
| 77 | const size_t kLeavesSamples = kTestBufferSize >> kLevels; |
| 78 | // Create tree with Discrete Meyer Wavelet Coefficients. |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 79 | WPDTree tree(kTestBufferSize, kDaubechies8HighPassCoefficients, |
| 80 | kDaubechies8LowPassCoefficients, kDaubechies8CoefficientsLength, |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 81 | kLevels); |
| 82 | // Allocate and open all matlab and out files. |
Niels Möller | 5a6ae02 | 2019-01-21 11:59:10 +0100 | [diff] [blame] | 83 | FileWrapper matlab_files_data[kLeaves]; |
| 84 | FileWrapper out_files_data[kLeaves]; |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 85 | |
| 86 | for (int i = 0; i < kLeaves; ++i) { |
| 87 | // Matlab files. |
Jonas Olsson | 366a50c | 2018-09-06 13:41:30 +0200 | [diff] [blame] | 88 | rtc::StringBuilder matlab_stream; |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 89 | matlab_stream << "audio_processing/transient/wpd" << i; |
| 90 | std::string matlab_string = test::ResourcePath(matlab_stream.str(), "dat"); |
Niels Möller | 5a6ae02 | 2019-01-21 11:59:10 +0100 | [diff] [blame] | 91 | matlab_files_data[i] = FileWrapper::OpenReadOnly(matlab_string.c_str()); |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 92 | |
Niels Möller | 5a6ae02 | 2019-01-21 11:59:10 +0100 | [diff] [blame] | 93 | bool file_opened = matlab_files_data[i].is_open(); |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 94 | ASSERT_TRUE(file_opened) << "File could not be opened.\n" << matlab_string; |
| 95 | |
| 96 | // Out files. |
Jonas Olsson | 366a50c | 2018-09-06 13:41:30 +0200 | [diff] [blame] | 97 | rtc::StringBuilder out_stream; |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 98 | out_stream << test::OutputPath() << "wpd_" << i << ".out"; |
| 99 | std::string out_string = out_stream.str(); |
| 100 | |
Niels Möller | 5a6ae02 | 2019-01-21 11:59:10 +0100 | [diff] [blame] | 101 | out_files_data[i] = FileWrapper::OpenWriteOnly(out_string.c_str()); |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 102 | |
Niels Möller | 5a6ae02 | 2019-01-21 11:59:10 +0100 | [diff] [blame] | 103 | file_opened = out_files_data[i].is_open(); |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 104 | ASSERT_TRUE(file_opened) << "File could not be opened.\n" << out_string; |
| 105 | } |
| 106 | |
| 107 | // Prepare the test file. |
| 108 | std::string test_file_name = test::ResourcePath( |
| 109 | "audio_processing/transient/ajm-macbook-1-spke16m", "pcm"); |
| 110 | |
Niels Möller | 5a6ae02 | 2019-01-21 11:59:10 +0100 | [diff] [blame] | 111 | FileWrapper test_file = FileWrapper::OpenReadOnly(test_file_name.c_str()); |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 112 | |
Niels Möller | 5a6ae02 | 2019-01-21 11:59:10 +0100 | [diff] [blame] | 113 | bool file_opened = test_file.is_open(); |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 114 | ASSERT_TRUE(file_opened) << "File could not be opened.\n" << test_file_name; |
| 115 | |
| 116 | float test_buffer[kTestBufferSize]; |
| 117 | |
| 118 | // Only the first frames of the audio file are tested. The matlab files also |
| 119 | // only contains information about the first frames. |
| 120 | const size_t kMaxFramesToTest = 100; |
| 121 | const float kTolerance = 0.03f; |
| 122 | |
| 123 | size_t frames_read = 0; |
| 124 | |
| 125 | // Read first buffer from the PCM test file. |
Niels Möller | 5a6ae02 | 2019-01-21 11:59:10 +0100 | [diff] [blame] | 126 | size_t file_samples_read = |
| 127 | ReadInt16FromFileToFloatBuffer(&test_file, kTestBufferSize, test_buffer); |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 128 | while (file_samples_read > 0 && frames_read < kMaxFramesToTest) { |
| 129 | ++frames_read; |
| 130 | |
| 131 | if (file_samples_read < kTestBufferSize) { |
| 132 | // Pad the rest of the buffer with zeros. |
| 133 | for (size_t i = file_samples_read; i < kTestBufferSize; ++i) { |
| 134 | test_buffer[i] = 0.0; |
| 135 | } |
| 136 | } |
| 137 | tree.Update(test_buffer, kTestBufferSize); |
| 138 | double matlab_buffer[kTestBufferSize]; |
| 139 | |
| 140 | // Compare results with data from the matlab test files. |
| 141 | for (int i = 0; i < kLeaves; ++i) { |
| 142 | // Compare data values |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 143 | size_t matlab_samples_read = ReadDoubleBufferFromFile( |
Niels Möller | 5a6ae02 | 2019-01-21 11:59:10 +0100 | [diff] [blame] | 144 | &matlab_files_data[i], kLeavesSamples, matlab_buffer); |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 145 | |
| 146 | ASSERT_EQ(kLeavesSamples, matlab_samples_read) |
| 147 | << "Matlab test files are malformed.\n" |
| 148 | << "File: 3_" << i; |
| 149 | // Get output data from the corresponding node |
| 150 | const float* node_data = tree.NodeAt(kLevels, i)->data(); |
| 151 | // Compare with matlab files. |
| 152 | for (size_t j = 0; j < kLeavesSamples; ++j) { |
| 153 | EXPECT_NEAR(matlab_buffer[j], node_data[j], kTolerance) |
| 154 | << "\nLeaf: " << i << "\nSample: " << j |
| 155 | << "\nFrame: " << frames_read - 1; |
| 156 | } |
| 157 | |
| 158 | // Write results to out files. |
Niels Möller | 5a6ae02 | 2019-01-21 11:59:10 +0100 | [diff] [blame] | 159 | WriteFloatBufferToFile(&out_files_data[i], kLeavesSamples, node_data); |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 160 | } |
| 161 | |
| 162 | // Read next buffer from the PCM test file. |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 163 | file_samples_read = ReadInt16FromFileToFloatBuffer( |
Niels Möller | 5a6ae02 | 2019-01-21 11:59:10 +0100 | [diff] [blame] | 164 | &test_file, kTestBufferSize, test_buffer); |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 165 | } |
| 166 | |
| 167 | // Close all matlab and out files. |
| 168 | for (int i = 0; i < kLeaves; ++i) { |
Niels Möller | 5a6ae02 | 2019-01-21 11:59:10 +0100 | [diff] [blame] | 169 | matlab_files_data[i].Close(); |
| 170 | out_files_data[i].Close(); |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 171 | } |
| 172 | |
Niels Möller | 5a6ae02 | 2019-01-21 11:59:10 +0100 | [diff] [blame] | 173 | test_file.Close(); |
pbos@webrtc.org | 788acd1 | 2014-12-15 09:41:24 +0000 | [diff] [blame] | 174 | } |
| 175 | |
| 176 | } // namespace webrtc |