blob: 02c7f51db58ad76bac7461833579f565eaa1cb08 [file] [log] [blame]
pbos@webrtc.org788acd12014-12-15 09:41:24 +00001/*
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 Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_processing/transient/wpd_tree.h"
pbos@webrtc.org788acd12014-12-15 09:41:24 +000012
kwiberg85d8bb02016-02-16 20:39:36 -080013#include <memory>
pbos@webrtc.org788acd12014-12-15 09:41:24 +000014#include <sstream>
15#include <string>
16
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "modules/audio_processing/transient/daubechies_8_wavelet_coeffs.h"
18#include "modules/audio_processing/transient/file_utils.h"
Karl Wiberg6a4d4112018-03-23 10:39:34 +010019#include "rtc_base/system/file_wrapper.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "test/gtest.h"
21#include "test/testsupport/fileutils.h"
pbos@webrtc.org788acd12014-12-15 09:41:24 +000022
23namespace webrtc {
24
25TEST(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};
33 const size_t kTestCoefficientsLength = sizeof(test_coefficients) /
34 sizeof(test_coefficients[0]);
35 WPDTree tree(kTestBufferSize,
36 test_coefficients,
37 test_coefficients,
38 kTestCoefficientsLength,
39 kLevels);
40 ASSERT_EQ(kExpectedNumberOfNodes, tree.num_nodes());
41 // Checks for NodeAt(level, index).
42 int nodes_at_level = 0;
43 for (int level = 0; level <= kLevels; ++level) {
44 nodes_at_level = 1 << level;
45 for (int i = 0; i < nodes_at_level; ++i) {
46 ASSERT_TRUE(NULL != tree.NodeAt(level, i));
47 }
48 // Out of bounds.
49 EXPECT_EQ(NULL, tree.NodeAt(level, -1));
50 EXPECT_EQ(NULL, tree.NodeAt(level, -12));
51 EXPECT_EQ(NULL, tree.NodeAt(level, nodes_at_level));
52 EXPECT_EQ(NULL, tree.NodeAt(level, nodes_at_level + 5));
53 }
54 // Out of bounds.
55 EXPECT_EQ(NULL, tree.NodeAt(-1, 0));
56 EXPECT_EQ(NULL, tree.NodeAt(-12, 0));
57 EXPECT_EQ(NULL, tree.NodeAt(kLevels + 1, 0));
58 EXPECT_EQ(NULL, tree.NodeAt(kLevels + 5, 0));
59 // Checks for Update().
60 EXPECT_EQ(0, tree.Update(test_buffer, kTestBufferSize));
61 EXPECT_EQ(-1, tree.Update(NULL, kTestBufferSize));
62 EXPECT_EQ(-1, tree.Update(test_buffer, kTestBufferSize - 1));
63}
64
65// This test is for the correctness of the tree.
66// Checks the results from the Matlab equivalent, it is done comparing the
67// results that are stored in the output files from Matlab.
68// It also writes the results in its own set of files in the out directory.
69// Matlab and output files contain all the results in double precision (Little
70// endian) appended.
Peter Boströme2976c82016-01-04 22:44:05 +010071#if defined(WEBRTC_IOS)
72TEST(WPDTreeTest, DISABLED_CorrectnessBasedOnMatlabFiles) {
73#else
74TEST(WPDTreeTest, CorrectnessBasedOnMatlabFiles) {
75#endif
pbos@webrtc.org788acd12014-12-15 09:41:24 +000076 // 10 ms at 16000 Hz.
77 const size_t kTestBufferSize = 160;
78 const int kLevels = 3;
79 const int kLeaves = 1 << kLevels;
80 const size_t kLeavesSamples = kTestBufferSize >> kLevels;
81 // Create tree with Discrete Meyer Wavelet Coefficients.
82 WPDTree tree(kTestBufferSize,
83 kDaubechies8HighPassCoefficients,
84 kDaubechies8LowPassCoefficients,
85 kDaubechies8CoefficientsLength,
86 kLevels);
87 // Allocate and open all matlab and out files.
kwiberg85d8bb02016-02-16 20:39:36 -080088 std::unique_ptr<FileWrapper> matlab_files_data[kLeaves];
89 std::unique_ptr<FileWrapper> out_files_data[kLeaves];
pbos@webrtc.org788acd12014-12-15 09:41:24 +000090
91 for (int i = 0; i < kLeaves; ++i) {
92 // Matlab files.
93 matlab_files_data[i].reset(FileWrapper::Create());
94
95 std::ostringstream matlab_stream;
96 matlab_stream << "audio_processing/transient/wpd" << i;
97 std::string matlab_string = test::ResourcePath(matlab_stream.str(), "dat");
tommia6219cc2016-06-15 10:30:14 -070098 matlab_files_data[i]->OpenFile(matlab_string.c_str(), true); // Read only.
pbos@webrtc.org788acd12014-12-15 09:41:24 +000099
tommia6219cc2016-06-15 10:30:14 -0700100 bool file_opened = matlab_files_data[i]->is_open();
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000101 ASSERT_TRUE(file_opened) << "File could not be opened.\n" << matlab_string;
102
103 // Out files.
104 out_files_data[i].reset(FileWrapper::Create());
105
106 std::ostringstream out_stream;
107 out_stream << test::OutputPath() << "wpd_" << i << ".out";
108 std::string out_string = out_stream.str();
109
tommia6219cc2016-06-15 10:30:14 -0700110 out_files_data[i]->OpenFile(out_string.c_str(), false); // Write mode.
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000111
tommia6219cc2016-06-15 10:30:14 -0700112 file_opened = out_files_data[i]->is_open();
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000113 ASSERT_TRUE(file_opened) << "File could not be opened.\n" << out_string;
114 }
115
116 // Prepare the test file.
117 std::string test_file_name = test::ResourcePath(
118 "audio_processing/transient/ajm-macbook-1-spke16m", "pcm");
119
kwiberg85d8bb02016-02-16 20:39:36 -0800120 std::unique_ptr<FileWrapper> test_file(FileWrapper::Create());
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000121
tommia6219cc2016-06-15 10:30:14 -0700122 test_file->OpenFile(test_file_name.c_str(), true); // Read only.
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000123
tommia6219cc2016-06-15 10:30:14 -0700124 bool file_opened = test_file->is_open();
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000125 ASSERT_TRUE(file_opened) << "File could not be opened.\n" << test_file_name;
126
127 float test_buffer[kTestBufferSize];
128
129 // Only the first frames of the audio file are tested. The matlab files also
130 // only contains information about the first frames.
131 const size_t kMaxFramesToTest = 100;
132 const float kTolerance = 0.03f;
133
134 size_t frames_read = 0;
135
136 // Read first buffer from the PCM test file.
137 size_t file_samples_read = ReadInt16FromFileToFloatBuffer(test_file.get(),
138 kTestBufferSize,
139 test_buffer);
140 while (file_samples_read > 0 && frames_read < kMaxFramesToTest) {
141 ++frames_read;
142
143 if (file_samples_read < kTestBufferSize) {
144 // Pad the rest of the buffer with zeros.
145 for (size_t i = file_samples_read; i < kTestBufferSize; ++i) {
146 test_buffer[i] = 0.0;
147 }
148 }
149 tree.Update(test_buffer, kTestBufferSize);
150 double matlab_buffer[kTestBufferSize];
151
152 // Compare results with data from the matlab test files.
153 for (int i = 0; i < kLeaves; ++i) {
154 // Compare data values
155 size_t matlab_samples_read =
156 ReadDoubleBufferFromFile(matlab_files_data[i].get(),
157 kLeavesSamples,
158 matlab_buffer);
159
160 ASSERT_EQ(kLeavesSamples, matlab_samples_read)
161 << "Matlab test files are malformed.\n"
162 << "File: 3_" << i;
163 // Get output data from the corresponding node
164 const float* node_data = tree.NodeAt(kLevels, i)->data();
165 // Compare with matlab files.
166 for (size_t j = 0; j < kLeavesSamples; ++j) {
167 EXPECT_NEAR(matlab_buffer[j], node_data[j], kTolerance)
168 << "\nLeaf: " << i << "\nSample: " << j
169 << "\nFrame: " << frames_read - 1;
170 }
171
172 // Write results to out files.
173 WriteFloatBufferToFile(out_files_data[i].get(),
174 kLeavesSamples,
175 node_data);
176 }
177
178 // Read next buffer from the PCM test file.
179 file_samples_read = ReadInt16FromFileToFloatBuffer(test_file.get(),
180 kTestBufferSize,
181 test_buffer);
182 }
183
184 // Close all matlab and out files.
185 for (int i = 0; i < kLeaves; ++i) {
186 matlab_files_data[i]->CloseFile();
187 out_files_data[i]->CloseFile();
188 }
189
190 test_file->CloseFile();
191}
192
193} // namespace webrtc