• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
23 namespace webrtc {
24 
TEST(WPDTreeTest,Construction)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};
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)
TEST(WPDTreeTest,DISABLED_CorrectnessBasedOnMatlabFiles)72 TEST(WPDTreeTest, DISABLED_CorrectnessBasedOnMatlabFiles) {
73 #else
74 TEST(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