Mercurial > hg > classical
changeset 32:abd5d022c85d
* Some sketchy track lookup code
author | Chris Cannam |
---|---|
date | Fri, 19 Mar 2010 12:21:59 +0000 |
parents | 07efb25d24d6 |
children | 84d6acb6b3ba |
files | utilities/track/track.cpp utilities/track/track.pro |
diffstat | 2 files changed, 331 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/utilities/track/track.cpp Fri Mar 19 12:21:59 2010 +0000 @@ -0,0 +1,317 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +#include "Objects.h" +#include "TypeRegistrar.h" + +#include <dataquay/BasicStore.h> +#include <dataquay/TransactionalStore.h> +#include <dataquay/RDFException.h> +#include <dataquay/objectmapper/ObjectLoader.h> +#include <dataquay/objectmapper/ObjectStorer.h> +#include <dataquay/objectmapper/ObjectMapper.h> +#include <dataquay/objectmapper/TypeMapping.h> +#include <dataquay/Debug.h> + +#include "data/fileio/AudioFileReaderFactory.h" +#include "data/fileio/AudioFileReader.h" + +#include <vamp-hostsdk/PluginLoader.h> + +#include <QMultiMap> +#include <QFileInfo> + +#include <iostream> + +using namespace Dataquay; +using namespace ClassicalData; +using namespace std; +using namespace Vamp; +using namespace Vamp::HostExt; + +ostream &operator<<(ostream &target, const QString &str) +{ + return target << str.toLocal8Bit().data(); +} + +ostream &operator<<(ostream &target, const QUrl &u) +{ + return target << "<" << u.toString() << ">"; +} + + +bool +load(BasicStore *store, QString fileName) +{ + QUrl url = QUrl::fromLocalFile(fileName); + + cerr << "Importing from URL " << url << " ..."; + try { + store->import(url, BasicStore::ImportPermitDuplicates); + } catch (RDFException e) { + cerr << " retrying with explicit ntriples type..."; + try { + store->import(url, BasicStore::ImportPermitDuplicates, "ntriples"); + } catch (RDFException e) { + cerr << "failed" << endl; + cerr << "Import failed: " << e.what() << endl; + return false; + } + } + + cerr << " done" << endl; + return true; +} + +void +usage(char *name) +{ + int s = 0; + for (int i = 0; name[i]; ++i) if (name[i] == '/') s = i + 1; + name = name + s; + cerr << "Usage:" << endl; + cerr << " " << name << " <input-rdf-file> guess <track.wav> [<track.wav> ...]" << endl; + exit(-1); +} + +static QList<Composer *> allComposers; +static QMap<Composer *, QSet<Work *> > worksMap; + +void +show(Composer *c) +{ + cout << c->property("uri").value<Uri>() << endl; + cout << c->getSortName(true); + QString d = c->getDisplayDates(); + if (d != "") cout << " (" << d << ")"; + if (!c->nationality().empty() || c->period() != "") { + cout << " ["; + bool first = true; + foreach (QString n, c->nationality()) { + if (!first) cout << "/"; + cout << n; + first = false; + } + if (c->period() != "") { + if (!first) cout << ", "; + cout << c->period(); + } + cout << "]"; + } + if (c->gender() != "") { + cout << " *" << c->gender(); + } + if (!worksMap[c].empty()) { + cout << " [" << worksMap[c].size() << " work(s)]"; + } + cout << endl; + foreach (QString a, c->aliases()) { + cout << " - " << a << endl; + } + if (c->remarks() != "") { + cout << " " << c->remarks() << endl; + } + foreach (Document *d, c->pages()) { + cout << d->siteName() << " -> " << d->uri() << endl; + } + foreach (Uri u, c->otherURIs()) { + cout << "Same as " << u << endl; + } +} + +void +showBrief(Composer *c) +{ + cout << c->property("uri").value<Uri>() << endl; + cout << c->getSortName(false); + QString d = c->getDisplayDates(); + if (d != "") cout << " (" << d << ")"; + if (!c->nationality().empty() || c->period() != "") { + cout << " ["; + bool first = true; + foreach (QString n, c->nationality()) { + if (!first) cout << "/"; + cout << n; + first = false; + } + if (c->period() != "") { + if (!first) cout << " "; + cout << c->period(); + } + cout << "]"; + } + if (c->gender() != "") { + cout << " *" << c->gender(); + } + if (!worksMap[c].empty()) { + cout << " [" << worksMap[c].size() << " work(s)]"; + } + cout << endl; +} + +void +listBrief(QList<Composer *> composers) +{ + QMultiMap<QString, Composer *> sorted; + foreach (Composer *c, composers) { + sorted.insert(c->getSortName(false), c); + } + foreach (Composer *c, sorted) { + showBrief(c); + } +} + +void +listUris(QList<Composer *> composers) +{ + QMultiMap<Uri, Composer *> sorted; + foreach (Composer *c, composers) { + sorted.insert(c->property("uri").value<Uri>(), c); + } + foreach (Uri uri, sorted.keys()) { + cout << uri << endl; + } +} + +void +showSearchResults(QMultiMap<float, Composer *> matches, int count) +{ + int n = 0; + for (QMultiMap<float, Composer *>::const_iterator i = matches.end(); + i != matches.begin(); ) { + --i; + if (i.key() <= 0) continue; + cout << endl; + if (n == 0) { + cout << "Best match:" << endl; + } else if (n == 1) { + cout << "Other candidate(s):" << endl; + } + cout << "[" << i.key() << "] "; + if (n == 0) show(i.value()); + else showBrief(i.value()); + if (++n > count) break; + } + if (n == 0) cout << "No matches" << endl; + cout << endl; +} + +void +guess(QString track) +{ + cout << "Guessing composer for: " << track << endl; + AudioFileReader *reader = AudioFileReaderFactory::createReader(track); + if (!reader || !reader->isOK()) { + cerr << "Failed to open audio file" << endl; + return; + } + + cout << "File tag title: " << reader->getTitle() << endl; + cout << "File tag maker: " << reader->getMaker() << endl; + + cout << "All tags:" << endl; + AudioFileReader::TagMap tags = reader->getTags(); + for (AudioFileReader::TagMap::const_iterator i = tags.begin(); + i != tags.end(); ++i) { + cout << i->first << " " << i->second << endl; + } + + PluginLoader *pl = PluginLoader::getInstance(); + Plugin *plugin = pl->loadPlugin + ("ofa-vamp-plugin:ofa_puid_and_fingerprint", reader->getSampleRate(), PluginLoader::ADAPT_ALL); + if (!plugin) { + cerr << "Failed to load OFA Vamp plugin" << endl; + return; + } + + // 135 seconds... well, ok, let's have 136 + int secs = 136; + + int want = int(secs * reader->getSampleRate()); + int ch = reader->getChannelCount(); + std::vector<SampleBlock> samples; + reader->getDeInterleavedFrames(0, want, samples); + int have = samples[0].size(); + if (!plugin->initialise(ch, have, have)) { + cerr << "Failed to initialise(" << ch << "," << have << "," << have << ") plugin" << endl; + return; + } + + float **input = new float *[ch]; + for (int i = 0; i < ch; ++i) { + input[i] = &samples[i][0]; + } + Plugin::FeatureSet features = plugin->process(input, RealTime::zeroTime); + std::string fingerprint; + std::string puid; + if (!features[0].empty()) fingerprint = features[0][0].label; + if (!features[1].empty()) puid = features[1][0].label; + features = plugin->getRemainingFeatures(); + if (fingerprint == "" && !features[0].empty()) fingerprint = features[0][0].label; + if (puid == "" && !features[1].empty()) puid = features[1][0].label; + std::cerr << "fingerprint = " << fingerprint << std::endl; + std::cerr << "puid = " << puid << std::endl; +} + + +int +main(int argc, char **argv) +{ + if (argc < 3) usage(argv[0]); + QString inRDFFileName = argv[1]; + QString command = argv[2]; + QStringList args; + for (int i = 3; i < argc; ++i) { + args.push_back(argv[i]); + } + + BasicStore *store = new BasicStore(); + store->setBaseUri(Uri("http://dbtune.org/classical/resource/")); + ObjectLoader *loader = new ObjectLoader(store); + + TypeMapping tm; + + TypeRegistrar::registerTypes(); + TypeRegistrar::addMappings(store, &tm); + + loader->setTypeMapping(tm); + + if (!load(store, inRDFFileName)) { + cerr << "Failed to load data source" << endl; + return 1; + } + + cerr << "Imported RDF data, mapping to objects..."; + QObjectList objects = loader->loadAll(); + cerr << " done" << endl; + + delete loader; + + foreach (QObject *o, objects) { + Composer *c = qobject_cast<Composer *>(o); + if (c) allComposers.push_back(c); + } + + QList<Work *> works; + foreach (QObject *o, objects) { + Work *w = qobject_cast<Work *>(o); + if (w) works.push_back(w); + } + + foreach (Work *w, works) { + Composition *c = w->composition(); + if (c) { + Composer *cp = c->composer(); + if (cp) worksMap[cp].insert(w); + } + } + + if (command == "guess") { + if (args.empty()) usage(argv[0]); + foreach (QString track, args) { + guess(track); + } + } + + delete store; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/utilities/track/track.pro Fri Mar 19 12:21:59 2010 +0000 @@ -0,0 +1,14 @@ +TEMPLATE = app +TARGET = track +#QT -= gui network xml + +load(../../../all.prf) + +SOURCES += track.cpp + +PRE_TARGETDEPS += ../../common/libcommon.a + +INCLUDEPATH += ../../common ../../../svcore + +LIBS += ../../common/libcommon.a -L../../../svcore -lsvcore ../../../../turbot/dataquay/libdataquay.a ../../../../turbot/ext/libext.a +