comparison base/test/TestMovingMedian.h @ 1573:f04038819c26 spectrogramparam

Introduce & make use of faster MovingMedian class (now with resize capability)
author Chris Cannam
date Thu, 08 Nov 2018 15:02:30 +0000
parents
children cfcfec216c21
comparison
equal deleted inserted replaced
1572:c36ffc195988 1573:f04038819c26
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 cerr << "ERROR: output array size " << output.size()
37 << " differs from expected size " << expected.size() << endl;
38 }
39 for (int i = 0; i < int(output.size()); ++i) {
40 if (output[i] != expected[i]) {
41 cerr << "ERROR: Value at index " << i
42 << " in output array differs from expected" << endl;
43 cerr << "Output: ";
44 for (auto v: output) cerr << v << " ";
45 cerr << "\nExpected: ";
46 for (auto v: expected) cerr << v << " ";
47 cerr << endl;
48 break;
49 }
50 }
51 QCOMPARE(output, expected);
52 }
53
54 template <typename T>
55 void testFixed(int n,
56 const vector<T> &input,
57 const vector<T> &expected,
58 double percentile = 50.0) {
59 vector<T> output;
60 MovingMedian<T> mm(n, percentile);
61 for (auto v: input) {
62 mm.push(v);
63 mm.checkIntegrity();
64 output.push_back(mm.get());
65 }
66 mm.checkIntegrity();
67 checkExpected<T>(output, expected);
68 }
69
70 private slots:
71
72 void empty() {
73 MovingMedian<double> mm(3);
74 QCOMPARE(mm.get(), 0.0);
75 }
76
77 void zeros() {
78 vector<double> input { 0.0, 0.0, 0.0, 0.0, 0.0 };
79 vector<double> expected { 0.0, 0.0, 0.0, 0.0, 0.0 };
80 testFixed<double>(3, input, expected);
81 }
82
83 void ascending() {
84 vector<double> input { 1.0, 2.0, 3.0, 4.0, 5.0 };
85 vector<double> expected { 0.0, 1.0, 2.0, 3.0, 4.0 };
86 testFixed<double>(3, input, expected);
87 }
88
89 void ascendingInt() {
90 vector<int> input { 1, 2, 3, 4, 5 };
91 vector<int> expected { 0, 1, 2, 3, 4 };
92 testFixed<int>(3, input, expected);
93 }
94
95 void descending() {
96 vector<double> input { 5.0, 4.0, 3.0, 2.0, 1.0 };
97 vector<double> expected { 0.0, 4.0, 4.0, 3.0, 2.0 };
98 testFixed<double>(3, input, expected);
99 }
100
101 void descendingInt() {
102 vector<int> input { 5, 4, 3, 2, 1 };
103 vector<int> expected { 0, 4, 4, 3, 2 };
104 testFixed<int>(3, input, expected);
105 }
106
107 void duplicates() {
108 vector<double> input { 2.0, 2.0, 3.0, 4.0, 3.0 };
109 vector<double> expected { 0.0, 2.0, 2.0, 3.0, 3.0 };
110 testFixed<double>(3, input, expected);
111 }
112
113 void percentile10() {
114 vector<double> input { 1.0, 2.0, 3.0, 4.0, 5.0 };
115 vector<double> expected { 0.0, 0.0, 1.0, 2.0, 3.0 };
116 testFixed<double>(3, input, expected, 10);
117 }
118
119 void percentile90() {
120 vector<double> input { 1.0, 2.0, 3.0, 4.0, 5.0 };
121 vector<double> expected { 1.0, 2.0, 3.0, 4.0, 5.0 };
122 testFixed<double>(3, input, expected, 90);
123 }
124
125 void even() {
126 vector<double> input { 5.0, 4.0, 3.0, 2.0, 1.0 };
127 vector<double> expected { 0.0, 4.0, 4.0, 4.0, 3.0 };
128 testFixed<double>(4, input, expected);
129 }
130
131 void growing() {
132 vector<double> input { 2.0, 4.0, 3.0, 2.5, 2.5, 3.0, 1.0, 2.0, 1.0, 0.0 };
133 vector<double> expected { 2.0, 4.0, 4.0, 3.0, 2.5, 2.5, 2.5, 2.5, 2.0, 1.0 };
134 vector<double> output;
135 MovingMedian<double> mm(1);
136 for (int i = 0; i < int(input.size()); ++i) {
137 // sizes 1, 1, 2, 2, 3, 3, 4, 4, 5, 5
138 int sz = i/2 + 1;
139 mm.resize(sz);
140 QCOMPARE(mm.size(), sz);
141 mm.push(input[i]);
142 mm.checkIntegrity();
143 output.push_back(mm.get());
144 }
145 mm.checkIntegrity();
146 checkExpected<double>(output, expected);
147 }
148
149 void shrinking() {
150 vector<double> input { 2.0, 4.0, 3.0, 2.5, 2.5, 3.0, 1.0, 2.0, 1.0, 0.0 };
151 vector<double> expected { 0.0, 0.0, 3.0, 3.0, 2.5, 2.5, 3.0, 2.0, 1.0, 0.0 };
152 vector<double> output;
153 MovingMedian<double> mm(99);
154 for (int i = 0; i < int(input.size()); ++i) {
155 // sizes 5, 5, 4, 4, 3, 3, 2, 2, 1, 1
156 int sz = 5 - i/2;
157 mm.resize(sz);
158 QCOMPARE(mm.size(), sz);
159 mm.push(input[i]);
160 mm.checkIntegrity();
161 output.push_back(mm.get());
162 }
163 mm.checkIntegrity();
164 checkExpected<double>(output, expected);
165 }
166 };
167
168 #endif