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