annotate rdf/RDFImporter.cpp @ 488:1c66e199e7d9

* remove some unused code
author Chris Cannam
date Fri, 21 Nov 2008 14:25:33 +0000
parents 3ffce691c9bf
children 82ab61fa9223
rev   line source
Chris@439 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@439 2
Chris@439 3 /*
Chris@439 4 Sonic Visualiser
Chris@439 5 An audio file viewer and annotation editor.
Chris@439 6 Centre for Digital Music, Queen Mary, University of London.
Chris@439 7 This file copyright 2008 QMUL.
Chris@439 8
Chris@439 9 This program is free software; you can redistribute it and/or
Chris@439 10 modify it under the terms of the GNU General Public License as
Chris@439 11 published by the Free Software Foundation; either version 2 of the
Chris@439 12 License, or (at your option) any later version. See the file
Chris@439 13 COPYING included with this distribution for more information.
Chris@439 14 */
Chris@439 15
Chris@439 16 #include "RDFImporter.h"
Chris@439 17
Chris@439 18 #include <map>
Chris@439 19 #include <vector>
Chris@439 20
Chris@439 21 #include <iostream>
Chris@439 22 #include <cmath>
Chris@439 23
Chris@439 24 #include "SimpleSPARQLQuery.h"
Chris@439 25
Chris@439 26 #include "base/ProgressReporter.h"
Chris@439 27 #include "base/RealTime.h"
Chris@439 28
Chris@439 29 #include "data/model/SparseOneDimensionalModel.h"
Chris@439 30 #include "data/model/SparseTimeValueModel.h"
Chris@439 31 #include "data/model/EditableDenseThreeDimensionalModel.h"
Chris@449 32 #include "data/model/NoteModel.h"
Chris@449 33 #include "data/model/RegionModel.h"
Chris@439 34
Chris@439 35 using std::cerr;
Chris@439 36 using std::endl;
Chris@439 37
Chris@439 38 class RDFImporterImpl
Chris@439 39 {
Chris@439 40 public:
Chris@439 41 RDFImporterImpl(QString url, int sampleRate);
Chris@439 42 virtual ~RDFImporterImpl();
Chris@439 43
Chris@439 44 bool isOK();
Chris@439 45 QString getErrorString() const;
Chris@439 46
Chris@439 47 std::vector<Model *> getDataModels(ProgressReporter *);
Chris@439 48
Chris@439 49 protected:
Chris@439 50 QString m_uristring;
Chris@439 51 QString m_errorString;
Chris@439 52 int m_sampleRate;
Chris@439 53
Chris@440 54 void getDataModelsSparse(std::vector<Model *> &, ProgressReporter *);
Chris@440 55 void getDataModelsDense(std::vector<Model *> &, ProgressReporter *);
Chris@440 56
Chris@440 57 void getDenseFeatureProperties(QString featureUri,
Chris@440 58 int &sampleRate, int &windowLength,
Chris@440 59 int &hopSize, int &width, int &height);
Chris@440 60
Chris@449 61
Chris@449 62 void fillModel(Model *, long, long, bool, std::vector<float> &, QString);
Chris@439 63 };
Chris@439 64
Chris@439 65
Chris@439 66 QString
Chris@439 67 RDFImporter::getKnownExtensions()
Chris@439 68 {
Chris@439 69 return "*.rdf *.n3 *.ttl";
Chris@439 70 }
Chris@439 71
Chris@439 72 RDFImporter::RDFImporter(QString url, int sampleRate) :
Chris@439 73 m_d(new RDFImporterImpl(url, sampleRate))
Chris@439 74 {
Chris@439 75 }
Chris@439 76
Chris@439 77 RDFImporter::~RDFImporter()
Chris@439 78 {
Chris@439 79 delete m_d;
Chris@439 80 }
Chris@439 81
Chris@439 82 bool
Chris@439 83 RDFImporter::isOK()
Chris@439 84 {
Chris@439 85 return m_d->isOK();
Chris@439 86 }
Chris@439 87
Chris@439 88 QString
Chris@439 89 RDFImporter::getErrorString() const
Chris@439 90 {
Chris@439 91 return m_d->getErrorString();
Chris@439 92 }
Chris@439 93
Chris@439 94 std::vector<Model *>
Chris@439 95 RDFImporter::getDataModels(ProgressReporter *r)
Chris@439 96 {
Chris@439 97 return m_d->getDataModels(r);
Chris@439 98 }
Chris@439 99
Chris@439 100 RDFImporterImpl::RDFImporterImpl(QString uri, int sampleRate) :
Chris@439 101 m_uristring(uri),
Chris@439 102 m_sampleRate(sampleRate)
Chris@439 103 {
Chris@439 104 }
Chris@439 105
Chris@439 106 RDFImporterImpl::~RDFImporterImpl()
Chris@439 107 {
Chris@439 108 }
Chris@439 109
Chris@439 110 bool
Chris@439 111 RDFImporterImpl::isOK()
Chris@439 112 {
Chris@439 113 return (m_errorString == "");
Chris@439 114 }
Chris@439 115
Chris@439 116 QString
Chris@439 117 RDFImporterImpl::getErrorString() const
Chris@439 118 {
Chris@439 119 return m_errorString;
Chris@439 120 }
Chris@439 121
Chris@439 122 std::vector<Model *>
Chris@439 123 RDFImporterImpl::getDataModels(ProgressReporter *reporter)
Chris@439 124 {
Chris@439 125 std::vector<Model *> models;
Chris@439 126
Chris@440 127 getDataModelsDense(models, reporter);
Chris@440 128
Chris@440 129 QString error;
Chris@440 130 if (!isOK()) error = m_errorString;
Chris@440 131 m_errorString = "";
Chris@440 132
Chris@440 133 getDataModelsSparse(models, reporter);
Chris@440 134
Chris@440 135 if (isOK()) m_errorString = error;
Chris@440 136
Chris@440 137 return models;
Chris@440 138 }
Chris@440 139
Chris@440 140 void
Chris@440 141 RDFImporterImpl::getDataModelsDense(std::vector<Model *> &models,
Chris@440 142 ProgressReporter *reporter)
Chris@440 143 {
Chris@440 144 SimpleSPARQLQuery query = SimpleSPARQLQuery
Chris@480 145 (m_uristring,
Chris@480 146 QString
Chris@440 147 (
Chris@440 148 " PREFIX mo: <http://purl.org/ontology/mo/>"
Chris@440 149 " PREFIX af: <http://purl.org/ontology/af/>"
Chris@440 150
Chris@440 151 " SELECT ?feature ?signal_source ?feature_signal_type ?value "
Chris@440 152 " FROM <%1> "
Chris@440 153
Chris@440 154 " WHERE { "
Chris@440 155
Chris@440 156 " ?signal a mo:Signal ; "
Chris@440 157 " mo:available_as ?signal_source ; "
Chris@440 158 " af:signal_feature ?feature . "
Chris@440 159
Chris@440 160 " ?feature a ?feature_signal_type ; "
Chris@440 161 " af:value ?value . "
Chris@440 162
Chris@440 163 " } "
Chris@440 164 )
Chris@440 165 .arg(m_uristring));
Chris@440 166
Chris@440 167 SimpleSPARQLQuery::ResultList results = query.execute();
Chris@440 168
Chris@440 169 if (!query.isOK()) {
Chris@440 170 m_errorString = query.getErrorString();
Chris@440 171 return;
Chris@440 172 }
Chris@440 173
Chris@440 174 if (query.wasCancelled()) {
Chris@440 175 m_errorString = "Query cancelled";
Chris@440 176 return;
Chris@440 177 }
Chris@440 178
Chris@440 179 for (int i = 0; i < results.size(); ++i) {
Chris@440 180
Chris@440 181 QString feature = results[i]["feature"].value;
Chris@440 182 QString source = results[i]["signal_source"].value;
Chris@440 183 QString type = results[i]["feature_signal_type"].value;
Chris@440 184 QString value = results[i]["value"].value;
Chris@440 185
Chris@440 186 int sampleRate = 0;
Chris@440 187 int windowLength = 0;
Chris@440 188 int hopSize = 0;
Chris@440 189 int width = 0;
Chris@440 190 int height = 0;
Chris@440 191 getDenseFeatureProperties
Chris@440 192 (feature, sampleRate, windowLength, hopSize, width, height);
Chris@440 193
Chris@440 194 if (sampleRate != 0 && sampleRate != m_sampleRate) {
Chris@440 195 cerr << "WARNING: Sample rate in dense feature description does not match our underlying rate -- using rate from feature description" << endl;
Chris@440 196 }
Chris@440 197 if (sampleRate == 0) sampleRate = m_sampleRate;
Chris@440 198
Chris@440 199 if (hopSize == 0) {
Chris@440 200 cerr << "WARNING: Dense feature description does not specify a hop size -- assuming 1" << endl;
Chris@440 201 hopSize = 1;
Chris@440 202 }
Chris@440 203
Chris@440 204 if (height == 0) {
Chris@440 205 cerr << "WARNING: Dense feature description does not specify feature signal dimensions -- assuming one-dimensional (height = 1)" << endl;
Chris@440 206 height = 1;
Chris@440 207 }
Chris@440 208
Chris@440 209 QStringList values = value.split(' ', QString::SkipEmptyParts);
Chris@440 210
Chris@440 211 if (values.empty()) {
Chris@440 212 cerr << "WARNING: Dense feature description does not specify any values!" << endl;
Chris@440 213 continue;
Chris@440 214 }
Chris@440 215
Chris@440 216 if (height == 1) {
Chris@440 217
Chris@440 218 SparseTimeValueModel *m = new SparseTimeValueModel
Chris@440 219 (sampleRate, hopSize, false);
Chris@440 220
Chris@440 221 for (int j = 0; j < values.size(); ++j) {
Chris@440 222 float f = values[j].toFloat();
Chris@440 223 SparseTimeValueModel::Point point(j * hopSize, f, "");
Chris@440 224 m->addPoint(point);
Chris@440 225 }
Chris@440 226
Chris@440 227 models.push_back(m);
Chris@440 228
Chris@440 229 } else {
Chris@440 230
Chris@440 231 EditableDenseThreeDimensionalModel *m =
Chris@440 232 new EditableDenseThreeDimensionalModel(sampleRate, hopSize,
Chris@440 233 height, false);
Chris@440 234
Chris@440 235 EditableDenseThreeDimensionalModel::Column column;
Chris@440 236
Chris@440 237 int x = 0;
Chris@440 238
Chris@440 239 for (int j = 0; j < values.size(); ++j) {
Chris@440 240 if (j % height == 0 && !column.empty()) {
Chris@440 241 m->setColumn(x++, column);
Chris@440 242 column.clear();
Chris@440 243 }
Chris@440 244 column.push_back(values[j].toFloat());
Chris@440 245 }
Chris@440 246
Chris@440 247 if (!column.empty()) {
Chris@440 248 m->setColumn(x++, column);
Chris@440 249 }
Chris@440 250
Chris@440 251 models.push_back(m);
Chris@440 252 }
Chris@440 253 }
Chris@440 254 }
Chris@440 255
Chris@440 256 void
Chris@440 257 RDFImporterImpl::getDenseFeatureProperties(QString featureUri,
Chris@440 258 int &sampleRate, int &windowLength,
Chris@440 259 int &hopSize, int &width, int &height)
Chris@440 260 {
Chris@440 261 QString dimensionsQuery
Chris@440 262 (
Chris@440 263 " PREFIX mo: <http://purl.org/ontology/mo/>"
Chris@440 264 " PREFIX af: <http://purl.org/ontology/af/>"
Chris@440 265
Chris@440 266 " SELECT ?dimensions "
Chris@440 267 " FROM <%1> "
Chris@440 268
Chris@440 269 " WHERE { "
Chris@440 270
Chris@440 271 " <%2> af:dimensions ?dimensions . "
Chris@440 272
Chris@440 273 " } "
Chris@440 274 );
Chris@440 275
Chris@440 276 SimpleSPARQLQuery::Value dimensionsValue =
Chris@480 277 SimpleSPARQLQuery::singleResultQuery(m_uristring,
Chris@480 278 dimensionsQuery
Chris@440 279 .arg(m_uristring).arg(featureUri),
Chris@440 280 "dimensions");
Chris@440 281
Chris@440 282 cerr << "Dimensions = \"" << dimensionsValue.value.toStdString() << "\""
Chris@440 283 << endl;
Chris@440 284
Chris@440 285 if (dimensionsValue.value != "") {
Chris@440 286 QStringList dl = dimensionsValue.value.split(" ");
Chris@440 287 if (dl.empty()) dl.push_back(dimensionsValue.value);
Chris@440 288 if (dl.size() > 0) height = dl[0].toInt();
Chris@440 289 if (dl.size() > 1) width = dl[1].toInt();
Chris@440 290 }
Chris@440 291
Chris@440 292 QString queryTemplate
Chris@440 293 (
Chris@440 294 " PREFIX mo: <http://purl.org/ontology/mo/>"
Chris@440 295 " PREFIX af: <http://purl.org/ontology/af/>"
Chris@440 296 " PREFIX tl: <http://purl.org/NET/c4dm/timeline.owl#>"
Chris@440 297
Chris@440 298 " SELECT ?%3 "
Chris@440 299 " FROM <%1> "
Chris@440 300
Chris@440 301 " WHERE { "
Chris@440 302
Chris@440 303 " <%2> mo:time ?time . "
Chris@440 304
Chris@440 305 " ?time a tl:Interval ; "
Chris@440 306 " tl:onTimeLine ?timeline . "
Chris@440 307
Chris@440 308 " ?map tl:rangeTimeLine ?timeline . "
Chris@440 309
Chris@440 310 " ?map tl:%3 ?%3 . "
Chris@440 311
Chris@440 312 " } "
Chris@440 313 );
Chris@440 314
Chris@440 315 // Another laborious workaround for rasqal's failure to handle
Chris@440 316 // multiple optionals properly
Chris@440 317
Chris@440 318 SimpleSPARQLQuery::Value srValue =
Chris@480 319 SimpleSPARQLQuery::singleResultQuery(m_uristring,
Chris@480 320 queryTemplate
Chris@440 321 .arg(m_uristring).arg(featureUri)
Chris@440 322 .arg("sampleRate"),
Chris@440 323 "sampleRate");
Chris@440 324 if (srValue.value != "") {
Chris@440 325 sampleRate = srValue.value.toInt();
Chris@440 326 }
Chris@440 327
Chris@440 328 SimpleSPARQLQuery::Value hopValue =
Chris@480 329 SimpleSPARQLQuery::singleResultQuery(m_uristring,
Chris@480 330 queryTemplate
Chris@440 331 .arg(m_uristring).arg(featureUri)
Chris@440 332 .arg("hopSize"),
Chris@440 333 "hopSize");
Chris@440 334 if (srValue.value != "") {
Chris@440 335 hopSize = hopValue.value.toInt();
Chris@440 336 }
Chris@440 337
Chris@440 338 SimpleSPARQLQuery::Value winValue =
Chris@480 339 SimpleSPARQLQuery::singleResultQuery(m_uristring,
Chris@480 340 queryTemplate
Chris@440 341 .arg(m_uristring).arg(featureUri)
Chris@440 342 .arg("windowLength"),
Chris@440 343 "windowLength");
Chris@440 344 if (winValue.value != "") {
Chris@440 345 windowLength = winValue.value.toInt();
Chris@440 346 }
Chris@440 347
Chris@440 348 cerr << "sr = " << sampleRate << ", hop = " << hopSize << ", win = " << windowLength << endl;
Chris@440 349 }
Chris@440 350
Chris@440 351 void
Chris@440 352 RDFImporterImpl::getDataModelsSparse(std::vector<Model *> &models,
Chris@440 353 ProgressReporter *reporter)
Chris@440 354 {
Chris@439 355 // Our query is intended to retrieve every thing that has a time,
Chris@439 356 // and every feature type and value associated with a thing that
Chris@439 357 // has a time.
Chris@439 358
Chris@439 359 // We will then need to refine this big bag of results into a set
Chris@439 360 // of data models.
Chris@439 361
Chris@439 362 // Results that have different source signals should go into
Chris@439 363 // different models.
Chris@439 364
Chris@439 365 // Results that have different feature types should go into
Chris@439 366 // different models.
Chris@439 367
Chris@439 368 // Results that are sparse should go into different models from
Chris@439 369 // those that are dense (we need to examine the timestamps to
Chris@439 370 // establish this -- if the timestamps are regular, the results
Chris@439 371 // are dense -- so we can't do it as we go along, only after
Chris@439 372 // collecting all results).
Chris@439 373
Chris@439 374 // Timed things that have features associated with them should not
Chris@439 375 // appear directly in any model -- their features should appear
Chris@439 376 // instead -- and these should be different models from those used
Chris@439 377 // for timed things that do not have features.
Chris@439 378
Chris@439 379 // As we load the results, we'll push them into a partially
Chris@439 380 // structured container that maps from source signal (URI as
Chris@439 381 // string) -> feature type (likewise) -> time -> list of values.
Chris@439 382 // If the source signal or feature type is unavailable, the empty
Chris@439 383 // string will do.
Chris@439 384
Chris@449 385 QString prefixes = QString(
Chris@439 386 " PREFIX event: <http://purl.org/NET/c4dm/event.owl#>"
Chris@449 387 " PREFIX tl: <http://purl.org/NET/c4dm/timeline.owl#>"
Chris@439 388 " PREFIX mo: <http://purl.org/ontology/mo/>"
Chris@439 389 " PREFIX af: <http://purl.org/ontology/af/>"
Chris@449 390 " PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>"
Chris@449 391 );
Chris@439 392
Chris@449 393 QString queryString = prefixes + QString(
Chris@449 394
Chris@449 395 " SELECT ?signal_source ?timed_thing ?event_type ?value"
Chris@439 396 " FROM <%1>"
Chris@439 397
Chris@439 398 " WHERE {"
Chris@440 399
Chris@440 400 " ?signal mo:available_as ?signal_source ."
Chris@440 401 " ?signal a mo:Signal ."
Chris@440 402
Chris@439 403 " ?signal mo:time ?interval ."
Chris@449 404 " ?interval tl:onTimeLine ?tl ."
Chris@449 405 " ?time tl:onTimeLine ?tl ."
Chris@449 406 " ?timed_thing event:time ?time ."
Chris@440 407 " ?timed_thing a ?event_type ."
Chris@440 408
Chris@439 409 " OPTIONAL {"
Chris@440 410 " ?timed_thing af:feature ?value"
Chris@439 411 " }"
Chris@439 412 " }"
Chris@439 413
Chris@439 414 ).arg(m_uristring);
Chris@439 415
Chris@449 416 QString timeQueryString = prefixes + QString(
Chris@449 417
Chris@449 418 " SELECT ?time FROM <%1> "
Chris@449 419 " WHERE { "
Chris@449 420 " <%2> event:time ?t . "
Chris@449 421 " ?t tl:at ?time . "
Chris@449 422 " } "
Chris@449 423
Chris@449 424 ).arg(m_uristring);
Chris@449 425
Chris@449 426 QString rangeQueryString = prefixes + QString(
Chris@449 427
Chris@449 428 " SELECT ?time ?duration FROM <%1> "
Chris@449 429 " WHERE { "
Chris@449 430 " <%2> event:time ?t . "
Chris@449 431 " ?t tl:beginsAt ?time . "
Chris@449 432 " ?t tl:duration ?duration . "
Chris@449 433 " } "
Chris@449 434
Chris@449 435 ).arg(m_uristring);
Chris@449 436
Chris@449 437 QString labelQueryString = prefixes + QString(
Chris@449 438
Chris@449 439 " SELECT ?label FROM <%1> "
Chris@449 440 " WHERE { "
Chris@449 441 " <%2> rdfs:label ?label . "
Chris@449 442 " } "
Chris@449 443
Chris@449 444 ).arg(m_uristring);
Chris@449 445
Chris@480 446 SimpleSPARQLQuery query(m_uristring, queryString);
Chris@439 447 query.setProgressReporter(reporter);
Chris@439 448
Chris@439 449 cerr << "Query will be: " << queryString.toStdString() << endl;
Chris@439 450
Chris@439 451 SimpleSPARQLQuery::ResultList results = query.execute();
Chris@439 452
Chris@439 453 if (!query.isOK()) {
Chris@439 454 m_errorString = query.getErrorString();
Chris@440 455 return;
Chris@439 456 }
Chris@439 457
Chris@439 458 if (query.wasCancelled()) {
Chris@439 459 m_errorString = "Query cancelled";
Chris@440 460 return;
Chris@439 461 }
Chris@439 462
Chris@449 463
Chris@449 464
Chris@449 465 /*
Chris@449 466
Chris@449 467 This function is now only used for sparse data (for dense data
Chris@449 468 we would be in getDataModelsDense instead).
Chris@449 469
Chris@449 470 For sparse data, the determining factors in deciding what model
Chris@449 471 to use are: Do the features have values? and Do the features
Chris@449 472 have duration?
Chris@449 473
Chris@449 474 We can run through the results and check off whether we find
Chris@449 475 values and duration for each of the source+type keys, and then
Chris@449 476 run through the source+type keys pushing each of the results
Chris@449 477 into a suitable model.
Chris@449 478
Chris@449 479 Unfortunately, at this point we do not yet have any actual
Chris@449 480 timing data (time/duration) -- just the time URI.
Chris@449 481
Chris@449 482 What we _could_ do is to create one of each type of model at the
Chris@449 483 start, for each of the source+type keys, and then push each
Chris@449 484 feature into the relevant model depending on what we find out
Chris@449 485 about it. Then return only non-empty models.
Chris@449 486
Chris@449 487
Chris@449 488 */
Chris@449 489
Chris@449 490 // Map from signal source to event type to dimensionality to
Chris@449 491 // presence of duration to model ptr. Whee!
Chris@449 492 std::map<QString, std::map<QString, std::map<int, std::map<bool, Model *> > > >
Chris@449 493 modelMap;
Chris@449 494
Chris@439 495 for (int i = 0; i < results.size(); ++i) {
Chris@439 496
Chris@440 497 QString source = results[i]["signal_source"].value;
Chris@449 498 QString type = results[i]["event_type"].value;
Chris@449 499 QString thinguri = results[i]["timed_thing"].value;
Chris@449 500
Chris@449 501 RealTime time;
Chris@449 502 RealTime duration;
Chris@439 503
Chris@449 504 bool haveTime = false;
Chris@449 505 bool haveDuration = false;
Chris@439 506
Chris@449 507 QString label = SimpleSPARQLQuery::singleResultQuery
Chris@480 508 (m_uristring, labelQueryString.arg(thinguri), "label").value;
Chris@449 509
Chris@480 510 SimpleSPARQLQuery rangeQuery(m_uristring, rangeQueryString.arg(thinguri));
Chris@450 511 SimpleSPARQLQuery::ResultList rangeResults = rangeQuery.execute();
Chris@450 512 if (!rangeResults.empty()) {
Chris@450 513 // std::cerr << rangeResults.size() << " range results" << std::endl;
Chris@450 514 time = RealTime::fromXsdDuration
Chris@450 515 (rangeResults[0]["time"].value.toStdString());
Chris@450 516 duration = RealTime::fromXsdDuration
Chris@450 517 (rangeResults[0]["duration"].value.toStdString());
Chris@450 518 // std::cerr << "duration string " << rangeResults[0]["duration"].value.toStdString() << std::endl;
Chris@449 519 haveTime = true;
Chris@450 520 haveDuration = true;
Chris@449 521 } else {
Chris@450 522 QString timestring = SimpleSPARQLQuery::singleResultQuery
Chris@480 523 (m_uristring, timeQueryString.arg(thinguri), "time").value;
Chris@450 524 if (timestring != "") {
Chris@450 525 time = RealTime::fromXsdDuration(timestring.toStdString());
Chris@449 526 haveTime = true;
Chris@449 527 }
Chris@449 528 }
Chris@439 529
Chris@439 530 QString valuestring = results[i]["value"].value;
Chris@449 531 std::vector<float> values;
Chris@449 532
Chris@439 533 if (valuestring != "") {
Chris@449 534 QStringList vsl = valuestring.split(" ", QString::SkipEmptyParts);
Chris@449 535 for (int j = 0; j < vsl.size(); ++j) {
Chris@449 536 bool success = false;
Chris@449 537 float v = vsl[j].toFloat(&success);
Chris@449 538 if (success) values.push_back(v);
Chris@449 539 }
Chris@439 540 }
Chris@439 541
Chris@449 542 int dimensions = 1;
Chris@449 543 if (values.size() == 1) dimensions = 2;
Chris@449 544 else if (values.size() > 1) dimensions = 3;
Chris@449 545
Chris@449 546 Model *model = 0;
Chris@449 547
Chris@449 548 if (modelMap[source][type][dimensions].find(haveDuration) ==
Chris@449 549 modelMap[source][type][dimensions].end()) {
Chris@449 550
Chris@449 551 /*
Chris@449 552 std::cerr << "Creating new model: source = " << source.toStdString()
Chris@449 553 << ", type = " << type.toStdString() << ", dimensions = "
Chris@449 554 << dimensions << ", haveDuration = " << haveDuration
Chris@449 555 << ", time = " << time << ", duration = " << duration
Chris@449 556 << std::endl;
Chris@449 557 */
Chris@449 558
Chris@449 559 if (!haveDuration) {
Chris@449 560
Chris@449 561 if (dimensions == 1) {
Chris@449 562
Chris@449 563 // std::cerr << "SparseOneDimensionalModel" << std::endl;
Chris@449 564 model = new SparseOneDimensionalModel(m_sampleRate, 1, false);
Chris@449 565
Chris@449 566 } else if (dimensions == 2) {
Chris@449 567
Chris@449 568 // std::cerr << "SparseTimeValueModel" << std::endl;
Chris@449 569 model = new SparseTimeValueModel(m_sampleRate, 1, false);
Chris@449 570
Chris@449 571 } else {
Chris@449 572
Chris@449 573 // We don't have a three-dimensional sparse model,
Chris@449 574 // so use a note model. We do have some logic (in
Chris@449 575 // extractStructure below) for guessing whether
Chris@449 576 // this should after all have been a dense model,
Chris@449 577 // but it's hard to apply it because we don't have
Chris@449 578 // all the necessary timing data yet... hmm
Chris@449 579
Chris@449 580 // std::cerr << "NoteModel" << std::endl;
Chris@449 581 model = new NoteModel(m_sampleRate, 1, false);
Chris@449 582 }
Chris@449 583
Chris@449 584 } else { // haveDuration
Chris@449 585
Chris@449 586 if (dimensions == 1 || dimensions == 2) {
Chris@449 587
Chris@449 588 // If our units are frequency or midi pitch, we
Chris@449 589 // should be using a note model... hm
Chris@449 590
Chris@449 591 // std::cerr << "RegionModel" << std::endl;
Chris@449 592 model = new RegionModel(m_sampleRate, 1, false);
Chris@449 593
Chris@449 594 } else {
Chris@449 595
Chris@449 596 // We don't have a three-dimensional sparse model,
Chris@449 597 // so use a note model. We do have some logic (in
Chris@449 598 // extractStructure below) for guessing whether
Chris@449 599 // this should after all have been a dense model,
Chris@449 600 // but it's hard to apply it because we don't have
Chris@449 601 // all the necessary timing data yet... hmm
Chris@449 602
Chris@449 603 // std::cerr << "NoteModel" << std::endl;
Chris@449 604 model = new NoteModel(m_sampleRate, 1, false);
Chris@449 605 }
Chris@449 606 }
Chris@449 607
Chris@449 608 modelMap[source][type][dimensions][haveDuration] = model;
Chris@449 609 models.push_back(model);
Chris@449 610 }
Chris@449 611
Chris@449 612 model = modelMap[source][type][dimensions][haveDuration];
Chris@449 613
Chris@449 614 if (model) {
Chris@449 615 long ftime = RealTime::realTime2Frame(time, m_sampleRate);
Chris@449 616 long fduration = RealTime::realTime2Frame(duration, m_sampleRate);
Chris@449 617 fillModel(model, ftime, fduration, haveDuration, values, label);
Chris@439 618 }
Chris@439 619 }
Chris@439 620 }
Chris@439 621
Chris@439 622 void
Chris@449 623 RDFImporterImpl::fillModel(Model *model,
Chris@449 624 long ftime,
Chris@449 625 long fduration,
Chris@449 626 bool haveDuration,
Chris@449 627 std::vector<float> &values,
Chris@449 628 QString label)
Chris@449 629 {
Chris@449 630 SparseOneDimensionalModel *sodm =
Chris@449 631 dynamic_cast<SparseOneDimensionalModel *>(model);
Chris@449 632 if (sodm) {
Chris@449 633 SparseOneDimensionalModel::Point point(ftime, label);
Chris@449 634 sodm->addPoint(point);
Chris@449 635 return;
Chris@449 636 }
Chris@449 637
Chris@449 638 SparseTimeValueModel *stvm =
Chris@449 639 dynamic_cast<SparseTimeValueModel *>(model);
Chris@449 640 if (stvm) {
Chris@449 641 SparseTimeValueModel::Point point
Chris@449 642 (ftime, values.empty() ? 0.f : values[0], label);
Chris@449 643 stvm->addPoint(point);
Chris@449 644 return;
Chris@449 645 }
Chris@449 646
Chris@449 647 NoteModel *nm =
Chris@449 648 dynamic_cast<NoteModel *>(model);
Chris@449 649 if (nm) {
Chris@449 650 if (haveDuration) {
Chris@449 651 float value = 0.f, level = 1.f;
Chris@449 652 if (!values.empty()) {
Chris@449 653 value = values[0];
Chris@449 654 if (values.size() > 1) {
Chris@449 655 level = values[1];
Chris@449 656 }
Chris@449 657 }
Chris@449 658 NoteModel::Point point(ftime, value, fduration, level, label);
Chris@449 659 nm->addPoint(point);
Chris@449 660 } else {
Chris@449 661 float value = 0.f, duration = 1.f, level = 1.f;
Chris@449 662 if (!values.empty()) {
Chris@449 663 value = values[0];
Chris@449 664 if (values.size() > 1) {
Chris@449 665 duration = values[1];
Chris@449 666 if (values.size() > 2) {
Chris@449 667 level = values[2];
Chris@449 668 }
Chris@449 669 }
Chris@449 670 }
Chris@449 671 NoteModel::Point point(ftime, value, duration, level, label);
Chris@449 672 nm->addPoint(point);
Chris@449 673 }
Chris@449 674 return;
Chris@449 675 }
Chris@449 676
Chris@449 677 RegionModel *rm =
Chris@449 678 dynamic_cast<RegionModel *>(model);
Chris@449 679 if (rm) {
Chris@449 680 if (haveDuration) {
Chris@449 681 RegionModel::Point point
Chris@449 682 (ftime, values.empty() ? 0.f : values[0], fduration, label);
Chris@449 683 rm->addPoint(point);
Chris@449 684 } else {
Chris@449 685 // This won't actually happen -- we only create region models
Chris@449 686 // if we do have duration -- but just for completeness
Chris@449 687 float value = 0.f, duration = 1.f;
Chris@449 688 if (!values.empty()) {
Chris@449 689 value = values[0];
Chris@449 690 if (values.size() > 1) {
Chris@449 691 duration = values[1];
Chris@449 692 }
Chris@449 693 }
Chris@449 694 RegionModel::Point point(ftime, value, duration, label);
Chris@449 695 rm->addPoint(point);
Chris@449 696 }
Chris@449 697 return;
Chris@449 698 }
Chris@449 699
Chris@449 700 std::cerr << "WARNING: RDFImporterImpl::fillModel: Unknown or unexpected model type" << std::endl;
Chris@449 701 return;
Chris@449 702 }
Chris@449 703
Chris@449 704