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 11#include "webrtc/modules/audio_processing/transient/wpd_tree.h" 12 13#include <sstream> 14#include <string> 15 16#include "testing/gtest/include/gtest/gtest.h" 17#include "webrtc/base/scoped_ptr.h" 18#include "webrtc/modules/audio_processing/transient/daubechies_8_wavelet_coeffs.h" 19#include "webrtc/modules/audio_processing/transient/file_utils.h" 20#include "webrtc/system_wrappers/include/file_wrapper.h" 21#include "webrtc/test/testsupport/fileutils.h" 22 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. 71#if defined(WEBRTC_IOS) 72TEST(WPDTreeTest, DISABLED_CorrectnessBasedOnMatlabFiles) { 73#else 74TEST(WPDTreeTest, CorrectnessBasedOnMatlabFiles) { 75#endif 76 // 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. 88 rtc::scoped_ptr<FileWrapper> matlab_files_data[kLeaves]; 89 rtc::scoped_ptr<FileWrapper> out_files_data[kLeaves]; 90 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"); 98 matlab_files_data[i]->OpenFile(matlab_string.c_str(), 99 true, // Read only. 100 false, // No loop. 101 false); // No text. 102 103 bool file_opened = matlab_files_data[i]->Open(); 104 ASSERT_TRUE(file_opened) << "File could not be opened.\n" << matlab_string; 105 106 // Out files. 107 out_files_data[i].reset(FileWrapper::Create()); 108 109 std::ostringstream out_stream; 110 out_stream << test::OutputPath() << "wpd_" << i << ".out"; 111 std::string out_string = out_stream.str(); 112 113 out_files_data[i]->OpenFile(out_string.c_str(), 114 false, // Write mode. 115 false, // No loop. 116 false); // No text. 117 118 file_opened = out_files_data[i]->Open(); 119 ASSERT_TRUE(file_opened) << "File could not be opened.\n" << out_string; 120 } 121 122 // Prepare the test file. 123 std::string test_file_name = test::ResourcePath( 124 "audio_processing/transient/ajm-macbook-1-spke16m", "pcm"); 125 126 rtc::scoped_ptr<FileWrapper> test_file(FileWrapper::Create()); 127 128 test_file->OpenFile(test_file_name.c_str(), 129 true, // Read only. 130 false, // No loop. 131 false); // No text. 132 133 bool file_opened = test_file->Open(); 134 ASSERT_TRUE(file_opened) << "File could not be opened.\n" << test_file_name; 135 136 float test_buffer[kTestBufferSize]; 137 138 // Only the first frames of the audio file are tested. The matlab files also 139 // only contains information about the first frames. 140 const size_t kMaxFramesToTest = 100; 141 const float kTolerance = 0.03f; 142 143 size_t frames_read = 0; 144 145 // Read first buffer from the PCM test file. 146 size_t file_samples_read = ReadInt16FromFileToFloatBuffer(test_file.get(), 147 kTestBufferSize, 148 test_buffer); 149 while (file_samples_read > 0 && frames_read < kMaxFramesToTest) { 150 ++frames_read; 151 152 if (file_samples_read < kTestBufferSize) { 153 // Pad the rest of the buffer with zeros. 154 for (size_t i = file_samples_read; i < kTestBufferSize; ++i) { 155 test_buffer[i] = 0.0; 156 } 157 } 158 tree.Update(test_buffer, kTestBufferSize); 159 double matlab_buffer[kTestBufferSize]; 160 161 // Compare results with data from the matlab test files. 162 for (int i = 0; i < kLeaves; ++i) { 163 // Compare data values 164 size_t matlab_samples_read = 165 ReadDoubleBufferFromFile(matlab_files_data[i].get(), 166 kLeavesSamples, 167 matlab_buffer); 168 169 ASSERT_EQ(kLeavesSamples, matlab_samples_read) 170 << "Matlab test files are malformed.\n" 171 << "File: 3_" << i; 172 // Get output data from the corresponding node 173 const float* node_data = tree.NodeAt(kLevels, i)->data(); 174 // Compare with matlab files. 175 for (size_t j = 0; j < kLeavesSamples; ++j) { 176 EXPECT_NEAR(matlab_buffer[j], node_data[j], kTolerance) 177 << "\nLeaf: " << i << "\nSample: " << j 178 << "\nFrame: " << frames_read - 1; 179 } 180 181 // Write results to out files. 182 WriteFloatBufferToFile(out_files_data[i].get(), 183 kLeavesSamples, 184 node_data); 185 } 186 187 // Read next buffer from the PCM test file. 188 file_samples_read = ReadInt16FromFileToFloatBuffer(test_file.get(), 189 kTestBufferSize, 190 test_buffer); 191 } 192 193 // Close all matlab and out files. 194 for (int i = 0; i < kLeaves; ++i) { 195 matlab_files_data[i]->CloseFile(); 196 out_files_data[i]->CloseFile(); 197 } 198 199 test_file->CloseFile(); 200} 201 202} // namespace webrtc 203