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@1265
|
26 using namespace std;
|
Chris@1265
|
27
|
Chris@1265
|
28 class TestColumnOp : public QObject
|
Chris@1265
|
29 {
|
Chris@1265
|
30 Q_OBJECT
|
Chris@1265
|
31
|
Chris@1265
|
32 typedef ColumnOp C;
|
Chris@1265
|
33 typedef ColumnOp::Column Column;
|
Chris@1266
|
34 typedef vector<double> BinMapping;
|
Chris@1266
|
35
|
Chris@1269
|
36 #ifdef REPORT
|
Chris@1266
|
37 template <typename T>
|
Chris@1266
|
38 void report(vector<T> v) {
|
Chris@1266
|
39 cerr << "Vector is: [ ";
|
Chris@1266
|
40 for (int i = 0; i < int(v.size()); ++i) {
|
Chris@1266
|
41 if (i > 0) cerr << ", ";
|
Chris@1266
|
42 cerr << v[i];
|
Chris@1266
|
43 }
|
Chris@1266
|
44 cerr << " ]\n";
|
Chris@1266
|
45 }
|
Chris@1269
|
46 #else
|
Chris@1269
|
47 template <typename T>
|
Chris@1269
|
48 void report(vector<T> ) { }
|
Chris@1269
|
49 #endif
|
Chris@1266
|
50
|
Chris@1265
|
51 private slots:
|
Chris@1265
|
52 void applyGain() {
|
Chris@1265
|
53 QCOMPARE(C::applyGain({}, 1.0), Column());
|
Chris@1265
|
54 Column c { 1, 2, 3, -4, 5, 6 };
|
Chris@1265
|
55 Column actual(C::applyGain(c, 1.5));
|
Chris@1265
|
56 Column expected { 1.5, 3, 4.5, -6, 7.5, 9 };
|
Chris@1265
|
57 QCOMPARE(actual, expected);
|
Chris@1265
|
58 actual = C::applyGain(c, 1.0);
|
Chris@1265
|
59 QCOMPARE(actual, c);
|
Chris@1265
|
60 actual = C::applyGain(c, 0.0);
|
Chris@1265
|
61 expected = { 0, 0, 0, 0, 0, 0 };
|
Chris@1265
|
62 QCOMPARE(actual, expected);
|
Chris@1265
|
63 }
|
Chris@1265
|
64
|
Chris@1265
|
65 void fftScale() {
|
Chris@1265
|
66 QCOMPARE(C::fftScale({}, 2.0), Column());
|
Chris@1265
|
67 Column c { 1, 2, 3, -4, 5 };
|
Chris@1265
|
68 Column actual(C::fftScale(c, 8));
|
Chris@1265
|
69 Column expected { 0.25, 0.5, 0.75, -1, 1.25 };
|
Chris@1265
|
70 QCOMPARE(actual, expected);
|
Chris@1265
|
71 }
|
Chris@1265
|
72
|
Chris@1265
|
73 void isPeak_null() {
|
Chris@1265
|
74 QVERIFY(!C::isPeak({}, 0));
|
Chris@1265
|
75 QVERIFY(!C::isPeak({}, 1));
|
Chris@1265
|
76 QVERIFY(!C::isPeak({}, -1));
|
Chris@1265
|
77 }
|
Chris@1265
|
78
|
Chris@1265
|
79 void isPeak_obvious() {
|
Chris@1265
|
80 Column c { 0.4, 0.5, 0.3 };
|
Chris@1265
|
81 QVERIFY(!C::isPeak(c, 0));
|
Chris@1265
|
82 QVERIFY(C::isPeak(c, 1));
|
Chris@1265
|
83 QVERIFY(!C::isPeak(c, 2));
|
Chris@1265
|
84 }
|
Chris@1265
|
85
|
Chris@1265
|
86 void isPeak_edges() {
|
Chris@1265
|
87 Column c { 0.5, 0.4, 0.3 };
|
Chris@1265
|
88 QVERIFY(C::isPeak(c, 0));
|
Chris@1265
|
89 QVERIFY(!C::isPeak(c, 1));
|
Chris@1265
|
90 QVERIFY(!C::isPeak(c, 2));
|
Chris@1265
|
91 QVERIFY(!C::isPeak(c, 3));
|
Chris@1265
|
92 QVERIFY(!C::isPeak(c, -1));
|
Chris@1265
|
93 c = { 1.4, 1.5 };
|
Chris@1265
|
94 QVERIFY(!C::isPeak(c, 0));
|
Chris@1265
|
95 QVERIFY(C::isPeak(c, 1));
|
Chris@1265
|
96 }
|
Chris@1265
|
97
|
Chris@1265
|
98 void isPeak_flat() {
|
Chris@1265
|
99 Column c { 0.0, 0.0, 0.0 };
|
Chris@1265
|
100 QVERIFY(C::isPeak(c, 0));
|
Chris@1265
|
101 QVERIFY(!C::isPeak(c, 1));
|
Chris@1265
|
102 QVERIFY(!C::isPeak(c, 2));
|
Chris@1265
|
103 }
|
Chris@1265
|
104
|
Chris@1265
|
105 void isPeak_mixedSign() {
|
Chris@1265
|
106 Column c { 0.4, -0.5, -0.3, -0.6, 0.1, -0.3 };
|
Chris@1265
|
107 QVERIFY(C::isPeak(c, 0));
|
Chris@1265
|
108 QVERIFY(!C::isPeak(c, 1));
|
Chris@1265
|
109 QVERIFY(C::isPeak(c, 2));
|
Chris@1265
|
110 QVERIFY(!C::isPeak(c, 3));
|
Chris@1265
|
111 QVERIFY(C::isPeak(c, 4));
|
Chris@1265
|
112 QVERIFY(!C::isPeak(c, 5));
|
Chris@1265
|
113 }
|
Chris@1265
|
114
|
Chris@1265
|
115 void isPeak_duplicate() {
|
Chris@1265
|
116 Column c({ 0.5, 0.5, 0.4, 0.4 });
|
Chris@1265
|
117 QVERIFY(C::isPeak(c, 0));
|
Chris@1265
|
118 QVERIFY(!C::isPeak(c, 1));
|
Chris@1265
|
119 QVERIFY(!C::isPeak(c, 2));
|
Chris@1265
|
120 QVERIFY(!C::isPeak(c, 3));
|
Chris@1265
|
121 c = { 0.4, 0.4, 0.5, 0.5 };
|
Chris@1265
|
122 QVERIFY(C::isPeak(c, 0)); // counterintuitive but necessary
|
Chris@1265
|
123 QVERIFY(!C::isPeak(c, 1));
|
Chris@1265
|
124 QVERIFY(C::isPeak(c, 2));
|
Chris@1265
|
125 QVERIFY(!C::isPeak(c, 3));
|
Chris@1265
|
126 }
|
Chris@1265
|
127
|
Chris@1265
|
128 void peakPick() {
|
Chris@1265
|
129 QCOMPARE(C::peakPick({}), Column());
|
Chris@1265
|
130 Column c({ 0.5, 0.5, 0.4, 0.4 });
|
Chris@1265
|
131 QCOMPARE(C::peakPick(c), Column({ 0.5, 0.0, 0.0, 0.0 }));
|
Chris@1265
|
132 c = Column({ 0.4, -0.5, -0.3, -0.6, 0.1, -0.3 });
|
Chris@1265
|
133 QCOMPARE(C::peakPick(c), Column({ 0.4, 0.0, -0.3, 0.0, 0.1, 0.0 }));
|
Chris@1265
|
134 }
|
Chris@1265
|
135
|
Chris@1265
|
136 void normalize_null() {
|
Chris@1265
|
137 QCOMPARE(C::normalize({}, ColumnNormalization::None), Column());
|
Chris@1265
|
138 QCOMPARE(C::normalize({}, ColumnNormalization::Sum1), Column());
|
Chris@1265
|
139 QCOMPARE(C::normalize({}, ColumnNormalization::Max1), Column());
|
Chris@1265
|
140 QCOMPARE(C::normalize({}, ColumnNormalization::Hybrid), Column());
|
Chris@1265
|
141 }
|
Chris@1265
|
142
|
Chris@1265
|
143 void normalize_none() {
|
Chris@1265
|
144 Column c { 1, 2, 3, 4 };
|
Chris@1265
|
145 QCOMPARE(C::normalize(c, ColumnNormalization::None), c);
|
Chris@1265
|
146 }
|
Chris@1265
|
147
|
Chris@1266
|
148 void normalize_none_mixedSign() {
|
Chris@1266
|
149 Column c { 1, 2, -3, -4 };
|
Chris@1266
|
150 QCOMPARE(C::normalize(c, ColumnNormalization::None), c);
|
Chris@1266
|
151 }
|
Chris@1266
|
152
|
Chris@1265
|
153 void normalize_sum1() {
|
Chris@1265
|
154 Column c { 1, 2, 4, 3 };
|
Chris@1265
|
155 QCOMPARE(C::normalize(c, ColumnNormalization::Sum1),
|
Chris@1265
|
156 Column({ 0.1, 0.2, 0.4, 0.3 }));
|
Chris@1265
|
157 }
|
Chris@1265
|
158
|
Chris@1266
|
159 void normalize_sum1_mixedSign() {
|
Chris@1266
|
160 Column c { 1, 2, -4, -3 };
|
Chris@1266
|
161 QCOMPARE(C::normalize(c, ColumnNormalization::Sum1),
|
Chris@1266
|
162 Column({ 0.1, 0.2, -0.4, -0.3 }));
|
Chris@1266
|
163 }
|
Chris@1266
|
164
|
Chris@1265
|
165 void normalize_max1() {
|
Chris@1265
|
166 Column c { 4, 3, 2, 1 };
|
Chris@1265
|
167 QCOMPARE(C::normalize(c, ColumnNormalization::Max1),
|
Chris@1265
|
168 Column({ 1.0, 0.75, 0.5, 0.25 }));
|
Chris@1265
|
169 }
|
Chris@1265
|
170
|
Chris@1266
|
171 void normalize_max1_mixedSign() {
|
Chris@1266
|
172 Column c { -4, -3, 2, 1 };
|
Chris@1266
|
173 QCOMPARE(C::normalize(c, ColumnNormalization::Max1),
|
Chris@1266
|
174 Column({ -1.0, -0.75, 0.5, 0.25 }));
|
Chris@1266
|
175 }
|
Chris@1266
|
176
|
Chris@1265
|
177 void normalize_hybrid() {
|
Chris@1265
|
178 // with max == 99, log10(max+1) == 2 so scale factor will be 2/99
|
Chris@1265
|
179 Column c { 22, 44, 99, 66 };
|
Chris@1265
|
180 QCOMPARE(C::normalize(c, ColumnNormalization::Hybrid),
|
Chris@1265
|
181 Column({ 44.0/99.0, 88.0/99.0, 2.0, 132.0/99.0 }));
|
Chris@1265
|
182 }
|
Chris@1265
|
183
|
Chris@1266
|
184 void normalize_hybrid_mixedSign() {
|
Chris@1266
|
185 // with max == 99, log10(max+1) == 2 so scale factor will be 2/99
|
Chris@1266
|
186 Column c { 22, 44, -99, -66 };
|
Chris@1266
|
187 QCOMPARE(C::normalize(c, ColumnNormalization::Hybrid),
|
Chris@1266
|
188 Column({ 44.0/99.0, 88.0/99.0, -2.0, -132.0/99.0 }));
|
Chris@1266
|
189 }
|
Chris@1266
|
190
|
Chris@1266
|
191 void distribute_simple() {
|
Chris@1266
|
192 Column in { 1, 2, 3 };
|
Chris@1266
|
193 BinMapping binfory { 0.0, 0.5, 1.0, 1.5, 2.0, 2.5 };
|
Chris@1266
|
194 Column expected { 1, 1, 2, 2, 3, 3 };
|
Chris@1266
|
195 Column actual(C::distribute(in, 6, binfory, 0, false));
|
Chris@1266
|
196 report(actual);
|
Chris@1266
|
197 QCOMPARE(actual, expected);
|
Chris@1266
|
198 }
|
Chris@1266
|
199
|
Chris@1266
|
200 void distribute_simple_interpolated() {
|
Chris@1266
|
201 Column in { 1, 2, 3 };
|
Chris@1266
|
202 BinMapping binfory { 0.0, 0.5, 1.0, 1.5, 2.0, 2.5 };
|
Chris@1267
|
203 // There is a 0.5-bin offset from the distribution you might
|
Chris@1267
|
204 // expect, because this corresponds visually to the way that
|
Chris@1267
|
205 // bin values are duplicated upwards in simple_distribution.
|
Chris@1267
|
206 // It means that switching between interpolated and
|
Chris@1267
|
207 // non-interpolated views retains the visual position of each
|
Chris@1267
|
208 // bin peak as somewhere in the middle of the scale area for
|
Chris@1267
|
209 // that bin.
|
Chris@1267
|
210 Column expected { 1, 1, 1.5, 2, 2.5, 3 };
|
Chris@1266
|
211 Column actual(C::distribute(in, 6, binfory, 0, true));
|
Chris@1266
|
212 report(actual);
|
Chris@1266
|
213 QCOMPARE(actual, expected);
|
Chris@1266
|
214 }
|
Chris@1266
|
215
|
Chris@1266
|
216 void distribute_nonlinear() {
|
Chris@1266
|
217 Column in { 1, 2, 3 };
|
Chris@1266
|
218 BinMapping binfory { 0.0, 0.2, 0.5, 1.0, 2.0, 2.5 };
|
Chris@1266
|
219 Column expected { 1, 1, 1, 2, 3, 3 };
|
Chris@1266
|
220 Column actual(C::distribute(in, 6, binfory, 0, false));
|
Chris@1266
|
221 report(actual);
|
Chris@1266
|
222 QCOMPARE(actual, expected);
|
Chris@1266
|
223 }
|
Chris@1266
|
224
|
Chris@1266
|
225 void distribute_nonlinear_interpolated() {
|
Chris@1267
|
226 // See distribute_simple_interpolated
|
Chris@1266
|
227 Column in { 1, 2, 3 };
|
Chris@1266
|
228 BinMapping binfory { 0.0, 0.2, 0.5, 1.0, 2.0, 2.5 };
|
Chris@1267
|
229 Column expected { 1, 1, 1, 1.5, 2.5, 3 };
|
Chris@1266
|
230 Column actual(C::distribute(in, 6, binfory, 0, true));
|
Chris@1266
|
231 report(actual);
|
Chris@1266
|
232 QCOMPARE(actual, expected);
|
Chris@1266
|
233 }
|
Chris@1266
|
234
|
Chris@1266
|
235 void distribute_shrinking() {
|
Chris@1266
|
236 Column in { 4, 1, 2, 3, 5, 6 };
|
Chris@1266
|
237 BinMapping binfory { 0.0, 2.0, 4.0 };
|
Chris@1266
|
238 Column expected { 4, 3, 6 };
|
Chris@1266
|
239 Column actual(C::distribute(in, 3, binfory, 0, false));
|
Chris@1266
|
240 report(actual);
|
Chris@1266
|
241 QCOMPARE(actual, expected);
|
Chris@1266
|
242 }
|
Chris@1266
|
243
|
Chris@1266
|
244 void distribute_shrinking_interpolated() {
|
Chris@1266
|
245 // should be same as distribute_shrinking, we don't
|
Chris@1266
|
246 // interpolate when resizing down
|
Chris@1266
|
247 Column in { 4, 1, 2, 3, 5, 6 };
|
Chris@1266
|
248 BinMapping binfory { 0.0, 2.0, 4.0 };
|
Chris@1266
|
249 Column expected { 4, 3, 6 };
|
Chris@1266
|
250 Column actual(C::distribute(in, 3, binfory, 0, true));
|
Chris@1266
|
251 report(actual);
|
Chris@1266
|
252 QCOMPARE(actual, expected);
|
Chris@1266
|
253 }
|
Chris@1265
|
254
|
Chris@1265
|
255
|
Chris@1265
|
256 };
|
Chris@1265
|
257
|
Chris@1265
|
258 #endif
|
Chris@1265
|
259
|