blob: 97d69aea3fa7679cf8b3842aae3e87fcc160a60d [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 <string>
15
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "modules/audio_processing/transient/daubechies_8_wavelet_coeffs.h"
17#include "modules/audio_processing/transient/file_utils.h"
Jonas Olsson366a50c2018-09-06 13:41:30 +020018#include "rtc_base/strings/string_builder.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"
Steve Anton10542f22019-01-11 09:11:00 -080021#include "test/testsupport/file_utils.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};
Yves Gerey665174f2018-06-19 15:03:05 +020033 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.org788acd12014-12-15 09:41:24 +000037 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öme2976c82016-01-04 22:44:05 +010068#if defined(WEBRTC_IOS)
69TEST(WPDTreeTest, DISABLED_CorrectnessBasedOnMatlabFiles) {
70#else
71TEST(WPDTreeTest, CorrectnessBasedOnMatlabFiles) {
72#endif
pbos@webrtc.org788acd12014-12-15 09:41:24 +000073 // 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 Gerey665174f2018-06-19 15:03:05 +020079 WPDTree tree(kTestBufferSize, kDaubechies8HighPassCoefficients,
80 kDaubechies8LowPassCoefficients, kDaubechies8CoefficientsLength,
pbos@webrtc.org788acd12014-12-15 09:41:24 +000081 kLevels);
82 // Allocate and open all matlab and out files.
Niels Möller5a6ae022019-01-21 11:59:10 +010083 FileWrapper matlab_files_data[kLeaves];
84 FileWrapper out_files_data[kLeaves];
pbos@webrtc.org788acd12014-12-15 09:41:24 +000085
86 for (int i = 0; i < kLeaves; ++i) {
87 // Matlab files.
Jonas Olsson366a50c2018-09-06 13:41:30 +020088 rtc::StringBuilder matlab_stream;
pbos@webrtc.org788acd12014-12-15 09:41:24 +000089 matlab_stream << "audio_processing/transient/wpd" << i;
90 std::string matlab_string = test::ResourcePath(matlab_stream.str(), "dat");
Niels Möller5a6ae022019-01-21 11:59:10 +010091 matlab_files_data[i] = FileWrapper::OpenReadOnly(matlab_string.c_str());
pbos@webrtc.org788acd12014-12-15 09:41:24 +000092
Niels Möller5a6ae022019-01-21 11:59:10 +010093 bool file_opened = matlab_files_data[i].is_open();
pbos@webrtc.org788acd12014-12-15 09:41:24 +000094 ASSERT_TRUE(file_opened) << "File could not be opened.\n" << matlab_string;
95
96 // Out files.
Jonas Olsson366a50c2018-09-06 13:41:30 +020097 rtc::StringBuilder out_stream;
pbos@webrtc.org788acd12014-12-15 09:41:24 +000098 out_stream << test::OutputPath() << "wpd_" << i << ".out";
99 std::string out_string = out_stream.str();
100
Niels Möller5a6ae022019-01-21 11:59:10 +0100101 out_files_data[i] = FileWrapper::OpenWriteOnly(out_string.c_str());
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000102
Niels Möller5a6ae022019-01-21 11:59:10 +0100103 file_opened = out_files_data[i].is_open();
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000104 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öller5a6ae022019-01-21 11:59:10 +0100111 FileWrapper test_file = FileWrapper::OpenReadOnly(test_file_name.c_str());
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000112
Niels Möller5a6ae022019-01-21 11:59:10 +0100113 bool file_opened = test_file.is_open();
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000114 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öller5a6ae022019-01-21 11:59:10 +0100126 size_t file_samples_read =
127 ReadInt16FromFileToFloatBuffer(&test_file, kTestBufferSize, test_buffer);
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000128 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 Gerey665174f2018-06-19 15:03:05 +0200143 size_t matlab_samples_read = ReadDoubleBufferFromFile(
Niels Möller5a6ae022019-01-21 11:59:10 +0100144 &matlab_files_data[i], kLeavesSamples, matlab_buffer);
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000145
146 ASSERT_EQ(kLeavesSamples, matlab_samples_read)
147 << "Matlab test files are malformed.\n"
Jonas Olssonb2b20312020-01-14 12:11:31 +0100148 "File: 3_"
149 << i;
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000150 // Get output data from the corresponding node
151 const float* node_data = tree.NodeAt(kLevels, i)->data();
152 // Compare with matlab files.
153 for (size_t j = 0; j < kLeavesSamples; ++j) {
154 EXPECT_NEAR(matlab_buffer[j], node_data[j], kTolerance)
155 << "\nLeaf: " << i << "\nSample: " << j
156 << "\nFrame: " << frames_read - 1;
157 }
158
159 // Write results to out files.
Niels Möller5a6ae022019-01-21 11:59:10 +0100160 WriteFloatBufferToFile(&out_files_data[i], kLeavesSamples, node_data);
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000161 }
162
163 // Read next buffer from the PCM test file.
Yves Gerey665174f2018-06-19 15:03:05 +0200164 file_samples_read = ReadInt16FromFileToFloatBuffer(
Niels Möller5a6ae022019-01-21 11:59:10 +0100165 &test_file, kTestBufferSize, test_buffer);
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000166 }
167
168 // Close all matlab and out files.
169 for (int i = 0; i < kLeaves; ++i) {
Niels Möller5a6ae022019-01-21 11:59:10 +0100170 matlab_files_data[i].Close();
171 out_files_data[i].Close();
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000172 }
173
Niels Möller5a6ae022019-01-21 11:59:10 +0100174 test_file.Close();
pbos@webrtc.org788acd12014-12-15 09:41:24 +0000175}
176
177} // namespace webrtc