24 #include <QTextStream> 32 using Vamp::PluginBase;
36 SupportOneFilePerTrack |
42 m_networkRetrieved(false),
54 return "Write output in Audio Features Ontology RDF/Turtle format.";
64 p.
description =
"Use \"plain\" RDF even if transform metadata is available.";
68 p.
name =
"audiofile-uri";
69 p.
description =
"Link the output RDF to the given audio file URI instead of its actual location.";
74 p.
description =
"Link the output RDF to the given track URI.";
79 p.
description =
"Link the track in the output RDF to the given foaf:maker URI.";
84 p.
description =
"Attempt to retrieve RDF descriptions of plugins from network, if not available locally";
96 for (map<string, string>::iterator i = params.begin();
97 i != params.end(); ++i) {
98 if (i->first ==
"plain") {
101 if (i->first ==
"audiofile-uri") {
104 if (i->first ==
"track-uri") {
107 if (i->first ==
"maker-uri") {
110 if (i->first ==
"network") {
133 const Plugin::OutputDescriptor& output,
134 const Plugin::FeatureList& features,
135 std::string summaryType)
149 SVCERR <<
"NOTE: Have RDF description for plugin ID \"" 150 << pluginId <<
"\"" << endl;
152 SVCERR <<
"NOTE: No RDF description for plugin ID \"" 153 << pluginId <<
"\"" << endl;
155 SVCERR <<
" Consider using the --rdf-network option to retrieve plugin descriptions" << endl;
156 SVCERR <<
" from the network where possible." << endl;
165 QTextCodec::codecForName(
"UTF-8"));
196 if (timelineURI ==
"") {
197 SVCERR <<
"RDFFeatureWriter: INTERNAL ERROR: writing features without having established a timeline URI!" << endl;
201 if (summaryType !=
"") {
208 (output.identifier.c_str()) ==
213 if (signalURI ==
"") {
214 SVCERR <<
"RDFFeatureWriter: INTERNAL ERROR: writing dense features without having established a signal URI!" << endl;
224 (output.identifier.c_str()) ==
227 (output.identifier.c_str()) !=
"") {
231 if (signalURI ==
"") {
232 SVCERR <<
"RDFFeatureWriter: INTERNAL ERROR: writing track-level features without having established a signal URI!" << endl;
249 QTextStream &stream = *sptr;
251 stream <<
"@prefix dc: <http://purl.org/dc/elements/1.1/> .\n" 252 <<
"@prefix mo: <http://purl.org/ontology/mo/> .\n" 253 <<
"@prefix af: <http://purl.org/ontology/af/> .\n" 254 <<
"@prefix foaf: <http://xmlns.com/foaf/0.1/> . \n" 255 <<
"@prefix event: <http://purl.org/NET/c4dm/event.owl#> .\n" 256 <<
"@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n" 257 <<
"@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n" 258 <<
"@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n" 259 <<
"@prefix tl: <http://purl.org/NET/c4dm/timeline.owl#> .\n" 260 <<
"@prefix vamp: <http://purl.org/ontology/vamp/> .\n" 261 <<
"@prefix : <#> .\n\n";
274 QFile file(filename);
277 if (!file.open(QIODevice::ReadOnly))
return;
279 QTextStream in(&file);
281 QRegExp localObjectUriWithDigits(
":[^ ]+_([0-9]+) a ");
283 while (!in.atEnd()) {
284 QString line = in.readLine();
285 if (line.length() > 120) {
288 if (localObjectUriWithDigits.indexIn(line) > -1) {
289 QString numeric = localObjectUriWithDigits.cap(1);
290 int number = numeric.toInt();
304 QTextStream &stream = *sptr;
310 QUrl url(trackId, QUrl::StrictMode);
311 QString scheme = url.scheme().toLower();
312 bool local = (scheme ==
"" || scheme ==
"file" || scheme.length() == 1);
316 url.setScheme(
"file");
317 url.setPath(QFileInfo(url.path()).absoluteFilePath());
318 }
else if (scheme.length() == 1) {
319 url.setScheme(
"file");
320 url.setPath(scheme +
":" + url.path());
326 unsigned long signalCount =
m_count++;
338 bool userSpecifiedTrack =
false;
342 userSpecifiedTrack =
true;
350 QString afURI = url.toEncoded().data();
353 bool wantTrack = (userSpecifiedTrack ||
373 stream << trackURI <<
" a mo:Track ";
374 if (tm.
title !=
"") {
375 stream <<
";\n dc:title \"\"\"" << tm.
title <<
"\"\"\" ";
379 }
else if (tm.
maker !=
"") {
380 stream <<
";\n foaf:maker [ a mo:MusicArtist; foaf:name \"\"\"" << tm.
maker <<
"\"\"\" ] ";
383 stream <<
";\n mo:available_as <" << afURI <<
"> ";
389 stream <<
"<" << afURI <<
"> a mo:AudioFile ;\n";
390 stream <<
" mo:encodes " << signalURI <<
".\n\n";
393 stream << signalURI <<
" a mo:Signal ;\n";
395 stream <<
" mo:time [\n" 396 <<
" a tl:Interval ;\n" 398 << timelineURI <<
"\n ] .\n\n";
400 stream << timelineURI <<
" a tl:Timeline .\n\n";
406 const Plugin::OutputDescriptor &od,
408 std::string summaryType)
410 QString outputId = od.identifier.c_str();
411 QTextStream &stream = *sptr;
418 bool needEventType =
false;
419 bool needSignalType =
false;
423 if (summaryType ==
"" &&
432 needSignalType =
true;
436 needSignalType =
true;
447 needEventType =
true;
453 needEventType =
true;
463 needEventType =
true;
467 needEventType =
true;
471 QString transformUri;
475 transformUri = QString(
":transform_%1_%2").arg(
m_count++).arg(outputId);
492 uri = QString(
":event_type_%1").arg(
m_count++);
497 <<
" rdfs:subClassOf event:Event ;" << endl
498 <<
" dc:title \"" << od.name.c_str() <<
"\" ;" << endl
499 <<
" dc:format \"" << od.unit.c_str() <<
"\" ;" << endl
500 <<
" dc:description \"" << od.description.c_str() <<
"\" ." 504 if (needSignalType) {
511 uri = QString(
":signal_type_%1").arg(
m_count++);
516 <<
" rdfs:subClassOf af:Signal ;" << endl
517 <<
" dc:title \"" << od.name.c_str() <<
"\" ;" << endl
518 <<
" dc:format \"" << od.unit.c_str() <<
"\" ;" << endl
519 <<
" dc:description \"" << od.description.c_str() <<
"\" ." 527 const Plugin::OutputDescriptor& od,
528 const Plugin::FeatureList& featureList,
534 if (featureList.empty())
return;
535 QTextStream &stream = *sptr;
539 QString outputId = od.identifier.c_str();
543 for (
int i = 0; i < (int)featureList.size(); ++i) {
545 const Plugin::Feature &feature = featureList[i];
546 unsigned long featureNumber =
m_count++;
548 stream <<
":event_" << featureNumber <<
" a ";
554 if (plain || eventTypeURI ==
"") {
559 stream <<
":event_type_" << outputId <<
" ;\n";
562 stream <<
"<" << eventTypeURI <<
"> ;\n";
566 QString timestamp = feature.timestamp.toString().c_str();
567 timestamp.replace(QRegExp(
"^ +"),
"");
569 if (feature.hasDuration && feature.duration > Vamp::RealTime::zeroTime) {
571 QString duration = feature.duration.toString().c_str();
572 duration.replace(QRegExp(
"^ +"),
"");
574 stream <<
" event:time [ \n" 575 <<
" a tl:Interval ;\n" 576 <<
" tl:onTimeLine " << timelineURI <<
" ;\n" 577 <<
" tl:beginsAt \"PT" << timestamp
578 <<
"S\"^^xsd:duration ;\n" 579 <<
" tl:duration \"PT" << duration
580 <<
"S\"^^xsd:duration ;\n" 585 stream <<
" event:time [ \n" 586 <<
" a tl:Instant ;\n" 587 <<
" tl:onTimeLine " << timelineURI <<
" ;\n" 588 <<
" tl:at \"PT" << timestamp
589 <<
"S\"^^xsd:duration ;\n ] ";
597 if (feature.label.length() > 0) {
599 stream <<
" rdfs:label \"\"\"" << feature.label.c_str() <<
"\"\"\" ";
602 if (!feature.values.empty()) {
605 stream <<
" af:feature \"" << feature.values[0];
606 for (
int j = 1; j < (int)feature.values.size(); ++j) {
607 stream <<
" " << feature.values[j];
619 const Plugin::OutputDescriptor& od,
620 const Plugin::FeatureList& featureList,
624 if (featureList.empty())
return;
625 QTextStream &stream = *sptr;
629 QString outputId = od.identifier.c_str();
632 if (featureUri ==
"") {
633 SVDEBUG <<
"RDFFeatureWriter::writeTrackLevelRDF: ERROR: No feature URI available -- this function should not have been called!" << endl;
637 for (
int i = 0; i < (int)featureList.size(); ++i) {
639 const Plugin::Feature &feature = featureList[i];
641 if (feature.values.empty()) {
643 if (feature.label ==
"")
continue;
645 stream << signalURI <<
" " << featureUri <<
" \"\"\"" 646 << feature.label.c_str() <<
"\"\"\" .\n";
650 stream << signalURI <<
" " << featureUri <<
" \"" 651 << feature.values[0] <<
"\"^^xsd:float .\n";
659 const Plugin::OutputDescriptor& od,
660 const Plugin::FeatureList& featureList,
665 if (featureList.empty())
return;
675 QTextStream stream(&str);
678 QString outputId = od.identifier.c_str();
680 unsigned long featureNumber =
m_count++;
686 stream <<
"\n:feature_timeline_" << featureNumber <<
" a tl:DiscreteTimeLine .\n\n";
689 int stepSize, blockSize;
695 if (od.sampleType == Plugin::OutputDescriptor::FixedSampleRate) {
697 sampleRate = od.sampleRate;
704 if (sampleRate == 0.f) {
705 SVCERR <<
"RDFFeatureWriter: INTERNAL ERROR: writing dense features without having set the sample rate properly!" << endl;
711 SVCERR <<
"RDFFeatureWriter: INTERNAL ERROR: writing dense features without having set the step size properly!" << endl;
716 if (blockSize == 0) {
717 SVCERR <<
"RDFFeatureWriter: INTERNAL ERROR: writing dense features without having set the block size properly!" << endl;
722 stream <<
":feature_timeline_map_" << featureNumber
723 <<
" a tl:UniformSamplingWindowingMap ;\n" 724 <<
" tl:rangeTimeLine :feature_timeline_" << featureNumber <<
" ;\n" 725 <<
" tl:domainTimeLine " << timelineURI <<
" ;\n" 726 <<
" tl:sampleRate \"" << sampleRate <<
"\"^^xsd:float ;\n" 727 <<
" tl:windowLength \"" << blockSize <<
"\"^^xsd:int ;\n" 728 <<
" tl:hopSize \"" << stepSize <<
"\"^^xsd:int .\n\n";
730 stream << signalURI <<
" af:signal_feature :feature_" 731 << featureNumber <<
" ." << endl << endl;
733 stream <<
":feature_" << featureNumber <<
" a ";
736 if (plain || signalTypeURI ==
"") {
741 stream <<
":signal_type_" << outputId <<
" ;\n";
744 stream <<
"<" << signalTypeURI <<
"> ;\n";
747 stream <<
" mo:time [" 748 <<
"\n a tl:Interval ;" 749 <<
"\n tl:onTimeLine :feature_timeline_" << featureNumber <<
" ;";
755 (startrt, sampleRate) / stepSize;
757 (durationrt, sampleRate) / stepSize;
760 stream <<
"\n tl:start \"" << start <<
"\"^^xsd:int ;";
763 stream <<
"\n tl:duration \"" << duration <<
"\"^^xsd:int ;";
766 stream <<
"\n ] ;\n";
769 stream <<
" vamp:computed_by " <<
m_transformURIs[transform] <<
" ;\n";
772 if (od.hasFixedBinCount) {
774 stream <<
" af:dimensions \"" << od.binCount <<
" 0\" ;\n";
777 stream <<
" af:value \"";
781 QTextStream stream(&str);
783 for (
int i = 0; i < (int)featureList.size(); ++i) {
785 const Plugin::Feature &feature = featureList[i];
787 for (
int j = 0; j < (int)feature.values.size(); ++j) {
788 stream << feature.values[j] <<
" ";
799 for (map<StringTransformPair, StreamBuffer>::iterator i =
804 *(b.first) << b.second <<
"\" ." << endl;
double sv_samplerate_t
Sample rate.
void setTrackMetadata(QString trackid, TrackMetadata metadata) override
void writeLocalFeatureTypes(QTextStream *, const Transform &, const Vamp::Plugin::OutputDescriptor &, PluginRDFDescription &, std::string summaryType)
map< StringTransformPair, StreamBuffer > m_openDenseFeatures
pair< QTextStream *, QString > StreamBuffer
virtual void setFixedEventTypeURI(QString uri)
int64_t sv_frame_t
Frame index, the unit of our time axis.
bool haveDescription() const
map< QTextStream *, set< Transform > > m_startedStreamTransforms
QTextStream * getOutputStream(QString, TransformId, QTextCodec *)
vector< Parameter > ParameterList
set< QString > m_startedTrackIds
void writeTrackLevelRDF(QTextStream *stream, const Transform &transform, const Vamp::Plugin::OutputDescriptor &output, const Vamp::Plugin::FeatureList &features, PluginRDFDescription &desc, QString signalURI)
map< Transform, QString > m_syntheticSignalTypeURIs
bool haveTitleArtistMetadata(QString trackId) const
map< QString, QString > m_trackTrackURIs
ParameterList getSupportedParameters() const override
pair< QString, Transform > StringTransformPair
QString getOutputFeatureAttributeURI(QString outputId) const
void writeSignalDescription(QTextStream *, QString)
QString getOutputSignalTypeURI(QString outputId) const
void setParameters(map< string, string > ¶ms) override
RDFDescriptionMap m_rdfDescriptions
void writePrefixes(QTextStream *)
virtual ~RDFFeatureWriter()
OutputDisposition getOutputDisposition(QString outputId) const
QString m_userAudioFileUri
map< Transform, QString > m_transformURIs
QString getOutputEventTypeURI(QString outputId) const
static sv_frame_t realTime2Frame(const RealTime &r, sv_samplerate_t sampleRate)
Convert a RealTime into a sample frame at the given sample rate.
void reviewFileForAppending(QString filename) override
void writeSparseRDF(QTextStream *stream, const Transform &transform, const Vamp::Plugin::OutputDescriptor &output, const Vamp::Plugin::FeatureList &features, PluginRDFDescription &desc, QString timelineURI)
void setParameters(map< string, string > ¶ms) override
map< QString, QString > m_trackSignalURIs
QString m_fixedEventTypeURI
string getDescription() const override
bool indexConfiguredURLs()
Index all URLs obtained from index files defined in the current settings.
map< QString, QString > m_trackTimelineURIs
static PluginRDFIndexer * getInstance()
map< Transform, QString > m_syntheticEventTypeURIs
TrackMetadataMap m_metadata
ParameterList getSupportedParameters() const override
void write(QString trackid, const Transform &transform, const Vamp::Plugin::OutputDescriptor &output, const Vamp::Plugin::FeatureList &features, std::string summaryType="") override
void writeDenseRDF(QTextStream *stream, const Transform &transform, const Vamp::Plugin::OutputDescriptor &output, const Vamp::Plugin::FeatureList &features, PluginRDFDescription &desc, QString signalURI, QString timelineURI)
RealTime represents time values to nanosecond precision with accurate arithmetic and frame-rate conve...