Chris@1265
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@1265
|
2
|
Chris@1265
|
3 /*
|
Chris@1265
|
4 Sonic Visualiser
|
Chris@1265
|
5 An audio file viewer and annotation editor.
|
Chris@1265
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@1265
|
7
|
Chris@1265
|
8 This program is free software; you can redistribute it and/or
|
Chris@1265
|
9 modify it under the terms of the GNU General Public License as
|
Chris@1265
|
10 published by the Free Software Foundation; either version 2 of the
|
Chris@1265
|
11 License, or (at your option) any later version. See the file
|
Chris@1265
|
12 COPYING included with this distribution for more information.
|
Chris@1265
|
13 */
|
Chris@1265
|
14
|
Chris@1265
|
15 #ifndef TEST_COLUMN_OP_H
|
Chris@1265
|
16 #define TEST_COLUMN_OP_H
|
Chris@1265
|
17
|
Chris@1265
|
18 #include "../ColumnOp.h"
|
Chris@1265
|
19
|
Chris@1265
|
20 #include <QObject>
|
Chris@1265
|
21 #include <QtTest>
|
Chris@1265
|
22 #include <QDir>
|
Chris@1265
|
23
|
Chris@1265
|
24 #include <iostream>
|
Chris@1265
|
25
|
Chris@1304
|
26 //#define REPORT 1
|
Chris@1304
|
27
|
Chris@1265
|
28 using namespace std;
|
Chris@1265
|
29
|
Chris@1265
|
30 class TestColumnOp : public QObject
|
Chris@1265
|
31 {
|
Chris@1265
|
32 Q_OBJECT
|
Chris@1265
|
33
|
Chris@1265
|
34 typedef ColumnOp C;
|
Chris@1265
|
35 typedef ColumnOp::Column Column;
|
Chris@1266
|
36 typedef vector<double> BinMapping;
|
Chris@1266
|
37
|
Chris@1269
|
38 #ifdef REPORT
|
Chris@1266
|
39 template <typename T>
|
Chris@1266
|
40 void report(vector<T> v) {
|
Chris@1266
|
41 cerr << "Vector is: [ ";
|
Chris@1266
|
42 for (int i = 0; i < int(v.size()); ++i) {
|
Chris@1266
|
43 if (i > 0) cerr << ", ";
|
Chris@1266
|
44 cerr << v[i];
|
Chris@1266
|
45 }
|
Chris@1266
|
46 cerr << " ]\n";
|
Chris@1266
|
47 }
|
Chris@1269
|
48 #else
|
Chris@1269
|
49 template <typename T>
|
Chris@1269
|
50 void report(vector<T> ) { }
|
Chris@1269
|
51 #endif
|
Chris@1266
|
52
|
Chris@1265
|
53 private slots:
|
Chris@1265
|
54 void applyGain() {
|
Chris@1265
|
55 QCOMPARE(C::applyGain({}, 1.0), Column());
|
Chris@1265
|
56 Column c { 1, 2, 3, -4, 5, 6 };
|
Chris@1265
|
57 Column actual(C::applyGain(c, 1.5));
|
Chris@1380
|
58 Column expected { 1.5f, 3, 4.5f, -6, 7.5f, 9 };
|
Chris@1265
|
59 QCOMPARE(actual, expected);
|
Chris@1265
|
60 actual = C::applyGain(c, 1.0);
|
Chris@1265
|
61 QCOMPARE(actual, c);
|
Chris@1265
|
62 actual = C::applyGain(c, 0.0);
|
Chris@1265
|
63 expected = { 0, 0, 0, 0, 0, 0 };
|
Chris@1265
|
64 QCOMPARE(actual, expected);
|
Chris@1265
|
65 }
|
Chris@1265
|
66
|
Chris@1265
|
67 void fftScale() {
|
Chris@1265
|
68 QCOMPARE(C::fftScale({}, 2.0), Column());
|
Chris@1265
|
69 Column c { 1, 2, 3, -4, 5 };
|
Chris@1265
|
70 Column actual(C::fftScale(c, 8));
|
Chris@1380
|
71 Column expected { 0.25f, 0.5f, 0.75f, -1, 1.25f };
|
Chris@1265
|
72 QCOMPARE(actual, expected);
|
Chris@1265
|
73 }
|
Chris@1265
|
74
|
Chris@1265
|
75 void isPeak_null() {
|
Chris@1265
|
76 QVERIFY(!C::isPeak({}, 0));
|
Chris@1265
|
77 QVERIFY(!C::isPeak({}, 1));
|
Chris@1265
|
78 QVERIFY(!C::isPeak({}, -1));
|
Chris@1265
|
79 }
|
Chris@1265
|
80
|
Chris@1265
|
81 void isPeak_obvious() {
|
Chris@1380
|
82 Column c { 0.4f, 0.5f, 0.3f };
|
Chris@1265
|
83 QVERIFY(!C::isPeak(c, 0));
|
Chris@1265
|
84 QVERIFY(C::isPeak(c, 1));
|
Chris@1265
|
85 QVERIFY(!C::isPeak(c, 2));
|
Chris@1265
|
86 }
|
Chris@1265
|
87
|
Chris@1265
|
88 void isPeak_edges() {
|
Chris@1380
|
89 Column c { 0.5f, 0.4f, 0.3f };
|
Chris@1265
|
90 QVERIFY(C::isPeak(c, 0));
|
Chris@1265
|
91 QVERIFY(!C::isPeak(c, 1));
|
Chris@1265
|
92 QVERIFY(!C::isPeak(c, 2));
|
Chris@1265
|
93 QVERIFY(!C::isPeak(c, 3));
|
Chris@1265
|
94 QVERIFY(!C::isPeak(c, -1));
|
Chris@1380
|
95 c = { 1.4f, 1.5f };
|
Chris@1265
|
96 QVERIFY(!C::isPeak(c, 0));
|
Chris@1265
|
97 QVERIFY(C::isPeak(c, 1));
|
Chris@1265
|
98 }
|
Chris@1265
|
99
|
Chris@1265
|
100 void isPeak_flat() {
|
Chris@1380
|
101 Column c { 0.0f, 0.0f, 0.0f };
|
Chris@1265
|
102 QVERIFY(C::isPeak(c, 0));
|
Chris@1265
|
103 QVERIFY(!C::isPeak(c, 1));
|
Chris@1265
|
104 QVERIFY(!C::isPeak(c, 2));
|
Chris@1265
|
105 }
|
Chris@1265
|
106
|
Chris@1265
|
107 void isPeak_mixedSign() {
|
Chris@1380
|
108 Column c { 0.4f, -0.5f, -0.3f, -0.6f, 0.1f, -0.3f };
|
Chris@1265
|
109 QVERIFY(C::isPeak(c, 0));
|
Chris@1265
|
110 QVERIFY(!C::isPeak(c, 1));
|
Chris@1265
|
111 QVERIFY(C::isPeak(c, 2));
|
Chris@1265
|
112 QVERIFY(!C::isPeak(c, 3));
|
Chris@1265
|
113 QVERIFY(C::isPeak(c, 4));
|
Chris@1265
|
114 QVERIFY(!C::isPeak(c, 5));
|
Chris@1265
|
115 }
|
Chris@1265
|
116
|
Chris@1265
|
117 void isPeak_duplicate() {
|
Chris@1380
|
118 Column c({ 0.5f, 0.5f, 0.4f, 0.4f });
|
Chris@1265
|
119 QVERIFY(C::isPeak(c, 0));
|
Chris@1265
|
120 QVERIFY(!C::isPeak(c, 1));
|
Chris@1265
|
121 QVERIFY(!C::isPeak(c, 2));
|
Chris@1265
|
122 QVERIFY(!C::isPeak(c, 3));
|
Chris@1380
|
123 c = { 0.4f, 0.4f, 0.5f, 0.5f };
|
Chris@1265
|
124 QVERIFY(C::isPeak(c, 0)); // counterintuitive but necessary
|
Chris@1265
|
125 QVERIFY(!C::isPeak(c, 1));
|
Chris@1265
|
126 QVERIFY(C::isPeak(c, 2));
|
Chris@1265
|
127 QVERIFY(!C::isPeak(c, 3));
|
Chris@1265
|
128 }
|
Chris@1265
|
129
|
Chris@1265
|
130 void peakPick() {
|
Chris@1265
|
131 QCOMPARE(C::peakPick({}), Column());
|
Chris@1380
|
132 Column c({ 0.5f, 0.5f, 0.4f, 0.4f });
|
Chris@1380
|
133 QCOMPARE(C::peakPick(c), Column({ 0.5f, 0.0f, 0.0f, 0.0f }));
|
Chris@1380
|
134 c = Column({ 0.4f, -0.5f, -0.3f, -0.6f, 0.1f, -0.3f });
|
Chris@1380
|
135 QCOMPARE(C::peakPick(c), Column({ 0.4f, 0.0f, -0.3f, 0.0f, 0.1f, 0.0f }));
|
Chris@1265
|
136 }
|
Chris@1265
|
137
|
Chris@1265
|
138 void normalize_null() {
|
Chris@1265
|
139 QCOMPARE(C::normalize({}, ColumnNormalization::None), Column());
|
Chris@1265
|
140 QCOMPARE(C::normalize({}, ColumnNormalization::Sum1), Column());
|
Chris@1265
|
141 QCOMPARE(C::normalize({}, ColumnNormalization::Max1), Column());
|
Chris@1265
|
142 QCOMPARE(C::normalize({}, ColumnNormalization::Hybrid), Column());
|
Chris@1265
|
143 }
|
Chris@1265
|
144
|
Chris@1265
|
145 void normalize_none() {
|
Chris@1265
|
146 Column c { 1, 2, 3, 4 };
|
Chris@1265
|
147 QCOMPARE(C::normalize(c, ColumnNormalization::None), c);
|
Chris@1265
|
148 }
|
Chris@1265
|
149
|
Chris@1266
|
150 void normalize_none_mixedSign() {
|
Chris@1266
|
151 Column c { 1, 2, -3, -4 };
|
Chris@1266
|
152 QCOMPARE(C::normalize(c, ColumnNormalization::None), c);
|
Chris@1266
|
153 }
|
Chris@1266
|
154
|
Chris@1265
|
155 void normalize_sum1() {
|
Chris@1265
|
156 Column c { 1, 2, 4, 3 };
|
Chris@1265
|
157 QCOMPARE(C::normalize(c, ColumnNormalization::Sum1),
|
Chris@1380
|
158 Column({ 0.1f, 0.2f, 0.4f, 0.3f }));
|
Chris@1265
|
159 }
|
Chris@1265
|
160
|
Chris@1266
|
161 void normalize_sum1_mixedSign() {
|
Chris@1266
|
162 Column c { 1, 2, -4, -3 };
|
Chris@1266
|
163 QCOMPARE(C::normalize(c, ColumnNormalization::Sum1),
|
Chris@1380
|
164 Column({ 0.1f, 0.2f, -0.4f, -0.3f }));
|
Chris@1266
|
165 }
|
Chris@1266
|
166
|
Chris@1265
|
167 void normalize_max1() {
|
Chris@1265
|
168 Column c { 4, 3, 2, 1 };
|
Chris@1265
|
169 QCOMPARE(C::normalize(c, ColumnNormalization::Max1),
|
Chris@1380
|
170 Column({ 1.0f, 0.75f, 0.5f, 0.25f }));
|
Chris@1265
|
171 }
|
Chris@1265
|
172
|
Chris@1266
|
173 void normalize_max1_mixedSign() {
|
Chris@1266
|
174 Column c { -4, -3, 2, 1 };
|
Chris@1266
|
175 QCOMPARE(C::normalize(c, ColumnNormalization::Max1),
|
Chris@1380
|
176 Column({ -1.0f, -0.75f, 0.5f, 0.25f }));
|
Chris@1266
|
177 }
|
Chris@1266
|
178
|
Chris@1265
|
179 void normalize_hybrid() {
|
Chris@1265
|
180 // with max == 99, log10(max+1) == 2 so scale factor will be 2/99
|
Chris@1265
|
181 Column c { 22, 44, 99, 66 };
|
Chris@1265
|
182 QCOMPARE(C::normalize(c, ColumnNormalization::Hybrid),
|
Chris@1380
|
183 Column({ 44.0f/99.0f, 88.0f/99.0f, 2.0f, 132.0f/99.0f }));
|
Chris@1265
|
184 }
|
Chris@1265
|
185
|
Chris@1266
|
186 void normalize_hybrid_mixedSign() {
|
Chris@1266
|
187 // with max == 99, log10(max+1) == 2 so scale factor will be 2/99
|
Chris@1266
|
188 Column c { 22, 44, -99, -66 };
|
Chris@1266
|
189 QCOMPARE(C::normalize(c, ColumnNormalization::Hybrid),
|
Chris@1380
|
190 Column({ 44.0f/99.0f, 88.0f/99.0f, -2.0f, -132.0f/99.0f }));
|
Chris@1266
|
191 }
|
Chris@1266
|
192
|
Chris@1266
|
193 void distribute_simple() {
|
Chris@1266
|
194 Column in { 1, 2, 3 };
|
Chris@1380
|
195 BinMapping binfory { 0.0f, 0.5f, 1.0f, 1.5f, 2.0f, 2.5f };
|
Chris@1266
|
196 Column expected { 1, 1, 2, 2, 3, 3 };
|
Chris@1266
|
197 Column actual(C::distribute(in, 6, binfory, 0, false));
|
Chris@1266
|
198 report(actual);
|
Chris@1266
|
199 QCOMPARE(actual, expected);
|
Chris@1266
|
200 }
|
Chris@1266
|
201
|
Chris@1266
|
202 void distribute_simple_interpolated() {
|
Chris@1266
|
203 Column in { 1, 2, 3 };
|
Chris@1380
|
204 BinMapping binfory { 0.0f, 0.5f, 1.0f, 1.5f, 2.0f, 2.5f };
|
Chris@1267
|
205 // There is a 0.5-bin offset from the distribution you might
|
Chris@1267
|
206 // expect, because this corresponds visually to the way that
|
Chris@1267
|
207 // bin values are duplicated upwards in simple_distribution.
|
Chris@1267
|
208 // It means that switching between interpolated and
|
Chris@1267
|
209 // non-interpolated views retains the visual position of each
|
Chris@1267
|
210 // bin peak as somewhere in the middle of the scale area for
|
Chris@1267
|
211 // that bin.
|
Chris@1380
|
212 Column expected { 1, 1, 1.5f, 2, 2.5f, 3 };
|
Chris@1266
|
213 Column actual(C::distribute(in, 6, binfory, 0, true));
|
Chris@1266
|
214 report(actual);
|
Chris@1266
|
215 QCOMPARE(actual, expected);
|
Chris@1266
|
216 }
|
Chris@1266
|
217
|
Chris@1266
|
218 void distribute_nonlinear() {
|
Chris@1266
|
219 Column in { 1, 2, 3 };
|
Chris@1380
|
220 BinMapping binfory { 0.0f, 0.2f, 0.5f, 1.0f, 2.0f, 2.5f };
|
Chris@1266
|
221 Column expected { 1, 1, 1, 2, 3, 3 };
|
Chris@1266
|
222 Column actual(C::distribute(in, 6, binfory, 0, false));
|
Chris@1266
|
223 report(actual);
|
Chris@1266
|
224 QCOMPARE(actual, expected);
|
Chris@1266
|
225 }
|
Chris@1266
|
226
|
Chris@1266
|
227 void distribute_nonlinear_interpolated() {
|
Chris@1267
|
228 // See distribute_simple_interpolated
|
Chris@1266
|
229 Column in { 1, 2, 3 };
|
Chris@1380
|
230 BinMapping binfory { 0.0f, 0.2f, 0.5f, 1.0f, 2.0f, 2.5f };
|
Chris@1267
|
231 Column expected { 1, 1, 1, 1.5, 2.5, 3 };
|
Chris@1266
|
232 Column actual(C::distribute(in, 6, binfory, 0, true));
|
Chris@1266
|
233 report(actual);
|
Chris@1266
|
234 QCOMPARE(actual, expected);
|
Chris@1266
|
235 }
|
Chris@1266
|
236
|
Chris@1266
|
237 void distribute_shrinking() {
|
Chris@1266
|
238 Column in { 4, 1, 2, 3, 5, 6 };
|
Chris@1380
|
239 BinMapping binfory { 0.0f, 2.0f, 4.0f };
|
Chris@1266
|
240 Column expected { 4, 3, 6 };
|
Chris@1266
|
241 Column actual(C::distribute(in, 3, binfory, 0, false));
|
Chris@1266
|
242 report(actual);
|
Chris@1266
|
243 QCOMPARE(actual, expected);
|
Chris@1266
|
244 }
|
Chris@1266
|
245
|
Chris@1266
|
246 void distribute_shrinking_interpolated() {
|
Chris@1266
|
247 // should be same as distribute_shrinking, we don't
|
Chris@1266
|
248 // interpolate when resizing down
|
Chris@1266
|
249 Column in { 4, 1, 2, 3, 5, 6 };
|
Chris@1380
|
250 BinMapping binfory { 0.0f, 2.0f, 4.0f };
|
Chris@1266
|
251 Column expected { 4, 3, 6 };
|
Chris@1266
|
252 Column actual(C::distribute(in, 3, binfory, 0, true));
|
Chris@1266
|
253 report(actual);
|
Chris@1266
|
254 QCOMPARE(actual, expected);
|
Chris@1266
|
255 }
|
Chris@1265
|
256
|
Chris@1304
|
257 void distribute_nonlinear_someshrinking_interpolated() {
|
Chris@1304
|
258 // But we *should* interpolate if the mapping involves
|
Chris@1304
|
259 // shrinking some bins but expanding others. See
|
Chris@1304
|
260 // distribute_simple_interpolated for note on 0.5 offset
|
Chris@1304
|
261 Column in { 4, 1, 2, 3, 5, 6 };
|
Chris@1380
|
262 BinMapping binfory { 0.0f, 3.0f, 4.0f, 4.5f };
|
Chris@1380
|
263 Column expected { 4.0f, 2.5f, 4.0f, 5.0f };
|
Chris@1304
|
264 Column actual(C::distribute(in, 4, binfory, 0, true));
|
Chris@1304
|
265 report(actual);
|
Chris@1304
|
266 QCOMPARE(actual, expected);
|
Chris@1380
|
267 binfory = BinMapping { 0.5f, 1.0f, 2.0f, 5.0f };
|
Chris@1380
|
268 expected = { 4.0f, 2.5f, 1.5f, 5.5f };
|
Chris@1304
|
269 actual = (C::distribute(in, 4, binfory, 0, true));
|
Chris@1304
|
270 report(actual);
|
Chris@1304
|
271 QCOMPARE(actual, expected);
|
Chris@1304
|
272 }
|
Chris@1265
|
273 };
|
Chris@1265
|
274
|
Chris@1265
|
275 #endif
|
Chris@1265
|
276
|