annotate data/model/test/TestSparseModels.h @ 1774:f19711ab7074

Optionally record relative pitch
author Chris Cannam
date Thu, 15 Aug 2019 18:18:03 +0100
parents 9d82b164f264
children
rev   line source
Chris@1611 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@1611 2
Chris@1611 3 /*
Chris@1611 4 Sonic Visualiser
Chris@1611 5 An audio file viewer and annotation editor.
Chris@1611 6 Centre for Digital Music, Queen Mary, University of London.
Chris@1611 7
Chris@1611 8 This program is free software; you can redistribute it and/or
Chris@1611 9 modify it under the terms of the GNU General Public License as
Chris@1611 10 published by the Free Software Foundation; either version 2 of the
Chris@1611 11 License, or (at your option) any later version. See the file
Chris@1611 12 COPYING included with this distribution for more information.
Chris@1611 13 */
Chris@1611 14
Chris@1611 15 #ifndef TEST_SPARSE_MODELS_H
Chris@1611 16 #define TEST_SPARSE_MODELS_H
Chris@1611 17
Chris@1611 18 #include "../SparseOneDimensionalModel.h"
Chris@1611 19 #include "../NoteModel.h"
Chris@1661 20 #include "../TextModel.h"
Chris@1741 21 #include "../Path.h"
Chris@1674 22 #include "../ImageModel.h"
Chris@1611 23
Chris@1611 24 #include <QObject>
Chris@1611 25 #include <QtTest>
Chris@1611 26
Chris@1611 27 #include <iostream>
Chris@1611 28
Chris@1611 29 using namespace std;
Chris@1611 30
Chris@1677 31 // NB model & dataset IDs in the export tests are incremental,
Chris@1677 32 // depending on how many have been exported in previous tests - so
Chris@1677 33 // when adding or removing tests we may occasionally need to update
Chris@1677 34 // the IDs in other ones
Chris@1677 35
Chris@1611 36 class TestSparseModels : public QObject
Chris@1611 37 {
Chris@1611 38 Q_OBJECT
Chris@1611 39
Chris@1611 40 private slots:
Chris@1611 41 void s1d_empty() {
Chris@1611 42 SparseOneDimensionalModel m(100, 10, false);
Chris@1611 43 QCOMPARE(m.isEmpty(), true);
Chris@1658 44 QCOMPARE(m.getEventCount(), 0);
Chris@1689 45 QCOMPARE(m.getAllEvents().size(), size_t(0));
Chris@1717 46 QCOMPARE(m.getStartFrame(), sv_frame_t(0));
Chris@1717 47 QCOMPARE(m.getEndFrame(), sv_frame_t(0));
Chris@1689 48 QCOMPARE(m.getSampleRate(), 100.0);
Chris@1611 49 QCOMPARE(m.getResolution(), 10);
Chris@1611 50 QCOMPARE(m.isSparse(), true);
Chris@1611 51
Chris@1658 52 Event p(10);
Chris@1658 53 m.add(p);
Chris@1658 54 m.remove(p);
Chris@1611 55 QCOMPARE(m.isEmpty(), true);
Chris@1658 56 QCOMPARE(m.getEventCount(), 0);
Chris@1689 57 QCOMPARE(m.getAllEvents().size(), size_t(0));
Chris@1717 58 QCOMPARE(m.getStartFrame(), sv_frame_t(0));
Chris@1717 59 QCOMPARE(m.getEndFrame(), sv_frame_t(0));
Chris@1611 60 }
Chris@1611 61
Chris@1611 62 void s1d_extents() {
Chris@1611 63 SparseOneDimensionalModel m(100, 10, false);
Chris@1658 64 Event p1(20);
Chris@1658 65 m.add(p1);
Chris@1611 66 QCOMPARE(m.isEmpty(), false);
Chris@1658 67 QCOMPARE(m.getEventCount(), 1);
Chris@1658 68 Event p2(50);
Chris@1658 69 m.add(p2);
Chris@1611 70 QCOMPARE(m.isEmpty(), false);
Chris@1658 71 QCOMPARE(m.getEventCount(), 2);
Chris@1689 72 QCOMPARE(m.getAllEvents().size(), size_t(2));
Chris@1658 73 QCOMPARE(*m.getAllEvents().begin(), p1);
Chris@1658 74 QCOMPARE(*m.getAllEvents().rbegin(), p2);
Chris@1717 75 QCOMPARE(m.getStartFrame(), sv_frame_t(20));
Chris@1717 76 QCOMPARE(m.getEndFrame(), sv_frame_t(60));
Chris@1658 77 QCOMPARE(m.containsEvent(p1), true);
Chris@1658 78 m.remove(p1);
Chris@1658 79 QCOMPARE(m.getEventCount(), 1);
Chris@1689 80 QCOMPARE(m.getAllEvents().size(), size_t(1));
Chris@1658 81 QCOMPARE(*m.getAllEvents().begin(), p2);
Chris@1717 82 QCOMPARE(m.getStartFrame(), sv_frame_t(50));
Chris@1717 83 QCOMPARE(m.getEndFrame(), sv_frame_t(60));
Chris@1658 84 QCOMPARE(m.containsEvent(p1), false);
Chris@1611 85 }
Chris@1611 86
Chris@1611 87 void s1d_sample() {
Chris@1611 88 SparseOneDimensionalModel m(100, 10, false);
Chris@1658 89 Event p1(20), p2(20), p3(50);
Chris@1658 90 m.add(p1);
Chris@1658 91 m.add(p2);
Chris@1658 92 m.add(p3);
Chris@1689 93 QCOMPARE(m.getAllEvents().size(), size_t(3));
Chris@1658 94 QCOMPARE(*m.getAllEvents().begin(), p1);
Chris@1658 95 QCOMPARE(*m.getAllEvents().rbegin(), p3);
Chris@1659 96
Chris@1659 97 // The EventSeries that is used internally is tested more
Chris@1659 98 // thoroughly in its own test suite. This is just a check
Chris@1659 99 auto pp = m.getEventsWithin(20, 10);
Chris@1689 100 QCOMPARE(pp.size(), size_t(2));
Chris@1611 101 QCOMPARE(*pp.begin(), p1);
Chris@1611 102 QCOMPARE(*pp.rbegin(), p2);
Chris@1643 103
Chris@1659 104 pp = m.getEventsWithin(40, 10);
Chris@1689 105 QCOMPARE(pp.size(), size_t(0));
Chris@1611 106
Chris@1659 107 pp = m.getEventsStartingAt(50);
Chris@1689 108 QCOMPARE(pp.size(), size_t(1));
Chris@1611 109 QCOMPARE(*pp.begin(), p3);
Chris@1611 110 }
Chris@1611 111
Chris@1611 112 void s1d_xml() {
Chris@1611 113 SparseOneDimensionalModel m(100, 10, false);
Chris@1611 114 m.setObjectName("This \"&\" that");
Chris@1674 115 Event p1(20);
Chris@1674 116 Event p2(20, "Label &'\">");
Chris@1674 117 Event p3(50, 12.4f, 16, ""); // value + duration should not be saved
Chris@1658 118 m.add(p1);
Chris@1658 119 m.add(p2);
Chris@1658 120 m.add(p3);
Chris@1611 121 QString xml;
Chris@1611 122 QTextStream str(&xml, QIODevice::WriteOnly);
Chris@1611 123 m.toXml(str);
Chris@1611 124 str.flush();
Chris@1611 125 QString expected =
Chris@1685 126 "<model id='1' name='This &quot;&amp;&quot; that' sampleRate='100' start='20' end='60' type='sparse' dimensions='1' resolution='10' notifyOnAdd='true' dataset='0' />\n"
Chris@1685 127 "<dataset id='0' dimensions='1'>\n"
Chris@1685 128 " <point frame='20' label='' />\n"
Chris@1611 129 " <point frame='20' label='Label &amp;&apos;&quot;&gt;' />\n"
Chris@1685 130 " <point frame='50' label='' />\n"
Chris@1611 131 "</dataset>\n";
Chris@1611 132 expected.replace("\'", "\"");
Chris@1611 133 if (xml != expected) {
Chris@1611 134 cerr << "Obtained xml:\n" << xml
Chris@1697 135 << "\nExpected:\n" << expected << std::endl;
Chris@1611 136 }
Chris@1611 137 QCOMPARE(xml, expected);
Chris@1611 138 }
Chris@1611 139
Chris@1611 140 void note_extents() {
Chris@1611 141 NoteModel m(100, 10, false);
Chris@1643 142 Event p1(20, 123.4f, 40, 0.8f, "note 1");
Chris@1644 143 m.add(p1);
Chris@1611 144 QCOMPARE(m.isEmpty(), false);
Chris@1644 145 QCOMPARE(m.getEventCount(), 1);
Chris@1643 146 Event p2(50, 124.3f, 30, 0.9f, "note 2");
Chris@1644 147 m.add(p2);
Chris@1611 148 QCOMPARE(m.isEmpty(), false);
Chris@1644 149 QCOMPARE(m.getEventCount(), 2);
Chris@1689 150 QCOMPARE(m.getAllEvents().size(), size_t(2));
Chris@1644 151 QCOMPARE(*m.getAllEvents().begin(), p1);
Chris@1644 152 QCOMPARE(*m.getAllEvents().rbegin(), p2);
Chris@1717 153 QCOMPARE(m.getStartFrame(), sv_frame_t(20));
Chris@1717 154 QCOMPARE(m.getEndFrame(), sv_frame_t(80));
Chris@1644 155 QCOMPARE(m.containsEvent(p1), true);
Chris@1643 156 QCOMPARE(m.getValueMinimum(), 123.4f);
Chris@1643 157 QCOMPARE(m.getValueMaximum(), 124.3f);
Chris@1644 158 m.remove(p1);
Chris@1644 159 QCOMPARE(m.getEventCount(), 1);
Chris@1689 160 QCOMPARE(m.getAllEvents().size(), size_t(1));
Chris@1644 161 QCOMPARE(*m.getAllEvents().begin(), p2);
Chris@1717 162 QCOMPARE(m.getStartFrame(), sv_frame_t(50));
Chris@1717 163 QCOMPARE(m.getEndFrame(), sv_frame_t(80));
Chris@1644 164 QCOMPARE(m.containsEvent(p1), false);
Chris@1611 165 }
Chris@1611 166
Chris@1611 167 void note_sample() {
Chris@1611 168 NoteModel m(100, 10, false);
Chris@1643 169 Event p1(20, 123.4f, 10, 0.8f, "note 1");
Chris@1643 170 Event p2(20, 124.3f, 20, 0.9f, "note 2");
Chris@1643 171 Event p3(50, 126.3f, 30, 0.9f, "note 3");
Chris@1644 172 m.add(p1);
Chris@1644 173 m.add(p2);
Chris@1644 174 m.add(p3);
Chris@1611 175
Chris@1689 176 QCOMPARE(m.getAllEvents().size(), size_t(3));
Chris@1644 177 QCOMPARE(*m.getAllEvents().begin(), p1);
Chris@1644 178 QCOMPARE(*m.getAllEvents().rbegin(), p3);
Chris@1611 179
Chris@1644 180 auto pp = m.getEventsSpanning(20, 10);
Chris@1689 181 QCOMPARE(pp.size(), size_t(2));
Chris@1611 182 QCOMPARE(*pp.begin(), p1);
Chris@1611 183 QCOMPARE(*pp.rbegin(), p2);
Chris@1611 184
Chris@1644 185 pp = m.getEventsSpanning(30, 20);
Chris@1689 186 QCOMPARE(pp.size(), size_t(1));
Chris@1643 187 QCOMPARE(*pp.begin(), p2);
Chris@1611 188
Chris@1644 189 pp = m.getEventsSpanning(40, 10);
Chris@1689 190 QCOMPARE(pp.size(), size_t(0));
Chris@1611 191
Chris@1644 192 pp = m.getEventsCovering(50);
Chris@1689 193 QCOMPARE(pp.size(), size_t(1));
Chris@1644 194 QCOMPARE(*pp.begin(), p3);
Chris@1611 195 }
Chris@1611 196
Chris@1611 197 void note_xml() {
Chris@1611 198 NoteModel m(100, 10, false);
Chris@1643 199 Event p1(20, 123.4f, 20, 0.8f, "note 1");
Chris@1643 200 Event p2(20, 124.3f, 10, 0.9f, "note 2");
Chris@1643 201 Event p3(50, 126.3f, 30, 0.9f, "note 3");
Chris@1611 202 m.setScaleUnits("Hz");
Chris@1644 203 m.add(p1);
Chris@1644 204 m.add(p2);
Chris@1644 205 m.add(p3);
Chris@1611 206 QString xml;
Chris@1611 207 QTextStream str(&xml, QIODevice::WriteOnly);
Chris@1611 208 m.toXml(str);
Chris@1611 209 str.flush();
Chris@1651 210
Chris@1611 211 QString expected =
Chris@1685 212 "<model id='3' name='' sampleRate='100' start='20' end='80' type='sparse' dimensions='3' resolution='10' notifyOnAdd='true' dataset='2' subtype='note' valueQuantization='0' minimum='123.4' maximum='126.3' units='Hz' />\n"
Chris@1685 213 "<dataset id='2' dimensions='3'>\n"
Chris@1643 214 " <point frame='20' value='124.3' duration='10' level='0.9' label='note 2' />\n"
Chris@1611 215 " <point frame='20' value='123.4' duration='20' level='0.8' label='note 1' />\n"
Chris@1611 216 " <point frame='50' value='126.3' duration='30' level='0.9' label='note 3' />\n"
Chris@1611 217 "</dataset>\n";
Chris@1611 218 expected.replace("\'", "\"");
Chris@1611 219 if (xml != expected) {
Chris@1611 220 cerr << "Obtained xml:\n" << xml
Chris@1697 221 << "\nExpected:\n" << expected << std::endl;
Chris@1611 222 }
Chris@1611 223 QCOMPARE(xml, expected);
Chris@1611 224 }
Chris@1661 225
Chris@1661 226 void text_xml() {
Chris@1661 227 TextModel m(100, 10, false);
Chris@1661 228 Event p1(20, 1.0f, "text 1");
Chris@1661 229 Event p2(20, 0.0f, "text 2");
Chris@1661 230 Event p3(50, 0.3f, "text 3");
Chris@1661 231 m.add(p1);
Chris@1674 232 m.add(p2.withLevel(0.8f));
Chris@1661 233 m.add(p3);
Chris@1661 234 QString xml;
Chris@1661 235 QTextStream str(&xml, QIODevice::WriteOnly);
Chris@1661 236 m.toXml(str);
Chris@1661 237 str.flush();
Chris@1661 238
Chris@1661 239 QString expected =
Chris@1685 240 "<model id='5' name='' sampleRate='100' start='20' end='60' type='sparse' dimensions='2' resolution='10' notifyOnAdd='true' dataset='4' subtype='text' />\n"
Chris@1685 241 "<dataset id='4' dimensions='2'>\n"
Chris@1661 242 " <point frame='20' height='0' label='text 2' />\n"
Chris@1661 243 " <point frame='20' height='1' label='text 1' />\n"
Chris@1661 244 " <point frame='50' height='0.3' label='text 3' />\n"
Chris@1661 245 "</dataset>\n";
Chris@1661 246 expected.replace("\'", "\"");
Chris@1661 247 if (xml != expected) {
Chris@1661 248 cerr << "Obtained xml:\n" << xml
Chris@1697 249 << "\nExpected:\n" << expected << std::endl;
Chris@1661 250 }
Chris@1661 251 QCOMPARE(xml, expected);
Chris@1661 252 }
Chris@1662 253
Chris@1662 254 void path_xml() {
Chris@1741 255 Path m(100, 10);
Chris@1662 256 PathPoint p1(20, 30);
Chris@1662 257 PathPoint p2(40, 60);
Chris@1662 258 PathPoint p3(50, 49);
Chris@1663 259 m.add(p1);
Chris@1663 260 m.add(p2);
Chris@1663 261 m.add(p3);
Chris@1662 262 QString xml;
Chris@1662 263 QTextStream str(&xml, QIODevice::WriteOnly);
Chris@1662 264 m.toXml(str);
Chris@1662 265 str.flush();
Chris@1662 266
Chris@1662 267 QString expected =
Chris@1685 268 "<model id='6' name='' sampleRate='100' start='20' end='60' type='sparse' dimensions='2' resolution='10' notifyOnAdd='true' dataset='6' subtype='path' />\n"
Chris@1685 269 "<dataset id='6' dimensions='2'>\n"
Chris@1662 270 " <point frame='20' mapframe='30' />\n"
Chris@1662 271 " <point frame='40' mapframe='60' />\n"
Chris@1662 272 " <point frame='50' mapframe='49' />\n"
Chris@1662 273 "</dataset>\n";
Chris@1662 274 expected.replace("\'", "\"");
Chris@1662 275 if (xml != expected) {
Chris@1662 276 cerr << "Obtained xml:\n" << xml
Chris@1697 277 << "\nExpected:\n" << expected << std::endl;
Chris@1662 278 }
Chris@1662 279 QCOMPARE(xml, expected);
Chris@1662 280 }
Chris@1663 281
Chris@1674 282 void image_xml() {
Chris@1674 283 ImageModel m(100, 10, false);
Chris@1674 284 Event p1(20, 30, 40, "a label"); // value + duration should not be saved
Chris@1674 285 m.add(p1.withURI("/path/to/thing.png").withLevel(0.8f));
Chris@1674 286 QString xml;
Chris@1674 287 QTextStream str(&xml, QIODevice::WriteOnly);
Chris@1674 288 m.toXml(str);
Chris@1674 289 str.flush();
Chris@1674 290
Chris@1674 291 QString expected =
Chris@1685 292 "<model id='8' name='' sampleRate='100' start='20' end='30' type='sparse' dimensions='1' resolution='10' notifyOnAdd='true' dataset='7' subtype='image' />\n"
Chris@1685 293 "<dataset id='7' dimensions='1'>\n"
Chris@1674 294 " <point frame='20' label='a label' image='/path/to/thing.png' />\n"
Chris@1674 295 "</dataset>\n";
Chris@1674 296 expected.replace("\'", "\"");
Chris@1674 297 if (xml != expected) {
Chris@1674 298 cerr << "Obtained xml:\n" << xml
Chris@1697 299 << "\nExpected:\n" << expected << std::endl;
Chris@1674 300 }
Chris@1674 301 QCOMPARE(xml, expected);
Chris@1674 302 }
Chris@1611 303 };
Chris@1611 304
Chris@1611 305 #endif