annotate base/test/TestColumnOp.h @ 1671:82d03c9661f9 single-point

Rework isReady()/getCompletion() on models. Previously the new overhauled models were implementing getCompletion() but inheriting a version of isReady() (from the Model base) that didn't call it, referring only to isOK(). So they were reporting completion as soon as they had begun. Instead hoist getCompletion() to abstract base and call it from Model::isReady().
author Chris Cannam
date Wed, 27 Mar 2019 13:15:16 +0000
parents 9ef1cc26024c
children 1b688ab5f1b3
rev   line source
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@1394 142 QCOMPARE(C::normalize({}, ColumnNormalization::Range01), Column());
Chris@1265 143 QCOMPARE(C::normalize({}, ColumnNormalization::Hybrid), Column());
Chris@1265 144 }
Chris@1265 145
Chris@1265 146 void normalize_none() {
Chris@1265 147 Column c { 1, 2, 3, 4 };
Chris@1265 148 QCOMPARE(C::normalize(c, ColumnNormalization::None), c);
Chris@1265 149 }
Chris@1265 150
Chris@1266 151 void normalize_none_mixedSign() {
Chris@1266 152 Column c { 1, 2, -3, -4 };
Chris@1266 153 QCOMPARE(C::normalize(c, ColumnNormalization::None), c);
Chris@1266 154 }
Chris@1266 155
Chris@1265 156 void normalize_sum1() {
Chris@1265 157 Column c { 1, 2, 4, 3 };
Chris@1265 158 QCOMPARE(C::normalize(c, ColumnNormalization::Sum1),
Chris@1380 159 Column({ 0.1f, 0.2f, 0.4f, 0.3f }));
Chris@1265 160 }
Chris@1265 161
Chris@1266 162 void normalize_sum1_mixedSign() {
Chris@1266 163 Column c { 1, 2, -4, -3 };
Chris@1266 164 QCOMPARE(C::normalize(c, ColumnNormalization::Sum1),
Chris@1380 165 Column({ 0.1f, 0.2f, -0.4f, -0.3f }));
Chris@1266 166 }
Chris@1266 167
Chris@1265 168 void normalize_max1() {
Chris@1265 169 Column c { 4, 3, 2, 1 };
Chris@1265 170 QCOMPARE(C::normalize(c, ColumnNormalization::Max1),
Chris@1380 171 Column({ 1.0f, 0.75f, 0.5f, 0.25f }));
Chris@1265 172 }
Chris@1265 173
Chris@1266 174 void normalize_max1_mixedSign() {
Chris@1266 175 Column c { -4, -3, 2, 1 };
Chris@1266 176 QCOMPARE(C::normalize(c, ColumnNormalization::Max1),
Chris@1380 177 Column({ -1.0f, -0.75f, 0.5f, 0.25f }));
Chris@1266 178 }
Chris@1266 179
Chris@1394 180 void normalize_range01() {
Chris@1394 181 Column c { 4, 3, 2, 1 };
Chris@1394 182 QCOMPARE(C::normalize(c, ColumnNormalization::Range01),
Chris@1394 183 Column({ 1.0f, 2.f/3.f, 1.f/3.f, 0.0f }));
Chris@1394 184 }
Chris@1394 185
Chris@1394 186 void normalize_range01_mixedSign() {
Chris@1394 187 Column c { -2, -3, 2, 1 };
Chris@1394 188 QCOMPARE(C::normalize(c, ColumnNormalization::Range01),
Chris@1394 189 Column({ 0.2f, 0.0f, 1.0f, 0.8f }));
Chris@1394 190 }
Chris@1394 191
Chris@1265 192 void normalize_hybrid() {
Chris@1265 193 // with max == 99, log10(max+1) == 2 so scale factor will be 2/99
Chris@1265 194 Column c { 22, 44, 99, 66 };
Chris@1265 195 QCOMPARE(C::normalize(c, ColumnNormalization::Hybrid),
Chris@1380 196 Column({ 44.0f/99.0f, 88.0f/99.0f, 2.0f, 132.0f/99.0f }));
Chris@1265 197 }
Chris@1265 198
Chris@1266 199 void normalize_hybrid_mixedSign() {
Chris@1266 200 // with max == 99, log10(max+1) == 2 so scale factor will be 2/99
Chris@1266 201 Column c { 22, 44, -99, -66 };
Chris@1266 202 QCOMPARE(C::normalize(c, ColumnNormalization::Hybrid),
Chris@1380 203 Column({ 44.0f/99.0f, 88.0f/99.0f, -2.0f, -132.0f/99.0f }));
Chris@1266 204 }
Chris@1266 205
Chris@1266 206 void distribute_simple() {
Chris@1266 207 Column in { 1, 2, 3 };
Chris@1380 208 BinMapping binfory { 0.0f, 0.5f, 1.0f, 1.5f, 2.0f, 2.5f };
Chris@1266 209 Column expected { 1, 1, 2, 2, 3, 3 };
Chris@1266 210 Column actual(C::distribute(in, 6, binfory, 0, false));
Chris@1266 211 report(actual);
Chris@1266 212 QCOMPARE(actual, expected);
Chris@1266 213 }
Chris@1266 214
Chris@1266 215 void distribute_simple_interpolated() {
Chris@1266 216 Column in { 1, 2, 3 };
Chris@1380 217 BinMapping binfory { 0.0f, 0.5f, 1.0f, 1.5f, 2.0f, 2.5f };
Chris@1267 218 // There is a 0.5-bin offset from the distribution you might
Chris@1267 219 // expect, because this corresponds visually to the way that
Chris@1267 220 // bin values are duplicated upwards in simple_distribution.
Chris@1267 221 // It means that switching between interpolated and
Chris@1267 222 // non-interpolated views retains the visual position of each
Chris@1267 223 // bin peak as somewhere in the middle of the scale area for
Chris@1267 224 // that bin.
Chris@1380 225 Column expected { 1, 1, 1.5f, 2, 2.5f, 3 };
Chris@1266 226 Column actual(C::distribute(in, 6, binfory, 0, true));
Chris@1266 227 report(actual);
Chris@1266 228 QCOMPARE(actual, expected);
Chris@1266 229 }
Chris@1266 230
Chris@1266 231 void distribute_nonlinear() {
Chris@1266 232 Column in { 1, 2, 3 };
Chris@1380 233 BinMapping binfory { 0.0f, 0.2f, 0.5f, 1.0f, 2.0f, 2.5f };
Chris@1266 234 Column expected { 1, 1, 1, 2, 3, 3 };
Chris@1266 235 Column actual(C::distribute(in, 6, binfory, 0, false));
Chris@1266 236 report(actual);
Chris@1266 237 QCOMPARE(actual, expected);
Chris@1266 238 }
Chris@1266 239
Chris@1266 240 void distribute_nonlinear_interpolated() {
Chris@1267 241 // See distribute_simple_interpolated
Chris@1266 242 Column in { 1, 2, 3 };
Chris@1380 243 BinMapping binfory { 0.0f, 0.2f, 0.5f, 1.0f, 2.0f, 2.5f };
Chris@1267 244 Column expected { 1, 1, 1, 1.5, 2.5, 3 };
Chris@1266 245 Column actual(C::distribute(in, 6, binfory, 0, true));
Chris@1266 246 report(actual);
Chris@1266 247 QCOMPARE(actual, expected);
Chris@1266 248 }
Chris@1266 249
Chris@1266 250 void distribute_shrinking() {
Chris@1266 251 Column in { 4, 1, 2, 3, 5, 6 };
Chris@1380 252 BinMapping binfory { 0.0f, 2.0f, 4.0f };
Chris@1266 253 Column expected { 4, 3, 6 };
Chris@1266 254 Column actual(C::distribute(in, 3, binfory, 0, false));
Chris@1266 255 report(actual);
Chris@1266 256 QCOMPARE(actual, expected);
Chris@1266 257 }
Chris@1266 258
Chris@1266 259 void distribute_shrinking_interpolated() {
Chris@1266 260 // should be same as distribute_shrinking, we don't
Chris@1266 261 // interpolate when resizing down
Chris@1266 262 Column in { 4, 1, 2, 3, 5, 6 };
Chris@1380 263 BinMapping binfory { 0.0f, 2.0f, 4.0f };
Chris@1266 264 Column expected { 4, 3, 6 };
Chris@1266 265 Column actual(C::distribute(in, 3, binfory, 0, true));
Chris@1266 266 report(actual);
Chris@1266 267 QCOMPARE(actual, expected);
Chris@1266 268 }
Chris@1265 269
Chris@1304 270 void distribute_nonlinear_someshrinking_interpolated() {
Chris@1304 271 // But we *should* interpolate if the mapping involves
Chris@1304 272 // shrinking some bins but expanding others. See
Chris@1304 273 // distribute_simple_interpolated for note on 0.5 offset
Chris@1304 274 Column in { 4, 1, 2, 3, 5, 6 };
Chris@1380 275 BinMapping binfory { 0.0f, 3.0f, 4.0f, 4.5f };
Chris@1380 276 Column expected { 4.0f, 2.5f, 4.0f, 5.0f };
Chris@1304 277 Column actual(C::distribute(in, 4, binfory, 0, true));
Chris@1304 278 report(actual);
Chris@1304 279 QCOMPARE(actual, expected);
Chris@1380 280 binfory = BinMapping { 0.5f, 1.0f, 2.0f, 5.0f };
Chris@1380 281 expected = { 4.0f, 2.5f, 1.5f, 5.5f };
Chris@1304 282 actual = (C::distribute(in, 4, binfory, 0, true));
Chris@1304 283 report(actual);
Chris@1304 284 QCOMPARE(actual, expected);
Chris@1304 285 }
Chris@1265 286 };
Chris@1265 287
Chris@1265 288 #endif
Chris@1265 289