Chris@1573
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@1573
|
2
|
Chris@1573
|
3 /*
|
Chris@1573
|
4 Sonic Visualiser
|
Chris@1573
|
5 An audio file viewer and annotation editor.
|
Chris@1573
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@1573
|
7
|
Chris@1573
|
8 This program is free software; you can redistribute it and/or
|
Chris@1573
|
9 modify it under the terms of the GNU General Public License as
|
Chris@1573
|
10 published by the Free Software Foundation; either version 2 of the
|
Chris@1573
|
11 License, or (at your option) any later version. See the file
|
Chris@1573
|
12 COPYING included with this distribution for more information.
|
Chris@1573
|
13 */
|
Chris@1573
|
14
|
Chris@1573
|
15 #ifndef TEST_MOVING_MEDIAN_H
|
Chris@1573
|
16 #define TEST_MOVING_MEDIAN_H
|
Chris@1573
|
17
|
Chris@1573
|
18 #include "../MovingMedian.h"
|
Chris@1573
|
19
|
Chris@1573
|
20 #include <QObject>
|
Chris@1573
|
21 #include <QtTest>
|
Chris@1573
|
22 #include <QDir>
|
Chris@1573
|
23
|
Chris@1573
|
24 #include <iostream>
|
Chris@1573
|
25
|
Chris@1573
|
26 using namespace std;
|
Chris@1573
|
27
|
Chris@1573
|
28 class TestMovingMedian : public QObject
|
Chris@1573
|
29 {
|
Chris@1573
|
30 Q_OBJECT
|
Chris@1573
|
31
|
Chris@1573
|
32 template <typename T>
|
Chris@1573
|
33 void checkExpected(const vector<T> &output,
|
Chris@1573
|
34 const vector<T> &expected) {
|
Chris@1573
|
35 if (output.size() != expected.size()) {
|
Chris@1574
|
36 std::cerr << "ERROR: output array size " << output.size()
|
Chris@1574
|
37 << " differs from expected size " << expected.size()
|
Chris@1574
|
38 << std::endl;
|
Chris@1573
|
39 }
|
Chris@1573
|
40 for (int i = 0; i < int(output.size()); ++i) {
|
Chris@1573
|
41 if (output[i] != expected[i]) {
|
Chris@1574
|
42 std::cerr << "ERROR: Value at index " << i
|
Chris@1574
|
43 << " in output array differs from expected"
|
Chris@1574
|
44 << std::endl;
|
Chris@1574
|
45 std::cerr << "Output: ";
|
Chris@1574
|
46 for (auto v: output) std::cerr << v << " ";
|
Chris@1574
|
47 std::cerr << "\nExpected: ";
|
Chris@1574
|
48 for (auto v: expected) std::cerr << v << " ";
|
Chris@1574
|
49 std::cerr << std::endl;
|
Chris@1573
|
50 break;
|
Chris@1573
|
51 }
|
Chris@1573
|
52 }
|
Chris@1573
|
53 QCOMPARE(output, expected);
|
Chris@1573
|
54 }
|
Chris@1573
|
55
|
Chris@1573
|
56 template <typename T>
|
Chris@1573
|
57 void testFixed(int n,
|
Chris@1573
|
58 const vector<T> &input,
|
Chris@1573
|
59 const vector<T> &expected,
|
Chris@1573
|
60 double percentile = 50.0) {
|
Chris@1573
|
61 vector<T> output;
|
Chris@1573
|
62 MovingMedian<T> mm(n, percentile);
|
Chris@1573
|
63 for (auto v: input) {
|
Chris@1573
|
64 mm.push(v);
|
Chris@1573
|
65 mm.checkIntegrity();
|
Chris@1573
|
66 output.push_back(mm.get());
|
Chris@1573
|
67 }
|
Chris@1573
|
68 mm.checkIntegrity();
|
Chris@1573
|
69 checkExpected<T>(output, expected);
|
Chris@1573
|
70 }
|
Chris@1573
|
71
|
Chris@1573
|
72 private slots:
|
Chris@1573
|
73
|
Chris@1573
|
74 void empty() {
|
Chris@1573
|
75 MovingMedian<double> mm(3);
|
Chris@1573
|
76 QCOMPARE(mm.get(), 0.0);
|
Chris@1573
|
77 }
|
Chris@1573
|
78
|
Chris@1573
|
79 void zeros() {
|
Chris@1573
|
80 vector<double> input { 0.0, 0.0, 0.0, 0.0, 0.0 };
|
Chris@1573
|
81 vector<double> expected { 0.0, 0.0, 0.0, 0.0, 0.0 };
|
Chris@1573
|
82 testFixed<double>(3, input, expected);
|
Chris@1573
|
83 }
|
Chris@1573
|
84
|
Chris@1573
|
85 void ascending() {
|
Chris@1573
|
86 vector<double> input { 1.0, 2.0, 3.0, 4.0, 5.0 };
|
Chris@1573
|
87 vector<double> expected { 0.0, 1.0, 2.0, 3.0, 4.0 };
|
Chris@1573
|
88 testFixed<double>(3, input, expected);
|
Chris@1573
|
89 }
|
Chris@1573
|
90
|
Chris@1573
|
91 void ascendingInt() {
|
Chris@1573
|
92 vector<int> input { 1, 2, 3, 4, 5 };
|
Chris@1573
|
93 vector<int> expected { 0, 1, 2, 3, 4 };
|
Chris@1573
|
94 testFixed<int>(3, input, expected);
|
Chris@1573
|
95 }
|
Chris@1573
|
96
|
Chris@1573
|
97 void descending() {
|
Chris@1573
|
98 vector<double> input { 5.0, 4.0, 3.0, 2.0, 1.0 };
|
Chris@1573
|
99 vector<double> expected { 0.0, 4.0, 4.0, 3.0, 2.0 };
|
Chris@1573
|
100 testFixed<double>(3, input, expected);
|
Chris@1573
|
101 }
|
Chris@1573
|
102
|
Chris@1573
|
103 void descendingInt() {
|
Chris@1573
|
104 vector<int> input { 5, 4, 3, 2, 1 };
|
Chris@1573
|
105 vector<int> expected { 0, 4, 4, 3, 2 };
|
Chris@1573
|
106 testFixed<int>(3, input, expected);
|
Chris@1573
|
107 }
|
Chris@1573
|
108
|
Chris@1573
|
109 void duplicates() {
|
Chris@1573
|
110 vector<double> input { 2.0, 2.0, 3.0, 4.0, 3.0 };
|
Chris@1573
|
111 vector<double> expected { 0.0, 2.0, 2.0, 3.0, 3.0 };
|
Chris@1573
|
112 testFixed<double>(3, input, expected);
|
Chris@1573
|
113 }
|
Chris@1573
|
114
|
Chris@1573
|
115 void percentile10() {
|
Chris@1573
|
116 vector<double> input { 1.0, 2.0, 3.0, 4.0, 5.0 };
|
Chris@1573
|
117 vector<double> expected { 0.0, 0.0, 1.0, 2.0, 3.0 };
|
Chris@1573
|
118 testFixed<double>(3, input, expected, 10);
|
Chris@1573
|
119 }
|
Chris@1573
|
120
|
Chris@1573
|
121 void percentile90() {
|
Chris@1573
|
122 vector<double> input { 1.0, 2.0, 3.0, 4.0, 5.0 };
|
Chris@1573
|
123 vector<double> expected { 1.0, 2.0, 3.0, 4.0, 5.0 };
|
Chris@1573
|
124 testFixed<double>(3, input, expected, 90);
|
Chris@1573
|
125 }
|
Chris@1573
|
126
|
Chris@1573
|
127 void even() {
|
Chris@1573
|
128 vector<double> input { 5.0, 4.0, 3.0, 2.0, 1.0 };
|
Chris@1573
|
129 vector<double> expected { 0.0, 4.0, 4.0, 4.0, 3.0 };
|
Chris@1573
|
130 testFixed<double>(4, input, expected);
|
Chris@1573
|
131 }
|
Chris@1573
|
132
|
Chris@1573
|
133 void growing() {
|
Chris@1573
|
134 vector<double> input { 2.0, 4.0, 3.0, 2.5, 2.5, 3.0, 1.0, 2.0, 1.0, 0.0 };
|
Chris@1573
|
135 vector<double> expected { 2.0, 4.0, 4.0, 3.0, 2.5, 2.5, 2.5, 2.5, 2.0, 1.0 };
|
Chris@1573
|
136 vector<double> output;
|
Chris@1573
|
137 MovingMedian<double> mm(1);
|
Chris@1573
|
138 for (int i = 0; i < int(input.size()); ++i) {
|
Chris@1573
|
139 // sizes 1, 1, 2, 2, 3, 3, 4, 4, 5, 5
|
Chris@1573
|
140 int sz = i/2 + 1;
|
Chris@1573
|
141 mm.resize(sz);
|
Chris@1573
|
142 QCOMPARE(mm.size(), sz);
|
Chris@1573
|
143 mm.push(input[i]);
|
Chris@1573
|
144 mm.checkIntegrity();
|
Chris@1573
|
145 output.push_back(mm.get());
|
Chris@1573
|
146 }
|
Chris@1573
|
147 mm.checkIntegrity();
|
Chris@1573
|
148 checkExpected<double>(output, expected);
|
Chris@1573
|
149 }
|
Chris@1573
|
150
|
Chris@1573
|
151 void shrinking() {
|
Chris@1573
|
152 vector<double> input { 2.0, 4.0, 3.0, 2.5, 2.5, 3.0, 1.0, 2.0, 1.0, 0.0 };
|
Chris@1573
|
153 vector<double> expected { 0.0, 0.0, 3.0, 3.0, 2.5, 2.5, 3.0, 2.0, 1.0, 0.0 };
|
Chris@1573
|
154 vector<double> output;
|
Chris@1573
|
155 MovingMedian<double> mm(99);
|
Chris@1573
|
156 for (int i = 0; i < int(input.size()); ++i) {
|
Chris@1573
|
157 // sizes 5, 5, 4, 4, 3, 3, 2, 2, 1, 1
|
Chris@1573
|
158 int sz = 5 - i/2;
|
Chris@1573
|
159 mm.resize(sz);
|
Chris@1573
|
160 QCOMPARE(mm.size(), sz);
|
Chris@1573
|
161 mm.push(input[i]);
|
Chris@1573
|
162 mm.checkIntegrity();
|
Chris@1573
|
163 output.push_back(mm.get());
|
Chris@1573
|
164 }
|
Chris@1573
|
165 mm.checkIntegrity();
|
Chris@1573
|
166 checkExpected<double>(output, expected);
|
Chris@1573
|
167 }
|
Chris@1573
|
168 };
|
Chris@1573
|
169
|
Chris@1573
|
170 #endif
|