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