svcore
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2008-2012 QMUL. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 00014 */ 00015 00016 #include "RDFImporter.h" 00017 00018 #include <map> 00019 #include <vector> 00020 00021 #include <iostream> 00022 #include <cmath> 00023 00024 #include "base/ProgressReporter.h" 00025 #include "base/RealTime.h" 00026 00027 #include "data/model/SparseOneDimensionalModel.h" 00028 #include "data/model/SparseTimeValueModel.h" 00029 #include "data/model/EditableDenseThreeDimensionalModel.h" 00030 #include "data/model/NoteModel.h" 00031 #include "data/model/TextModel.h" 00032 #include "data/model/RegionModel.h" 00033 #include "data/model/WaveFileModel.h" 00034 00035 #include "data/fileio/FileSource.h" 00036 #include "data/fileio/CachedFile.h" 00037 #include "data/fileio/FileFinder.h" 00038 00039 #include <dataquay/BasicStore.h> 00040 #include <dataquay/PropertyObject.h> 00041 00042 using Dataquay::Uri; 00043 using Dataquay::Node; 00044 using Dataquay::Nodes; 00045 using Dataquay::Triple; 00046 using Dataquay::Triples; 00047 using Dataquay::BasicStore; 00048 using Dataquay::PropertyObject; 00049 00050 class RDFImporterImpl 00051 { 00052 public: 00053 RDFImporterImpl(QString url, int sampleRate); 00054 virtual ~RDFImporterImpl(); 00055 00056 void setSampleRate(int sampleRate) { m_sampleRate = sampleRate; } 00057 00058 bool isOK(); 00059 QString getErrorString() const; 00060 00061 std::vector<Model *> getDataModels(ProgressReporter *); 00062 00063 protected: 00064 BasicStore *m_store; 00065 Uri expand(QString s) { return m_store->expand(s); } 00066 00067 QString m_uristring; 00068 QString m_errorString; 00069 std::map<QString, Model *> m_audioModelMap; 00070 int m_sampleRate; 00071 00072 std::map<Model *, std::map<QString, float> > m_labelValueMap; 00073 00074 void getDataModelsAudio(std::vector<Model *> &, ProgressReporter *); 00075 void getDataModelsSparse(std::vector<Model *> &, ProgressReporter *); 00076 void getDataModelsDense(std::vector<Model *> &, ProgressReporter *); 00077 00078 void getDenseModelTitle(Model *, QString, QString); 00079 00080 void getDenseFeatureProperties(QString featureUri, 00081 int &sampleRate, int &windowLength, 00082 int &hopSize, int &width, int &height); 00083 00084 void fillModel(Model *, long, long, bool, std::vector<float> &, QString); 00085 }; 00086 00087 QString 00088 RDFImporter::getKnownExtensions() 00089 { 00090 return "*.rdf *.n3 *.ttl"; 00091 } 00092 00093 RDFImporter::RDFImporter(QString url, int sampleRate) : 00094 m_d(new RDFImporterImpl(url, sampleRate)) 00095 { 00096 } 00097 00098 RDFImporter::~RDFImporter() 00099 { 00100 delete m_d; 00101 } 00102 00103 void 00104 RDFImporter::setSampleRate(int sampleRate) 00105 { 00106 m_d->setSampleRate(sampleRate); 00107 } 00108 00109 bool 00110 RDFImporter::isOK() 00111 { 00112 return m_d->isOK(); 00113 } 00114 00115 QString 00116 RDFImporter::getErrorString() const 00117 { 00118 return m_d->getErrorString(); 00119 } 00120 00121 std::vector<Model *> 00122 RDFImporter::getDataModels(ProgressReporter *r) 00123 { 00124 return m_d->getDataModels(r); 00125 } 00126 00127 RDFImporterImpl::RDFImporterImpl(QString uri, int sampleRate) : 00128 m_store(new BasicStore), 00129 m_uristring(uri), 00130 m_sampleRate(sampleRate) 00131 { 00133 00134 m_store->addPrefix("mo", Uri("http://purl.org/ontology/mo/")); 00135 m_store->addPrefix("af", Uri("http://purl.org/ontology/af/")); 00136 m_store->addPrefix("dc", Uri("http://purl.org/dc/elements/1.1/")); 00137 m_store->addPrefix("tl", Uri("http://purl.org/NET/c4dm/timeline.owl#")); 00138 m_store->addPrefix("event", Uri("http://purl.org/NET/c4dm/event.owl#")); 00139 m_store->addPrefix("rdfs", Uri("http://www.w3.org/2000/01/rdf-schema#")); 00140 00141 try { 00142 QUrl url; 00143 if (uri.startsWith("file:")) { 00144 url = QUrl(uri); 00145 } else { 00146 url = QUrl::fromLocalFile(uri); 00147 } 00148 m_store->import(url, BasicStore::ImportIgnoreDuplicates); 00149 } catch (std::exception &e) { 00150 m_errorString = e.what(); 00151 } 00152 } 00153 00154 RDFImporterImpl::~RDFImporterImpl() 00155 { 00156 delete m_store; 00157 } 00158 00159 bool 00160 RDFImporterImpl::isOK() 00161 { 00162 return (m_errorString == ""); 00163 } 00164 00165 QString 00166 RDFImporterImpl::getErrorString() const 00167 { 00168 return m_errorString; 00169 } 00170 00171 std::vector<Model *> 00172 RDFImporterImpl::getDataModels(ProgressReporter *reporter) 00173 { 00174 std::vector<Model *> models; 00175 00176 getDataModelsAudio(models, reporter); 00177 00178 if (m_sampleRate == 0) { 00179 m_errorString = QString("Invalid audio data model (is audio file format supported?)"); 00180 cerr << m_errorString << endl; 00181 return models; 00182 } 00183 00184 QString error; 00185 00186 if (m_errorString != "") { 00187 error = m_errorString; 00188 } 00189 m_errorString = ""; 00190 00191 getDataModelsDense(models, reporter); 00192 00193 if (m_errorString != "") { 00194 error = m_errorString; 00195 } 00196 m_errorString = ""; 00197 00198 getDataModelsSparse(models, reporter); 00199 00200 if (m_errorString == "" && error != "") { 00201 m_errorString = error; 00202 } 00203 00204 return models; 00205 } 00206 00207 void 00208 RDFImporterImpl::getDataModelsAudio(std::vector<Model *> &models, 00209 ProgressReporter *reporter) 00210 { 00211 Nodes sigs = m_store->match 00212 (Triple(Node(), Uri("a"), expand("mo:Signal"))).subjects(); 00213 00214 foreach (Node sig, sigs) { 00215 00216 Node file = m_store->complete(Triple(Node(), expand("mo:encodes"), sig)); 00217 if (file == Node()) { 00218 file = m_store->complete(Triple(sig, expand("mo:available_as"), Node())); 00219 } 00220 if (file == Node()) { 00221 cerr << "RDFImporterImpl::getDataModelsAudio: ERROR: No source for signal " << sig << endl; 00222 continue; 00223 } 00224 00225 QString signal = sig.value; 00226 QString source = file.value; 00227 00228 SVDEBUG << "NOTE: Seeking signal source \"" << source 00229 << "\"..." << endl; 00230 00231 FileSource *fs = new FileSource(source, reporter); 00232 if (fs->isAvailable()) { 00233 SVDEBUG << "NOTE: Source is available: Local filename is \"" 00234 << fs->getLocalFilename() 00235 << "\"..." << endl; 00236 } 00237 00238 #ifdef NO_SV_GUI 00239 if (!fs->isAvailable()) { 00240 m_errorString = QString("Signal source \"%1\" is not available").arg(source); 00241 delete fs; 00242 continue; 00243 } 00244 #else 00245 if (!fs->isAvailable()) { 00246 SVDEBUG << "NOTE: Signal source \"" << source 00247 << "\" is not available, using file finder..." << endl; 00248 FileFinder *ff = FileFinder::getInstance(); 00249 if (ff) { 00250 QString path = ff->find(FileFinder::AudioFile, 00251 fs->getLocation(), 00252 m_uristring); 00253 if (path != "") { 00254 cerr << "File finder returns: \"" << path 00255 << "\"" << endl; 00256 delete fs; 00257 fs = new FileSource(path, reporter); 00258 if (!fs->isAvailable()) { 00259 delete fs; 00260 m_errorString = QString("Signal source \"%1\" is not available").arg(source); 00261 continue; 00262 } 00263 } 00264 } 00265 } 00266 #endif 00267 00268 if (reporter) { 00269 reporter->setMessage(RDFImporter::tr("Importing audio referenced in RDF...")); 00270 } 00271 fs->waitForData(); 00272 WaveFileModel *newModel = new WaveFileModel(*fs, m_sampleRate); 00273 if (newModel->isOK()) { 00274 cerr << "Successfully created wave file model from source at \"" << source << "\"" << endl; 00275 models.push_back(newModel); 00276 m_audioModelMap[signal] = newModel; 00277 if (m_sampleRate == 0) { 00278 m_sampleRate = newModel->getSampleRate(); 00279 } 00280 } else { 00281 m_errorString = QString("Failed to create wave file model from source at \"%1\"").arg(source); 00282 delete newModel; 00283 } 00284 delete fs; 00285 } 00286 } 00287 00288 void 00289 RDFImporterImpl::getDataModelsDense(std::vector<Model *> &models, 00290 ProgressReporter *reporter) 00291 { 00292 if (reporter) { 00293 reporter->setMessage(RDFImporter::tr("Importing dense signal data from RDF...")); 00294 } 00295 00296 Nodes sigFeatures = m_store->match 00297 (Triple(Node(), expand("af:signal_feature"), Node())).objects(); 00298 00299 foreach (Node sf, sigFeatures) { 00300 00301 if (sf.type != Node::URI && sf.type != Node::Blank) continue; 00302 00303 Node t = m_store->complete(Triple(sf, expand("a"), Node())); 00304 Node v = m_store->complete(Triple(sf, expand("af:value"), Node())); 00305 00306 QString feature = sf.value; 00307 QString type = t.value; 00308 QString value = v.value; 00309 00310 if (type == "" || value == "") continue; 00311 00312 int sampleRate = 0; 00313 int windowLength = 0; 00314 int hopSize = 0; 00315 int width = 0; 00316 int height = 0; 00317 getDenseFeatureProperties 00318 (feature, sampleRate, windowLength, hopSize, width, height); 00319 00320 if (sampleRate != 0 && sampleRate != m_sampleRate) { 00321 cerr << "WARNING: Sample rate in dense feature description does not match our underlying rate -- using rate from feature description" << endl; 00322 } 00323 if (sampleRate == 0) sampleRate = m_sampleRate; 00324 00325 if (hopSize == 0) { 00326 cerr << "WARNING: Dense feature description does not specify a hop size -- assuming 1" << endl; 00327 hopSize = 1; 00328 } 00329 00330 if (height == 0) { 00331 cerr << "WARNING: Dense feature description does not specify feature signal dimensions -- assuming one-dimensional (height = 1)" << endl; 00332 height = 1; 00333 } 00334 00335 QStringList values = value.split(' ', QString::SkipEmptyParts); 00336 00337 if (values.empty()) { 00338 cerr << "WARNING: Dense feature description does not specify any values!" << endl; 00339 continue; 00340 } 00341 00342 if (height == 1) { 00343 00344 SparseTimeValueModel *m = new SparseTimeValueModel 00345 (sampleRate, hopSize, false); 00346 00347 for (int j = 0; j < values.size(); ++j) { 00348 float f = values[j].toFloat(); 00349 SparseTimeValueModel::Point point(j * hopSize, f, ""); 00350 m->addPoint(point); 00351 } 00352 00353 getDenseModelTitle(m, feature, type); 00354 00355 m->setRDFTypeURI(type); 00356 00357 models.push_back(m); 00358 00359 } else { 00360 00361 EditableDenseThreeDimensionalModel *m = 00362 new EditableDenseThreeDimensionalModel 00363 (sampleRate, hopSize, height, 00364 EditableDenseThreeDimensionalModel::NoCompression, false); 00365 00366 EditableDenseThreeDimensionalModel::Column column; 00367 00368 int x = 0; 00369 00370 for (int j = 0; j < values.size(); ++j) { 00371 if (j % height == 0 && !column.empty()) { 00372 m->setColumn(x++, column); 00373 column.clear(); 00374 } 00375 column.push_back(values[j].toFloat()); 00376 } 00377 00378 if (!column.empty()) { 00379 m->setColumn(x++, column); 00380 } 00381 00382 getDenseModelTitle(m, feature, type); 00383 00384 m->setRDFTypeURI(type); 00385 00386 models.push_back(m); 00387 } 00388 } 00389 } 00390 00391 void 00392 RDFImporterImpl::getDenseModelTitle(Model *m, 00393 QString featureUri, 00394 QString featureTypeUri) 00395 { 00396 Node n = m_store->complete 00397 (Triple(Uri(featureUri), expand("dc:title"), Node())); 00398 00399 if (n.type == Node::Literal && n.value != "") { 00400 SVDEBUG << "RDFImporterImpl::getDenseModelTitle: Title (from signal) \"" << n.value << "\"" << endl; 00401 m->setObjectName(n.value); 00402 return; 00403 } 00404 00405 n = m_store->complete 00406 (Triple(Uri(featureTypeUri), expand("dc:title"), Node())); 00407 00408 if (n.type == Node::Literal && n.value != "") { 00409 SVDEBUG << "RDFImporterImpl::getDenseModelTitle: Title (from signal type) \"" << n.value << "\"" << endl; 00410 m->setObjectName(n.value); 00411 return; 00412 } 00413 00414 SVDEBUG << "RDFImporterImpl::getDenseModelTitle: No title available for feature <" << featureUri << ">" << endl; 00415 } 00416 00417 void 00418 RDFImporterImpl::getDenseFeatureProperties(QString featureUri, 00419 int &sampleRate, int &windowLength, 00420 int &hopSize, int &width, int &height) 00421 { 00422 Node dim = m_store->complete 00423 (Triple(Uri(featureUri), expand("af:dimensions"), Node())); 00424 00425 cerr << "Dimensions = \"" << dim.value << "\"" << endl; 00426 00427 if (dim.type == Node::Literal && dim.value != "") { 00428 QStringList dl = dim.value.split(" "); 00429 if (dl.empty()) dl.push_back(dim.value); 00430 if (dl.size() > 0) height = dl[0].toInt(); 00431 if (dl.size() > 1) width = dl[1].toInt(); 00432 } 00433 00434 // Looking for rate, hop, window from: 00435 // 00436 // ?feature mo:time ?time . 00437 // ?time a tl:Interval . 00438 // ?time tl:onTimeLine ?timeline . 00439 // ?map tl:rangeTimeLine ?timeline . 00440 // ?map tl:sampleRate ?rate . 00441 // ?map tl:hopSize ?hop . 00442 // ?map tl:windowLength ?window . 00443 00444 Node interval = m_store->complete(Triple(Uri(featureUri), expand("mo:time"), Node())); 00445 00446 if (!m_store->contains(Triple(interval, expand("a"), expand("tl:Interval")))) { 00447 cerr << "RDFImporterImpl::getDenseFeatureProperties: Feature time node " 00448 << interval << " is not a tl:Interval" << endl; 00449 return; 00450 } 00451 00452 Node tl = m_store->complete(Triple(interval, expand("tl:onTimeLine"), Node())); 00453 00454 if (tl == Node()) { 00455 cerr << "RDFImporterImpl::getDenseFeatureProperties: Interval node " 00456 << interval << " lacks tl:onTimeLine property" << endl; 00457 return; 00458 } 00459 00460 Node map = m_store->complete(Triple(Node(), expand("tl:rangeTimeLine"), tl)); 00461 00462 if (map == Node()) { 00463 cerr << "RDFImporterImpl::getDenseFeatureProperties: No map for " 00464 << "timeline node " << tl << endl; 00465 } 00466 00467 PropertyObject po(m_store, "tl:", map); 00468 00469 if (po.hasProperty("sampleRate")) { 00470 sampleRate = po.getProperty("sampleRate").toInt(); 00471 } 00472 if (po.hasProperty("hopSize")) { 00473 hopSize = po.getProperty("hopSize").toInt(); 00474 } 00475 if (po.hasProperty("windowLength")) { 00476 windowLength = po.getProperty("windowLength").toInt(); 00477 } 00478 00479 cerr << "sr = " << sampleRate << ", hop = " << hopSize << ", win = " << windowLength << endl; 00480 } 00481 00482 void 00483 RDFImporterImpl::getDataModelsSparse(std::vector<Model *> &models, 00484 ProgressReporter *reporter) 00485 { 00486 if (reporter) { 00487 reporter->setMessage(RDFImporter::tr("Importing event data from RDF...")); 00488 } 00489 00490 /* 00491 This function is only used for sparse data (for dense data we 00492 would be in getDataModelsDense instead). 00493 00494 Our query is intended to retrieve every thing that has a time, 00495 and every feature type and value associated with a thing that 00496 has a time. 00497 00498 We will then need to refine this big bag of results into a set 00499 of data models. 00500 00501 Results that have different source signals should go into 00502 different models. 00503 00504 Results that have different feature types should go into 00505 different models. 00506 */ 00507 00508 Nodes sigs = m_store->match 00509 (Triple(Node(), expand("a"), expand("mo:Signal"))).subjects(); 00510 00511 // Map from timeline uri to event type to dimensionality to 00512 // presence of duration to model ptr. Whee! 00513 std::map<QString, std::map<QString, std::map<int, std::map<bool, Model *> > > > 00514 modelMap; 00515 00516 foreach (Node sig, sigs) { 00517 00518 Node interval = m_store->complete(Triple(sig, expand("mo:time"), Node())); 00519 if (interval == Node()) continue; 00520 00521 Node tl = m_store->complete(Triple(interval, expand("tl:onTimeLine"), Node())); 00522 if (tl == Node()) continue; 00523 00524 Nodes times = m_store->match(Triple(Node(), expand("tl:onTimeLine"), tl)).subjects(); 00525 00526 foreach (Node tn, times) { 00527 00528 Nodes timedThings = m_store->match(Triple(Node(), expand("event:time"), tn)).subjects(); 00529 00530 foreach (Node thing, timedThings) { 00531 00532 Node typ = m_store->complete(Triple(thing, expand("a"), Node())); 00533 if (typ == Node()) continue; 00534 00535 Node valu = m_store->complete(Triple(thing, expand("af:feature"), Node())); 00536 00537 QString source = sig.value; 00538 QString timeline = tl.value; 00539 QString type = typ.value; 00540 QString thinguri = thing.value; 00541 00542 /* 00543 For sparse data, the determining factors in deciding 00544 what model to use are: Do the features have values? 00545 and Do the features have duration? 00546 00547 We can run through the results and check off whether 00548 we find values and duration for each of the 00549 source+type keys, and then run through the 00550 source+type keys pushing each of the results into a 00551 suitable model. 00552 00553 Unfortunately, at this point we do not yet have any 00554 actual timing data (time/duration) -- just the time 00555 URI. 00556 00557 What we _could_ do is to create one of each type of 00558 model at the start, for each of the source+type 00559 keys, and then push each feature into the relevant 00560 model depending on what we find out about it. Then 00561 return only non-empty models. 00562 */ 00563 00564 QString label = ""; 00565 bool text = (type.contains("Text") || type.contains("text")); // Ha, ha 00566 bool note = (type.contains("Note") || type.contains("note")); // Guffaw 00567 00568 if (text) { 00569 label = m_store->complete(Triple(thing, expand("af:text"), Node())).value; 00570 } 00571 00572 if (label == "") { 00573 label = m_store->complete(Triple(thing, expand("rdfs:label"), Node())).value; 00574 } 00575 00576 RealTime time; 00577 RealTime duration; 00578 00579 // bool haveTime = false; 00580 bool haveDuration = false; 00581 00582 Node at = m_store->complete(Triple(tn, expand("tl:at"), Node())); 00583 00584 if (at != Node()) { 00585 time = RealTime::fromXsdDuration(at.value.toStdString()); 00586 // haveTime = true; 00587 } else { 00589 // beginsAt -> start 00590 // onTimeLine -> timeline 00591 00592 Node start = m_store->complete(Triple(tn, expand("tl:beginsAt"), Node())); 00593 Node dur = m_store->complete(Triple(tn, expand("tl:duration"), Node())); 00594 if (start != Node() && dur != Node()) { 00595 time = RealTime::fromXsdDuration 00596 (start.value.toStdString()); 00597 duration = RealTime::fromXsdDuration 00598 (dur.value.toStdString()); 00599 // haveTime = haveDuration = true; 00600 } 00601 } 00602 00603 QString valuestring = valu.value; 00604 std::vector<float> values; 00605 00606 if (valuestring != "") { 00607 QStringList vsl = valuestring.split(" ", QString::SkipEmptyParts); 00608 for (int j = 0; j < vsl.size(); ++j) { 00609 bool success = false; 00610 float v = vsl[j].toFloat(&success); 00611 if (success) values.push_back(v); 00612 } 00613 } 00614 00615 int dimensions = 1; 00616 if (values.size() == 1) dimensions = 2; 00617 else if (values.size() > 1) dimensions = 3; 00618 00619 Model *model = 0; 00620 00621 if (modelMap[timeline][type][dimensions].find(haveDuration) == 00622 modelMap[timeline][type][dimensions].end()) { 00623 00624 /* 00625 SVDEBUG << "Creating new model: source = " << source << ", type = " << type << ", dimensions = " 00626 << dimensions << ", haveDuration = " << haveDuration 00627 << ", time = " << time << ", duration = " << duration 00628 << endl; 00629 */ 00630 00631 if (!haveDuration) { 00632 00633 if (dimensions == 1) { 00634 if (text) { 00635 model = new TextModel(m_sampleRate, 1, false); 00636 } else { 00637 model = new SparseOneDimensionalModel(m_sampleRate, 1, false); 00638 } 00639 } else if (dimensions == 2) { 00640 if (text) { 00641 model = new TextModel(m_sampleRate, 1, false); 00642 } else { 00643 model = new SparseTimeValueModel(m_sampleRate, 1, false); 00644 } 00645 } else { 00646 // We don't have a three-dimensional sparse model, 00647 // so use a note model. We do have some logic (in 00648 // extractStructure below) for guessing whether 00649 // this should after all have been a dense model, 00650 // but it's hard to apply it because we don't have 00651 // all the necessary timing data yet... hmm 00652 model = new NoteModel(m_sampleRate, 1, false); 00653 } 00654 00655 } else { // haveDuration 00656 00657 if (note || (dimensions > 2)) { 00658 model = new NoteModel(m_sampleRate, 1, false); 00659 } else { 00660 // If our units are frequency or midi pitch, we 00661 // should be using a note model... hm 00662 model = new RegionModel(m_sampleRate, 1, false); 00663 } 00664 } 00665 00666 model->setRDFTypeURI(type); 00667 00668 if (m_audioModelMap.find(source) != m_audioModelMap.end()) { 00669 cerr << "source model for " << model << " is " << m_audioModelMap[source] << endl; 00670 model->setSourceModel(m_audioModelMap[source]); 00671 } 00672 00673 QString title = m_store->complete 00674 (Triple(typ, expand("dc:title"), Node())).value; 00675 if (title == "") { 00676 // take it from the end of the event type 00677 title = type; 00678 title.replace(QRegExp("^.*[/#]"), ""); 00679 } 00680 model->setObjectName(title); 00681 00682 modelMap[timeline][type][dimensions][haveDuration] = model; 00683 models.push_back(model); 00684 } 00685 00686 model = modelMap[timeline][type][dimensions][haveDuration]; 00687 00688 if (model) { 00689 long ftime = RealTime::realTime2Frame(time, m_sampleRate); 00690 long fduration = RealTime::realTime2Frame(duration, m_sampleRate); 00691 fillModel(model, ftime, fduration, haveDuration, values, label); 00692 } 00693 } 00694 } 00695 } 00696 } 00697 00698 void 00699 RDFImporterImpl::fillModel(Model *model, 00700 long ftime, 00701 long fduration, 00702 bool haveDuration, 00703 std::vector<float> &values, 00704 QString label) 00705 { 00706 // SVDEBUG << "RDFImporterImpl::fillModel: adding point at frame " << ftime << endl; 00707 00708 SparseOneDimensionalModel *sodm = 00709 dynamic_cast<SparseOneDimensionalModel *>(model); 00710 if (sodm) { 00711 SparseOneDimensionalModel::Point point(ftime, label); 00712 sodm->addPoint(point); 00713 return; 00714 } 00715 00716 TextModel *tm = 00717 dynamic_cast<TextModel *>(model); 00718 if (tm) { 00719 TextModel::Point point 00720 (ftime, 00721 values.empty() ? 0.5f : values[0] < 0.f ? 0.f : values[0] > 1.f ? 1.f : values[0], // I was young and feckless once too 00722 label); 00723 tm->addPoint(point); 00724 return; 00725 } 00726 00727 SparseTimeValueModel *stvm = 00728 dynamic_cast<SparseTimeValueModel *>(model); 00729 if (stvm) { 00730 SparseTimeValueModel::Point point 00731 (ftime, values.empty() ? 0.f : values[0], label); 00732 stvm->addPoint(point); 00733 return; 00734 } 00735 00736 NoteModel *nm = 00737 dynamic_cast<NoteModel *>(model); 00738 if (nm) { 00739 if (haveDuration) { 00740 float value = 0.f, level = 1.f; 00741 if (!values.empty()) { 00742 value = values[0]; 00743 if (values.size() > 1) { 00744 level = values[1]; 00745 } 00746 } 00747 NoteModel::Point point(ftime, value, fduration, level, label); 00748 nm->addPoint(point); 00749 } else { 00750 float value = 0.f, duration = 1.f, level = 1.f; 00751 if (!values.empty()) { 00752 value = values[0]; 00753 if (values.size() > 1) { 00754 duration = values[1]; 00755 if (values.size() > 2) { 00756 level = values[2]; 00757 } 00758 } 00759 } 00760 NoteModel::Point point(ftime, value, duration, level, label); 00761 nm->addPoint(point); 00762 } 00763 return; 00764 } 00765 00766 RegionModel *rm = 00767 dynamic_cast<RegionModel *>(model); 00768 if (rm) { 00769 float value = 0.f; 00770 if (values.empty()) { 00771 // no values? map each unique label to a distinct value 00772 if (m_labelValueMap[model].find(label) == m_labelValueMap[model].end()) { 00773 m_labelValueMap[model][label] = rm->getValueMaximum() + 1.f; 00774 } 00775 value = m_labelValueMap[model][label]; 00776 } else { 00777 value = values[0]; 00778 } 00779 if (haveDuration) { 00780 RegionModel::Point point(ftime, value, fduration, label); 00781 rm->addPoint(point); 00782 } else { 00783 // This won't actually happen -- we only create region models 00784 // if we do have duration -- but just for completeness 00785 float duration = 1.f; 00786 if (!values.empty()) { 00787 value = values[0]; 00788 if (values.size() > 1) { 00789 duration = values[1]; 00790 } 00791 } 00792 RegionModel::Point point(ftime, value, duration, label); 00793 rm->addPoint(point); 00794 } 00795 return; 00796 } 00797 00798 cerr << "WARNING: RDFImporterImpl::fillModel: Unknown or unexpected model type" << endl; 00799 return; 00800 } 00801 00802 RDFImporter::RDFDocumentType 00803 RDFImporter::identifyDocumentType(QString url) 00804 { 00805 bool haveAudio = false; 00806 bool haveAnnotations = false; 00807 bool haveRDF = false; 00808 00809 BasicStore *store = 0; 00810 00811 // This is not expected to return anything useful, but if it does 00812 // anything at all then we know we have RDF 00813 try { 00815 store = BasicStore::load(QUrl(url)); 00816 Triple t = store->matchOnce(Triple()); 00817 if (t != Triple()) haveRDF = true; 00818 } catch (std::exception &e) { 00819 // nothing; haveRDF will be false so the next bit catches it 00820 } 00821 00822 if (!haveRDF) { 00823 delete store; 00824 return NotRDF; 00825 } 00826 00827 store->addPrefix("mo", Uri("http://purl.org/ontology/mo/")); 00828 store->addPrefix("event", Uri("http://purl.org/NET/c4dm/event.owl#")); 00829 store->addPrefix("af", Uri("http://purl.org/ontology/af/")); 00830 00831 // "MO-conformant" structure for audio files 00832 00833 Node n = store->complete(Triple(Node(), Uri("a"), store->expand("mo:AudioFile"))); 00834 if (n != Node() && n.type == Node::URI) { 00835 00836 haveAudio = true; 00837 00838 } else { 00839 00840 // Sonic Annotator v0.2 and below used to write this structure 00841 // (which is not properly in conformance with the Music 00842 // Ontology) 00843 00844 Nodes sigs = store->match(Triple(Node(), Uri("a"), store->expand("mo:Signal"))).subjects(); 00845 foreach (Node sig, sigs) { 00846 Node aa = store->complete(Triple(sig, store->expand("mo:available_as"), Node())); 00847 if (aa != Node()) { 00848 haveAudio = true; 00849 break; 00850 } 00851 } 00852 } 00853 00854 SVDEBUG << "NOTE: RDFImporter::identifyDocumentType: haveAudio = " 00855 << haveAudio << endl; 00856 00857 // can't call complete() with two Nothing nodes 00858 n = store->matchOnce(Triple(Node(), store->expand("event:time"), Node())).c; 00859 if (n != Node()) { 00860 haveAnnotations = true; 00861 } 00862 00863 if (!haveAnnotations) { 00864 // can't call complete() with two Nothing nodes 00865 n = store->matchOnce(Triple(Node(), store->expand("af:signal_feature"), Node())).c; 00866 if (n != Node()) { 00867 haveAnnotations = true; 00868 } 00869 } 00870 00871 SVDEBUG << "NOTE: RDFImporter::identifyDocumentType: haveAnnotations = " 00872 << haveAnnotations << endl; 00873 00874 delete store; 00875 00876 if (haveAudio) { 00877 if (haveAnnotations) { 00878 return AudioRefAndAnnotations; 00879 } else { 00880 return AudioRef; 00881 } 00882 } else { 00883 if (haveAnnotations) { 00884 return Annotations; 00885 } else { 00886 return OtherRDFDocument; 00887 } 00888 } 00889 00890 return OtherRDFDocument; 00891 } 00892