comparison base/test/TestMovingMedian.h @ 1577:50fe6d6a5ef0

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