Thread: [Sv1-commits] SF.net SVN: sv1: [817] runner/trunk
Brought to you by:
cannam
From: <ca...@us...> - 2007-11-02 16:54:36
|
Revision: 817 http://sv1.svn.sourceforge.net/sv1/?rev=817&view=rev Author: cannam Date: 2007-11-02 09:54:34 -0700 (Fri, 02 Nov 2007) Log Message: ----------- * first bit Added Paths: ----------- runner/trunk/runner.cpp runner/trunk/runner.pro Added: runner/trunk/runner.cpp =================================================================== --- runner/trunk/runner.cpp (rev 0) +++ runner/trunk/runner.cpp 2007-11-02 16:54:34 UTC (rev 817) @@ -0,0 +1,201 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +#include "vamp-sdk/PluginHostAdapter.h" +#include "vamp-sdk/hostext/PluginChannelAdapter.h" +#include "vamp-sdk/hostext/PluginInputDomainAdapter.h" +#include "vamp-sdk/hostext/PluginLoader.h" +#include "vamp/vamp.h" + +#include <iostream> +#include <fstream> +#include <sndfile.h> + +#include <cmath> + +#include <QCoreApplication> +#include <QStringList> +#include <QString> +#include <QTime> + +#include "data/fileio/FileSource.h" +#include "data/fileio/AudioFileReader.h" +#include "data/fileio/AudioFileReaderFactory.h" + +#include "base/TempDirectory.h" + +using std::cout; +using std::cerr; +using std::endl; +using std::string; +using std::vector; +using std::ofstream; +using std::ios; + +using Vamp::HostExt::PluginLoader; + +/* + + usage: + + runner vamp:aubioonset:onsets http://example.com/file.mp3 + +*/ + +void usage() +{ + cerr << "usage: runner vamp:soname:plugin[:output] <file-or-url>" << endl; + exit(2); +} + +int main(int argc, char **argv) +{ + QCoreApplication application(argc, argv); + + QTime time; + time.start(); + + QStringList args = application.arguments(); + + QCoreApplication::setOrganizationName("sonic-visualiser"); + QCoreApplication::setOrganizationDomain("sonicvisualiser.org"); + QCoreApplication::setApplicationName("runner"); + + if (args.size() != 3) usage(); + + QString pluginName = args[1]; + QString inputName = args[2]; + + if (pluginName.startsWith("vamp:")) { + pluginName = pluginName.right(pluginName.length()-5); + } + + size_t rate = 44100; + + Vamp::Plugin *plugin = PluginLoader::getInstance()->loadPlugin + (pluginName.toStdString(), rate, PluginLoader::ADAPT_ALL_SAFE); + + if (!plugin) { + cerr << "ERROR: Plugin \"" << pluginName.toStdString() << "\" could not be loaded" << endl; + exit(1); + } + + FileSourceProgressPrinter printer; + FileSource source(args[2]); + QObject::connect(&source, SIGNAL(progress(int)), + &printer, SLOT(progress(int))); + + if (!source.isAvailable()) { + cerr << "ERROR: File or URL \"" << args[2].toStdString() << "\" could not be located" << endl; + exit(1); + } + + cerr << "Retrieving or locating \"" << args[2].toStdString() << "\"..." << endl; + + source.waitForData(); + + cerr << "Opening and/or decoding audio file..." << endl; + + AudioFileReader *reader = AudioFileReaderFactory::createReader(source); + + if (!reader) { + cerr << "ERROR: File or URL \"" << args[2].toStdString() << "\" could not be opened" << endl; + exit(1); + } + + if (reader->getSampleRate() != rate) { + delete plugin; + rate = reader->getSampleRate(); + plugin = PluginLoader::getInstance()->loadPlugin + (pluginName.toStdString(), rate); + if (!plugin) { + cerr << "ERROR: Plugin \"" << pluginName.toStdString() << "\" could not be loaded" << endl; + exit(1); + } + } + + int blockSize = plugin->getPreferredBlockSize(); + int stepSize = plugin->getPreferredStepSize(); + + if (blockSize == 0) { + blockSize = 1024; + } + if (stepSize == 0) { + if (plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain) { + stepSize = blockSize/2; + } else { + stepSize = blockSize; + } + } else if (stepSize > blockSize) { + if (plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain) { + blockSize = stepSize * 2; + } else { + blockSize = stepSize; + } + } + + Vamp::Plugin::OutputList outputs = plugin->getOutputDescriptors(); + Vamp::Plugin::OutputDescriptor od; + + //!!! for now, use first output + od = outputs[0]; + + size_t channels = reader->getChannelCount(); + + if (!plugin->initialise(channels, stepSize, blockSize)) { + cerr << "ERROR: Plugin initialise (channels = " << channels + << ", stepSize = " << stepSize << ", blockSize = " + << blockSize << ") failed." << endl; + exit(1); + } + + float **data = new float *[channels]; + for (size_t c = 0; c < channels; ++c) data[c] = new float[blockSize]; + + cerr << "Running plugin..." << endl; + + int percent = 0; + size_t frameCount = reader->getFrameCount(); + + for (size_t i = 0; i < frameCount; i += stepSize) { + + //!!! inefficient, although much of the inefficiency may be + // susceptible to optimisation + + SampleBlock frames; + reader->getInterleavedFrames(i, blockSize, frames); + + for (size_t j = 0; j < blockSize; ++j) { + for (size_t c = 0; c < channels; ++c) { + size_t index = j * channels + c; + if (index < frames.size()) { + data[c][j] = frames[index]; + } else { + data[c][j] = 0.f; + } + } + } + + Vamp::RealTime timestamp = Vamp::RealTime::frame2RealTime(i, rate); + + Vamp::Plugin::FeatureSet features = plugin->process(data, timestamp); + + int ppc = percent; + percent = ((i * 100) / frameCount); + if (percent != ppc) { + cerr << "\r" << percent << "%"; + } + } + + cerr << "\rDone\n"; + + Vamp::Plugin::FeatureSet features = plugin->getRemainingFeatures(); + + TempDirectory::getInstance()->cleanup(); + + int ms = time.elapsed(); + cerr << "Total time: " << float(ms)/1000 << " sec" << endl; + + return 0; +} + + Added: runner/trunk/runner.pro =================================================================== --- runner/trunk/runner.pro (rev 0) +++ runner/trunk/runner.pro 2007-11-02 16:54:34 UTC (rev 817) @@ -0,0 +1,34 @@ + +TEMPLATE = app + +SV_UNIT_PACKAGES = vamp vamp-hostsdk samplerate mad id3tag oggz fishsound sndfile +load(../sonic-visualiser/sv.prf) + +CONFIG += sv qt thread warn_on stl rtti exceptions +QT += xml network + +TARGET = runner + +DEPENDPATH += . ../sonic-visualiser i18n main +INCLUDEPATH += . ../sonic-visualiser main +LIBPATH = ../sonic-visualiser/audioio ../sonic-visualiser/data ../sonic-visualiser/plugin ../sonic-visualiser/base ../sonic-visualiser/system $$LIBPATH + +contains(DEFINES, BUILD_STATIC):LIBS -= -ljack + +LIBS = -lsvaudioio -lsvdata -lsvplugin -lsvbase -lsvsystem $$LIBS + +PRE_TARGETDEPS += ../sonic-visualiser/audioio/libsvaudioio.a \ + ../sonic-visualiser/data/libsvdata.a \ + ../sonic-visualiser/plugin/libsvplugin.a \ + ../sonic-visualiser/base/libsvbase.a \ + ../sonic-visualiser/system/libsvsystem.a + +OBJECTS_DIR = tmp_obj +MOC_DIR = tmp_moc + +# Input +HEADERS += +SOURCES += runner.cpp + + + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mh...@us...> - 2007-11-07 10:15:24
|
Revision: 822 http://sv1.svn.sourceforge.net/sv1/?rev=822&view=rev Author: mhlevy Date: 2007-11-07 02:14:55 -0800 (Wed, 07 Nov 2007) Log Message: ----------- added existing host/writer code Added Paths: ----------- runner/trunk/DefaultFeatureWriter.cpp runner/trunk/DefaultFeatureWriter.h runner/trunk/FeatureExtractionManager.cpp runner/trunk/FeatureExtractionManager.h runner/trunk/FeatureWriter.h runner/trunk/PluginBufferingAdapter.cpp runner/trunk/PluginBufferingAdapter.h runner/trunk/QTAudioFile.cpp runner/trunk/QTAudioFile.h Added: runner/trunk/DefaultFeatureWriter.cpp =================================================================== --- runner/trunk/DefaultFeatureWriter.cpp (rev 0) +++ runner/trunk/DefaultFeatureWriter.cpp 2007-11-07 10:14:55 UTC (rev 822) @@ -0,0 +1,61 @@ +/* + * DefaultFeatureWriter.cpp + * vamphost + * + * Created by Mark Levy on 01/11/2007. + * Copyright 2007 Queen Mary, Univesity of London. All rights reserved. + * + */ + +#include <iostream> +#include <map> + +using namespace std; + +#include "DefaultFeatureWriter.h" + +void DefaultFeatureWriter::write(const string& trackid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) +{ + // generic XML output for FeatureSet + + /* + + <feature> + <name>output.name</name> + <timestamp>feature.timestamp</timestamp> + <values>output.binName[0]:feature.value[0]...</values> + <label>feature.label</label> + </feature> + + */ + + // iterate through FeatureLists + + for (map<int, Vamp::Plugin::FeatureList>::const_iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) + { + Vamp::Plugin::FeatureList featureList = iter->second; + Vamp::Plugin::OutputDescriptor output = outputList[iter->first]; + for (int i = 0; i < featureList.size(); ++i) + { + cerr << "<feature>" << endl; + cerr << "\t<name>" << output.name << "</name>" << endl; + cerr << "\t<timestamp>" << featureList[i].timestamp << "</timestamp>" << endl; + if (featureList[i].values.size() > 0) + { + cerr << "\t<values>"; + for (int j = 0; j < featureList[i].values.size(); ++j) + { + if (j > 0) + cerr << " "; + if (output.binNames.size() > 0) + cerr << output.binNames[j] << ":"; + cerr << featureList[i].values[j]; + } + cerr << "</values>" << endl; + } + if (featureList[i].label.length() > 0) + cerr << "\t<label>" << featureList[i].label << "</label>" << endl; + cerr << "</feature>" << endl; + } + } +} \ No newline at end of file Added: runner/trunk/DefaultFeatureWriter.h =================================================================== --- runner/trunk/DefaultFeatureWriter.h (rev 0) +++ runner/trunk/DefaultFeatureWriter.h 2007-11-07 10:14:55 UTC (rev 822) @@ -0,0 +1,23 @@ +/* + * DefaultFeatureWriter.h + * vamphost + * + * Created by Mark Levy on 01/11/2007. + * Copyright 2007 Queen Mary, Univesity of London. All rights reserved. + * + */ + +#ifndef _DEFAULT_FEATURE_WRITER_H_ +#define _DEFAULT_FEATURE_WRITER_H_ + + +#include "FeatureWriter.h" + +class DefaultFeatureWriter : public FeatureWriter +{ +public: + virtual ~DefaultFeatureWriter() { } + virtual void write(const string& trackid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); +}; + +#endif \ No newline at end of file Added: runner/trunk/FeatureExtractionManager.cpp =================================================================== --- runner/trunk/FeatureExtractionManager.cpp (rev 0) +++ runner/trunk/FeatureExtractionManager.cpp 2007-11-07 10:14:55 UTC (rev 822) @@ -0,0 +1,147 @@ +/* + * FeatureExtractionManager.cpp + * vamphost + * + * Created by Mark Levy on 31/10/2007. + * Copyright 2007 Queen Mary, University of London. All rights reserved. + * + */ + +#include <iostream> + +using namespace std; + +#include <vamp-sdk/PluginHostAdapter.h> +#include <vamp-sdk/hostext/PluginChannelAdapter.h> +#include <vamp-sdk/hostext/PluginInputDomainAdapter.h> +#include <vamp-sdk/hostext/PluginLoader.h> +#include <vamp/vamp.h> + +using Vamp::HostExt::PluginLoader; + +#include "PluginBufferingAdapter.h" +#include "FeatureWriter.h" +#include "FeatureExtractionManager.h" + + +FeatureExtractionManager::FeatureExtractionManager() +{ +} + +FeatureExtractionManager::~FeatureExtractionManager() +{ + for (int i = 0; i < plugins.size(); ++i) + delete plugins[i]; +} + +void FeatureExtractionManager::setChannels(int channels) +{ + m_channels = channels; +} + +void FeatureExtractionManager::setSampleRate(int sampleRate) +{ + m_sampleRate = sampleRate; +} + +bool FeatureExtractionManager::addFeatureExtractor(string library, string plugname, vector<FeatureWriter*> writers) +{ + PluginLoader *loader = PluginLoader::getInstance(); + + PluginLoader::PluginKey key = loader->composePluginKey(library, plugname); + + Vamp::Plugin *plugin = loader->loadPlugin(key, m_sampleRate, PluginLoader::ADAPT_ALL); + if (!plugin) { + cerr << "ERROR: Failed to load plugin \"" << plugin << "\" from library \"" << library << "\"" << endl; + return false; + } + + // wrap in a buffering adapter, also ensures all features are timestamped + plugin = new Vamp::HostExt::PluginBufferingAdapter(plugin); + + plugins.push_back(plugin); + pluginWriters.push_back(writers); + + return true; +} + +void FeatureExtractionManager::extractFeatures(QTAudioFile qtfile) +{ + // currently we can impose a sample rate and number of channels on QTAudioFile + qtfile.init(m_sampleRate, m_channels); + + // arbitrary fixed block size for QuickTime + int blockSize = 2048; + int stepSize = 2048; + + float **plugbuf = new float*[m_channels]; + for (int c = 0; c < m_channels; ++c) plugbuf[c] = new float[blockSize + 2]; + + cerr << "Using block size = " << blockSize << ", step size = " << stepSize << endl; + + for (int i = 0; i < plugins.size(); ++i) + { + int minch = plugins[i]->getMinChannelCount(); + int maxch = plugins[i]->getMaxChannelCount(); + cerr << "Plugin accepts " << minch << " -> " << maxch << " channel(s)" << endl; + cerr << "Sound file has " << m_channels << " (will mix/augment if necessary)" << endl; + + if (!plugins[i]->initialise(m_channels, stepSize, blockSize)) { + cerr << "ERROR: Plugin initialise (channels = " << m_channels << ", stepSize = " << stepSize << ", blockSize = " << blockSize << ") failed." << endl; + + // TODO: + // decide how to handle this error... + } + } + + // currently we need a buffer of doubles - easy to change + // - also its only a 1-d array due to the hard-coded mono + // output in QTAudioFile, need to change this + double* qtbuf = new double[blockSize]; + qtfile.setBuffer(qtbuf, blockSize); + + int n; + int j = 0; + while ((n = qtfile.fillBuffer()) > 0) + { + for (int i = 0; i < n; ++i) + plugbuf[0][i] = (float) qtbuf[i]; + + // pad last block + for (int i = n; i < blockSize; ++i) + plugbuf[0][i] = 0.0; + + + Vamp::RealTime timestamp = Vamp::RealTime::frame2RealTime(j*blockSize, m_sampleRate); + + for (int i = 0; i < plugins.size(); ++i) + { + Vamp::Plugin::FeatureSet featureSet = plugins[i]->process(plugbuf, timestamp); + for (int j = 0; j < pluginWriters[i].size(); ++j) + pluginWriters[i][j]->write("track01", plugins[i]->getOutputDescriptors(), featureSet); + } + + ++j; + } + + for (int i = 0; i < plugins.size(); ++i) + for (int j = 0; j < pluginWriters[i].size(); ++j) + pluginWriters[i][j]->write("track01", plugins[i]->getOutputDescriptors(), plugins[i]->getRemainingFeatures()); + + delete [] qtbuf; + qtfile.close(); +} + +void FeatureExtractionManager::extractFeaturesFromFile(string filepath) +{ + QTAudioFile qtfile; + qtfile.open(filepath); + extractFeatures(qtfile); +} + +void FeatureExtractionManager::extractFeaturesFromStream(string url) +{ + QTAudioFile qtfile; + qtfile.openStream(url); + extractFeatures(qtfile); +} \ No newline at end of file Added: runner/trunk/FeatureExtractionManager.h =================================================================== --- runner/trunk/FeatureExtractionManager.h (rev 0) +++ runner/trunk/FeatureExtractionManager.h 2007-11-07 10:14:55 UTC (rev 822) @@ -0,0 +1,42 @@ +/* + * FeatureExtractionManager.h + * vamphost + * + * Created by Mark Levy on 31/10/2007. + * Copyright 2007 Queen Mary, University of London. All rights reserved. + * + */ + +#ifndef _FEATURE_EXTRACTION_MANAGER_H_ +#define _FEATURE_EXTRACTION_MANAGER_H_ + +#include <vector> +#include <string> + +using std::vector; +using std::string; + +#include <vamp-sdk/plugin.h> +#include "QTAudioFile.h" + +class FeatureWriter; + +class FeatureExtractionManager +{ +public: + FeatureExtractionManager(); + virtual ~FeatureExtractionManager(); + void setChannels(int channels); + void setSampleRate(int sampleRate); + bool addFeatureExtractor(string library, string plugname, vector<FeatureWriter*> writers); + void extractFeaturesFromFile(string filepath); + void extractFeaturesFromStream(string url); + void extractFeatures(QTAudioFile qtfile); +private: + vector<Vamp::Plugin*> plugins; + vector<vector<FeatureWriter*> > pluginWriters; // parallel vector of writers for each plugin + int m_sampleRate; + int m_channels; +}; + +#endif \ No newline at end of file Added: runner/trunk/FeatureWriter.h =================================================================== --- runner/trunk/FeatureWriter.h (rev 0) +++ runner/trunk/FeatureWriter.h 2007-11-07 10:14:55 UTC (rev 822) @@ -0,0 +1,26 @@ +/* + * FeatureWriter.h + * vamphost + * + * Created by Mark Levy on 01/11/2007. + * Copyright 2007 Queen Mary, Univesity of London. All rights reserved. + * + */ + +#ifndef _FEATURE_WRITER_H_ +#define _FEATURE_WRITER_H_ + +#include <string> + +using std::string; + +#include <vamp-sdk/Plugin.h> + +class FeatureWriter +{ +public: + virtual ~FeatureWriter() { } + virtual void write(const string& trackid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) = 0; +}; + +#endif \ No newline at end of file Added: runner/trunk/PluginBufferingAdapter.cpp =================================================================== --- runner/trunk/PluginBufferingAdapter.cpp (rev 0) +++ runner/trunk/PluginBufferingAdapter.cpp 2007-11-07 10:14:55 UTC (rev 822) @@ -0,0 +1,286 @@ +/* + * PluginBufferingAdapter.cpp + * vamphost + * + * Created by Mark Levy on 29/10/2007. + * Copyright 2007 Queen Mary, University of London. All rights reserved. + * + */ + +#include <vector> +#include <map> + +using std::vector; +using std::map; + +#include "PluginBufferingAdapter.h" + +namespace Vamp { + + namespace HostExt { + + class PluginBufferingAdapter::Impl + { +public: + Impl(Plugin *plugin, size_t inputSampleRate); + ~Impl(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + + FeatureSet process(const float *const *inputBuffers, RealTime timestamp); + + FeatureSet getRemainingFeatures(); + + OutputList getOutputDescriptors() const; + +protected: + Plugin *m_plugin; + size_t m_inputStepSize; + size_t m_inputBlockSize; + size_t m_stepSize; + size_t m_blockSize; + size_t m_channels; + vector<vector<float> > m_queue; + float **m_buffers; // in fact an array of pointers into the queue + size_t m_inputPos; // start position in the queue of next input block + size_t m_inputSampleRate; + RealTime m_timestamp; + OutputList m_outputs; + + void processBlock(FeatureSet& allFeatureSets, RealTime timestamp); + }; + + PluginBufferingAdapter::PluginBufferingAdapter(Plugin *plugin) : + PluginWrapper(plugin) + { + m_impl = new Impl(plugin, m_inputSampleRate); + } + + PluginBufferingAdapter::~PluginBufferingAdapter() + { + delete m_impl; + } + + bool + PluginBufferingAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize) + { + return m_impl->initialise(channels, stepSize, blockSize); + } + + PluginBufferingAdapter::FeatureSet + PluginBufferingAdapter::process(const float *const *inputBuffers, + RealTime timestamp) + { + return m_impl->process(inputBuffers, timestamp); + } + + PluginBufferingAdapter::FeatureSet + PluginBufferingAdapter::getRemainingFeatures() + { + return m_impl->getRemainingFeatures(); + } + + PluginBufferingAdapter::OutputList + PluginBufferingAdapter::getOutputDescriptors() const + { + return m_impl->getOutputDescriptors(); + } + + + PluginBufferingAdapter::Impl::Impl(Plugin *plugin, size_t inputSampleRate) : + m_plugin(plugin), + m_inputStepSize(0), + m_inputBlockSize(0), + m_stepSize(0), + m_blockSize(0), + m_channels(0), + m_buffers(0), + m_inputPos(0), + m_inputSampleRate(inputSampleRate), + m_timestamp(), + m_outputs(m_plugin->getOutputDescriptors()) + { + } + + PluginBufferingAdapter::Impl::~Impl() + { + // the adapter will delete the plugin + + delete [] m_buffers; + } + + PluginBufferingAdapter::OutputList + PluginBufferingAdapter::Impl::getOutputDescriptors() const + { + OutputList outputs; + // adapter always sets the timestamp, alert clients by setting sampleType + for (int i = 0; i < m_outputs.size(); ++i) + { + outputs.push_back(OutputDescriptor(m_outputs[i])); + outputs[i].sampleType = OutputDescriptor::VariableSampleRate; + } + return outputs; + } + + + bool + PluginBufferingAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize) + { + m_channels = channels; + m_inputStepSize = stepSize; + m_inputBlockSize = blockSize; + + // use the step and block sizes which the plugin prefers + m_stepSize = m_plugin->getPreferredStepSize(); + m_blockSize = m_plugin->getPreferredBlockSize(); + + // or sensible defaults if it has no preference + if (m_blockSize == 0) { + m_blockSize = 1024; + } + if (m_stepSize == 0) { + if (m_plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain) { + m_stepSize = m_blockSize/2; + } else { + m_stepSize = m_blockSize; + } + } else if (m_stepSize > m_blockSize) { + if (m_plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain) { + m_blockSize = m_stepSize * 2; + } else { + m_blockSize = m_stepSize; + } + } + + std::cerr << "PluginBufferingAdapter::initialise: stepSize " << m_inputStepSize << " -> " << m_stepSize + << ", blockSize " << m_inputBlockSize << " -> " << m_blockSize << std::endl; + + // current implementation breaks if step is greater than block + if (m_stepSize > m_blockSize) { + std::cerr << "PluginBufferingAdapter::initialise: plugin's preferred stepSize greater than blockSize, giving up!" << std::endl; + return false; + } + + m_queue.resize(m_channels); + m_buffers = new float*[m_channels]; + + return m_plugin->initialise(m_channels, m_stepSize, m_blockSize); + } + + PluginBufferingAdapter::FeatureSet + PluginBufferingAdapter::Impl::process(const float *const *inputBuffers, + RealTime timestamp) + { + FeatureSet allFeatureSets; + + // queue the new input + + //std::cerr << "unread " << m_queue[0].size() - m_inputPos << " samples" << std::endl; + //std::cerr << "queueing " << m_inputBlockSize - (m_queue[0].size() - m_inputPos) << " samples" << std::endl; + + for (int i = 0; i < m_channels; ++i) + for (int j = m_queue[0].size() - m_inputPos; j < m_inputBlockSize; ++j) + m_queue[i].push_back(inputBuffers[i][j]); + + m_inputPos += m_inputStepSize; + + // process as much as we can + while (m_queue[0].size() >= m_blockSize) + { + processBlock(allFeatureSets, timestamp); + m_inputPos -= m_stepSize; + + //std::cerr << m_queue[0].size() << " samples still left in queue" << std::endl; + //std::cerr << "inputPos = " << m_inputPos << std::endl; + } + + return allFeatureSets; + } + + PluginBufferingAdapter::FeatureSet + PluginBufferingAdapter::Impl::getRemainingFeatures() + { + FeatureSet allFeatureSets; + + // process remaining samples in queue + while (m_queue[0].size() >= m_blockSize) + { + processBlock(allFeatureSets, m_timestamp); + } + + // pad any last samples remaining and process + if (m_queue[0].size() > 0) + { + for (int i = 0; i < m_channels; ++i) + while (m_queue[i].size() < m_blockSize) + m_queue[i].push_back(0.0); + processBlock(allFeatureSets, m_timestamp); + } + + // get remaining features + FeatureSet featureSet = m_plugin->getRemainingFeatures(); + for (map<int, FeatureList>::iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) + { + FeatureList featureList = iter->second; + for (int i = 0; i < featureList.size(); ++i) + allFeatureSets[iter->first].push_back(featureList[i]); + } + + return allFeatureSets; + } + + void + PluginBufferingAdapter::Impl::processBlock(FeatureSet& allFeatureSets, RealTime timestamp) + { + //std::cerr << m_queue[0].size() << " samples left in queue" << std::endl; + + // point the buffers to the head of the queue + for (int i = 0; i < m_channels; ++i) + m_buffers[i] = &m_queue[i][0]; + + FeatureSet featureSet = m_plugin->process(m_buffers, m_timestamp); + + for (map<int, FeatureList>::iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) + { + + FeatureList featureList = iter->second; + int outputNo = iter->first; + + for (int i = 0; i < featureList.size(); ++i) + { + + // make sure the timestamp is set + switch (m_outputs[outputNo].sampleType) + { + case OutputDescriptor::OneSamplePerStep: + featureList[i].timestamp = m_timestamp; // use our internal timestamp - OK???? + break; + case OutputDescriptor::FixedSampleRate: + featureList[i].timestamp = m_timestamp; // use our internal timestamp + break; + case OutputDescriptor::VariableSampleRate: + break; // plugin must set timestamp + default: + break; + } + + allFeatureSets[outputNo].push_back(featureList[i]); + } + } + + // step forward + for (int i = 0; i < m_channels; ++i) + m_queue[i].erase(m_queue[i].begin(), m_queue[i].begin() + m_stepSize); + + // fake up the timestamp each time we step forward + //std::cerr << m_timestamp; + long frame = RealTime::realTime2Frame(m_timestamp, m_inputSampleRate); + m_timestamp = RealTime::frame2RealTime(frame + m_stepSize, m_inputSampleRate); + //std::cerr << "--->" << m_timestamp << std::endl; + } + + } + +} + + Added: runner/trunk/PluginBufferingAdapter.h =================================================================== --- runner/trunk/PluginBufferingAdapter.h (rev 0) +++ runner/trunk/PluginBufferingAdapter.h 2007-11-07 10:14:55 UTC (rev 822) @@ -0,0 +1,64 @@ +/* + * PluginBufferingAdapter.h + * vamphost + * + * Created by Mark Levy on 29/10/2007. + * Copyright 2007 Queen Mary, University of London. All rights reserved. + * + */ + +#ifndef _VAMP_PLUGIN_BUFFERING_ADAPTER_H_ +#define _VAMP_PLUGIN_BUFFERING_ADAPTER_H_ + +#include <vamp-sdk/hostext/PluginWrapper.h> + +namespace Vamp { + + namespace HostExt { + + /** + * \class PluginBufferingAdapter PluginBufferingAdapter.h + * + * PluginBufferingAdapter is a Vamp plugin adapter that allows plugins + * to be used by a host supplying an audio stream in non-overlapping buffers + * of arbitrary size. + * A host using PluginBufferingAdapter may ignore the getPreferredStepSize + * and getPreferredBlockSize reported by the plugin, and still expect the + * plugin to run. The value of blockSize passed to initialise should be the + * size of the buffer which the host will supply. Any dummy value for stepSize + * can be passed to initialise and will be ignored. + * + * In every respect other than its management of buffering, the + * PluginBufferingAdapter behaves identically to the plugin that it + * wraps. The wrapped plugin will be deleted when the wrapper is + * deleted. + * + * NO! - this adapter now ensures that a timestamp is set + * in every output feature + * + */ + + class PluginBufferingAdapter : public PluginWrapper + { + public: + PluginBufferingAdapter(Plugin *plugin); // I take ownership of plugin + virtual ~PluginBufferingAdapter(); + + bool initialise(size_t channels, size_t stepSize, size_t blockSize); + + FeatureSet process(const float *const *inputBuffers, RealTime timestamp); + + FeatureSet getRemainingFeatures(); + + OutputList getOutputDescriptors() const; + + protected: + class Impl; + Impl *m_impl; + }; + + } + +} + +#endif Added: runner/trunk/QTAudioFile.cpp =================================================================== --- runner/trunk/QTAudioFile.cpp (rev 0) +++ runner/trunk/QTAudioFile.cpp 2007-11-07 10:14:55 UTC (rev 822) @@ -0,0 +1,306 @@ +/* + * QTAudioFile.cpp + * QTAudioFile + * + * Created by Chris Sutton on 02/10/2006. + * Copyright 2006 Chris Sutton and Mark Levy. All rights reserved. + * + */ + +#include "QTAudioFile.h" +#include <string> + +using std::string; + +#define DEBUGMSGS 1 +#define QTAudioFileException 10 + +/* + * Open the audio file at path for decoding, returning 1 on success. + */ +void QTAudioFile::open(string path) +{ +#ifdef WIN32 + theMovie = NULL; + short actualResId = DoTheRightThing; + error = 0; + + FSSpec theFSSpec; + short resRefNum = -1; + + InitializeQTML(0); + + // NOTE different for multi-threaded code... + //EnterMoviesOnThread(0); + EnterMovies(); + + error = NativePathNameToFSSpec(const_cast<char*>(path.c_str()), &theFSSpec, 0 /* flags */); + if (error) + { + printf("NativePathNameToFSSpec failed %d\n", error); + throw QTAudioFileException; + } + + error = OpenMovieFile(&theFSSpec, &resRefNum, 0); + if (error) + { + printf("OpenMovieFile failed %d for file\n%s\n", error, path.c_str()); + throw QTAudioFileException; + } + + error = NewMovieFromFile(&theMovie, resRefNum, &actualResId, (unsigned char *) 0, 0, (Boolean *) 0); + if (error) + { + printf("NewMovieFromFile failed %d\n", error); + throw QTAudioFileException; + } + + if (resRefNum != -1) + CloseMovieFile(resRefNum); +#else + CFURLRef fileLocation; + Handle dataRef; + OSType dataRefType; + long QTversion; + + error = Gestalt(gestaltQuickTime,&QTversion); + if ((error != noErr) || (QTversion < 0x07000000)) + { + printf("ERROR : QuickTime Version 7 or above is not installed !\n"); + throw QTAudioFileException; + } + else + { + dm("Initialising Quicktime, "); + + // NOTE different for multi-threaded code... + //EnterMoviesOnThread(0); + EnterMovies(); + + + dm("Setting fileLocation, "); + + + if (isStream) + { + // this works if the path passed in is a URL - so we can read a stream! + // ALSO it works if passed the raw location from the iTunes Library xml file + // (file://localhost/...) + CFStringRef myURLString = CFStringCreateWithCString(kCFAllocatorDefault, path.c_str(), kCFStringEncodingASCII); + fileLocation = CFURLCreateWithString(NULL, myURLString, NULL); + isStream = false; + } + else + { + // need to use this with a local filepath + dm(const_cast<char*>(path.c_str())); + fileLocation = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)path.c_str(), (CFIndex) path.length(), false); + } + + dm("Creating data reference, "); + + error = QTNewDataReferenceFromCFURL(fileLocation, 0, &dataRef, &dataRefType); + if (error) + { + printf("Error ! Code %d\n", error); + throw QTAudioFileException; + } + + dm("Creating new movie, "); + short fileID = movieInDataForkResID; + short flags = 0; + error = NewMovieFromDataRef(&theMovie, flags, &fileID, dataRef, dataRefType); + if (error) + { + printf("Error ! Code %d\n", error); + throw QTAudioFileException; + } + else dm("File open complete.\n"); + } +#endif + + dm("Checking for DRM... "); + Boolean isProtected = 0; + Track aTrack = GetMovieIndTrackType(theMovie, 1, SoundMediaType, + movieTrackMediaType | movieTrackEnabledOnly); + if (aTrack) + { + Media aMedia = GetTrackMedia(aTrack); // get the track media + if (aMedia) + { + MediaHandler mh = GetMediaHandler(aMedia); // get the media handler we can query + if (mh) + { + error = QTGetComponentProperty(mh, + kQTPropertyClass_DRM, + kQTDRMPropertyID_IsProtected, + sizeof(Boolean), &isProtected,nil); + } + else + error=1; + } + else + error=1; + } + else + error=1; + + if (error && error !=kQTPropertyNotSupportedErr) + { + printf("Error checking for DRM ! Code %d\n", error); + throw QTAudioFileException; + } + else if (!error && isProtected) + { + printf("File is protected with DRM !\n"); + throw QTAudioFileException; + } + else if (error == kQTPropertyNotSupportedErr && !isProtected) + dm("File is not protected with DRM.\n"); +} + +void QTAudioFile::openStream(string url) +{ + isStream = true; + open(url); +} + +/* + * Initialise the movie and set correct output format + */ +void QTAudioFile::init(int sampleRate, int channels) +{ + dm("Setting movie active, "); + SetMovieActive(theMovie, TRUE); + + dm("Beginning extraction session, "); + error = MovieAudioExtractionBegin(theMovie, 0, &extractionSessionRef); + if (error) printf("Error ! Code %d\n", error); + + dm("Setting mono output, "); + AudioChannelLayout monoLayout = {0}; + monoLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono; + error = MovieAudioExtractionSetProperty(extractionSessionRef, + kQTPropertyClass_MovieAudioExtraction_Audio, + kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, + sizeof(monoLayout), &monoLayout); + if (error) printf("Error ! Code %d\n", error); + + dm("Getting default output format : \n"); + error = MovieAudioExtractionGetProperty(extractionSessionRef, + kQTPropertyClass_MovieAudioExtraction_Audio, kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, + sizeof (asbd), &asbd, nil); + if (error) printf("Error ! Code %d\n", error); + printASBD(asbd); + + dm("Setting new output format (22kHz doubles) : \n"); + /* Desired ASBD : */ + asbd.mFormatFlags = kAudioFormatFlagIsFloat | + kAudioFormatFlagIsPacked | + kAudioFormatFlagsNativeEndian; + asbd.mChannelsPerFrame = 1; + asbd.mBitsPerChannel = sizeof(double) * 8; + asbd.mBytesPerFrame = sizeof(double) * asbd.mChannelsPerFrame; + asbd.mBytesPerPacket = asbd.mBytesPerFrame; + asbd.mSampleRate = sampleRate; + + error = MovieAudioExtractionSetProperty(extractionSessionRef, + kQTPropertyClass_MovieAudioExtraction_Audio, kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, + sizeof (asbd), &asbd); + if (error) + printf("Error ! Code %d\n", error); + printASBD(asbd); + + dm("Init complete.\n"); +} + +/* + * Set up output buffers for samples + */ +void QTAudioFile::setBuffer(double* buf, int buflen) +{ + dm("Setting up buffers, "); + UInt32 sampleCount; + numFrames = buflen; + + buffer = (AudioBufferList*) calloc(sizeof(AudioBufferList), 1); + + buffer->mNumberBuffers = 1; + buffer->mBuffers[0].mNumberChannels = asbd.mChannelsPerFrame; + buffer->mBuffers[0].mDataByteSize = sizeof(double) * buffer->mBuffers[0].mNumberChannels * numFrames; + + // samples = (double*) calloc(buffer->mBuffers[0].mDataByteSize, 1); + buffer->mBuffers[0].mData = buf; + sampleCount = numFrames * buffer->mBuffers[0].mNumberChannels; + + dm("Success.\n"); + +} + +/* + * Read numFrames worth of samples into buffers from last position in file + */ +int QTAudioFile::fillBuffer() +{ + UInt32 extractionFlags = 0; + error = MovieAudioExtractionFillBuffer(extractionSessionRef, &numFrames, buffer, &extractionFlags); + if (error) + printf("Error ! Code %d\n", error); + + return numFrames; +} + +/* + * Close audio file and shut down quicktime + */ +void QTAudioFile::close() +{ + dm("Ending extraction session, "); + error = MovieAudioExtractionEnd(extractionSessionRef); + if (error) + printf("Error ! Code %d\n", error); + + dm("Shutting down QuickTime. "); + + // NOTE different for multi-threaded code... + //ExitMoviesOnThread(); + ExitMovies(); + + dm("Success.\n"); +} + +/* + * Pretty printer for ASBDs + */ +void QTAudioFile::printASBD(AudioStreamBasicDescription asbd) +{ + if (DEBUGMSGS) + { + switch(asbd.mFormatID) + { + case kAudioFormatLinearPCM : + printf("ASBD : Format : Linear PCM, "); break; + case kAudioFormatMPEGLayer3 : + printf("ASBD : Format : MP3, "); break; + case kAudioFormatMPEG4AAC : + printf("ASBD : Format : AAC, "); break; + default : + printf("ASBD : Format : Other, enum code %d, ",asbd.mFormatID); break; + } + + // printf("ASBD : Format : %d, ",asbd.mFormatID); + printf("Flags : %d\n",asbd.mFormatFlags); + printf(" Channels : %d\n",asbd.mChannelsPerFrame); + printf(" Fs : %dHz\n",(int)asbd.mSampleRate); + printf(" %d bytes per frame, %d frames per packet\n", asbd.mBytesPerFrame, asbd.mFramesPerPacket); + } +} + +/* + * Output function for debugging info + */ +void QTAudioFile::dm(char msg[]) +{ + if (DEBUGMSGS) printf(msg); +} + Added: runner/trunk/QTAudioFile.h =================================================================== --- runner/trunk/QTAudioFile.h (rev 0) +++ runner/trunk/QTAudioFile.h 2007-11-07 10:14:55 UTC (rev 822) @@ -0,0 +1,43 @@ +/* + * QTAudioFile.h + * QTAudioFile + * + * Created by Chris Sutton on 02/10/2006. + * Copyright 2006 Chris Sutton and Mark Levy. All rights reserved. + * + */ + +#ifdef WIN32 + #include <QTML.h> + #include <Movies.h> +#else + #include "QuickTime/QuickTime.h" +#endif + +#include <string> + +using std::string; + +class QTAudioFile +{ +public: + QTAudioFile() : isStream(false) { } + virtual ~QTAudioFile() { } + void open(string path); + void openStream(string url); + void init(int sampleRate, int channels); + void setBuffer(double* buf, int buflen); + int fillBuffer(); + void close(); + void printASBD(AudioStreamBasicDescription asbd); + void dm(char msg[]); + + UInt32 numFrames; //Used to indicate how many frames to read and how many have just been read. +private: + MovieAudioExtractionRef extractionSessionRef; + AudioBufferList* buffer; + OSErr error; + AudioStreamBasicDescription asbd; + Movie theMovie; + bool isStream; +}; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mh...@us...> - 2007-11-07 10:17:45
|
Revision: 823 http://sv1.svn.sourceforge.net/sv1/?rev=823&view=rev Author: mhlevy Date: 2007-11-07 02:17:41 -0800 (Wed, 07 Nov 2007) Log Message: ----------- more existing host/writer code Added Paths: ----------- runner/trunk/SimpleRDFFeatureWriter.cpp runner/trunk/SimpleRDFFeatureWriter.h runner/trunk/main.cpp Added: runner/trunk/SimpleRDFFeatureWriter.cpp =================================================================== --- runner/trunk/SimpleRDFFeatureWriter.cpp (rev 0) +++ runner/trunk/SimpleRDFFeatureWriter.cpp 2007-11-07 10:17:41 UTC (rev 823) @@ -0,0 +1,151 @@ +/* + * SimpleRDFFeatureWriter.cpp + * vamphost + * + * Created by Chris Sutton on 01/11/2007. + * Using code from Yves Raimond as a basis. + * Copyright 2007 Queen Mary, University of London. All rights reserved. + * + */ + +#include <iostream> +#include <map> +using namespace std; + +#include "SimpleRDFFeatureWriter.h" +using Vamp::Plugin; + +bool am_initialised = false; +int fe_count = 0; +string timelineURI = ":tl"; //FIXME ? + +void SimpleRDFFeatureWriter::init(const string& trackid, const Plugin::OutputList& outputList) +{ + cerr << "SimpleRDFFeatureWriter init()"<<endl; + + // TODO : Open appropriate output file for writing to - this is specified by a higher power in constructor ? + + // FIXME namespaces : + cout<< "@prefix dc: <http://purl.org/dc/elements/1.1/> .\n" + << "@prefix mo: <http://purl.org/ontology/mo/> .\n" + << "@prefix af: <http://purl.org/ontology/af/>.\n" + << "@prefix event: <http://purl.org/NET/c4dm/event.owl#>.\n" + << "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.\n" + << "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.\n" + << "@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.\n" + << "@prefix timeline: <http://purl.org/NET/c4dm/timeline.owl#>.\n" + << "@prefix time: <http://www.w3.org/2006/time#>.\n" + << "@prefix : <>.\n\n" + << endl; + + /* + * Describe signal we're analysing (AudioFile, Signal, TimeLine, etc.) + */ + cout << "<"<<trackid<<"> a mo:AudioFile .\n\n" + << ":signal a mo:Signal ;" + << " mo:available_as <"<<trackid<<"> ;\n" + << " mo:time :sig_int .\n" + << ":sig_int a time:Interval ;\n" + << " timeline:onTimeLine :tl.\n"; + + /* + * Describe feature events and features. + */ + // TODO : The URIs should be specified in a doc accompanying the Vamp plugin. + // For now, we'll make up local names based on plugin identifier + for (int i=0; i < outputList.size(); i++) + { + Plugin::OutputDescriptor od = outputList[i]; + cout << ":fetype_" << od.identifier << " rdfs:subClassOf af:FeatureEvent;\n" + << " dc:title \"" << od.name << "\"; \n" + << " dc:description \"" << od.description << " event\".\n" + << endl; + + cout << ":ftype_" << od.identifier << " rdfs:subClassOf af:Feature;\n" + << " dc:title \"" << od.name << "\"; \n" + << " dc:description \"" << od.description << "\";\n" + << " dc:format \"" << od.unit << "\".\n\n" + << endl; + } + am_initialised = true; +} + +void SimpleRDFFeatureWriter::write(const string& trackid, const Plugin::OutputList& outputList, const Plugin::FeatureSet& featureSet) +{ + if (!am_initialised) + init(trackid, outputList); + + if (featureSet.size() == 0) + return; + + // iterate through FeatureLists + //cerr << featureSet.size() << " featurelists in set" << endl; + for (map<int, Plugin::FeatureList>::const_iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) + { + Plugin::FeatureList featureList = iter->second; + Plugin::OutputDescriptor od = outputList[iter->first]; + for (int i = 0; i < featureList.size(); ++i) + { + Plugin::Feature feature = featureList[i]; + cout << ":fe_" << fe_count << " rdf:type :fetype_" << od.identifier << ";\n"; + + /* + * Add timestamp + * In current design this is handled by the rebuffering, s.t. all outputs are VariableSampleRate and have a valid timestamp. + */ + if (od.sampleType == Plugin::OutputDescriptor::VariableSampleRate) + { + cout<< " event:time [ rdf:type time:Instant;\n" //location of the event in time + << " time:onTimeLine " << timelineURI << ";\n" + << " time:atDuration \"PT" << feature.timestamp.toString() << "S\"^^xsd:duration;];\n"; + } + else if (od.sampleType == Plugin::OutputDescriptor::OneSamplePerStep) + { + /* + cout<< " event:time [ rdf:type time:Instant;\n" //location of the event in time + << " time:onTimeLine " << timelineURI << ";\n" + << " time:atDuration \"PT" << timestamp.toString() << "S\"^^xsd:duration;];\n"; + */ + cerr<<"Arg, got a OneSamplePerStep plugin but no timestamp, not sure what to do"<<endl; + } + else if (od.sampleType == Plugin::OutputDescriptor::FixedSampleRate) + { + cerr<<"Arg, got a FixedSampleRate plugin, not sure what to do"<<endl; +/* +16:48 < cannam> FixedSampleRate -> somewhat open to interpretation, but I'd say that the return from the first process call would be timestamped with the stamp passed in to the process call +16:48 < cannam> and subsequent ones would increment by 1 / (the sample rate specified in the output descriptor) +16:49 < cannam> I'm not 100% sure, but I think that no actual plugin uses FixedSampleRate at the moment +*/ + } + cout << " af:hasFeature :f_"<<fe_count<<"."<<endl; + + /* + * Add Feature resource + */ + + cout << ":f_"<<fe_count<<" rdf:type :ftype_"<<od.identifier<<""; + if (feature.label.length() > 0) + cout<< ";\n rdfs:label \"" << feature.label << "\""; + + if (feature.values.size() > 0) + { + cout<<";\n"; + + // TODO : If the plugin names its bins we should do one triple per value + // hopefully we have type URIs for the bins from the plugin's RDF file + + + // If the plugin doesn't name its bins there's probably no point separating them, + // so we'll do a CSV literal : + cout << " af:value \""<< feature.values[0]; + for (int j = 1; j < feature.values.size(); ++j) + cout << "," << feature.values[j]; + cout << "\"." << endl; + } + else + cout<< ".\n"; + + fe_count++; + } + } +} \ No newline at end of file Added: runner/trunk/SimpleRDFFeatureWriter.h =================================================================== --- runner/trunk/SimpleRDFFeatureWriter.h (rev 0) +++ runner/trunk/SimpleRDFFeatureWriter.h 2007-11-07 10:17:41 UTC (rev 823) @@ -0,0 +1,24 @@ +/* + * SimpleRDFFeatureWriter.h + * vamphost + * + * Created by Chris Sutton on 01/11/2007. + * Copyright 2007 Queen Mary, University of London. All rights reserved. + * + */ + +#ifndef _SIMPLE_RDF_FEATURE_WRITER_H_ +#define _SIMPLE_RDF_FEATURE_WRITER_H_ + + +#include "FeatureWriter.h" + +class SimpleRDFFeatureWriter : public FeatureWriter +{ +public: + virtual ~SimpleRDFFeatureWriter() { } + virtual void init(const string& trackid, const Vamp::Plugin::OutputList& outputList); + virtual void write(const string& trackid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); +}; + +#endif \ No newline at end of file Added: runner/trunk/main.cpp =================================================================== --- runner/trunk/main.cpp (rev 0) +++ runner/trunk/main.cpp 2007-11-07 10:17:41 UTC (rev 823) @@ -0,0 +1,84 @@ +/* + * main.cpp + * vamphost + * + * Created by Mark Levy on 02/11/2007. + * Copyright 2007 Queen Mary, University of London. All rights reserved. + * + */ + +#include <vector> +#include <string> + +using std::vector; +using std::string; + +#include "FeatureExtractionManager.h" +#include "DefaultFeatureWriter.h" +#include "SimpleRDFFeatureWriter.h" + +int main() +{ + FeatureExtractionManager manager; + manager.setSampleRate(22050); // always work at this rate + manager.setChannels(1); + + // need a strategy for who decides on these... + // - in principle the experimenter should be able to set them + // but each plugin may be allowed to complain in initialise() + // - alternatively the manager should be allowed to reject files + + // note that at present the channel adapter does some of this management silently within the plugin loader + + // TODO: + // currently QTAudioFile is hard-coded to give mono output - add code to act on channels parameter to init() + + // ISSUE: + // we may want to let the experimenter decide to reject tracks that + // have too low a sample rate or too few channels + // - responsibility may have to be refactored out of QTAudioFile + // and PluginChannelAdapter + + vector<FeatureWriter*> writers(1); + //writers[0] = new DefaultFeatureWriter(); // for debug + writers[0] = new SimpleRDFFeatureWriter(); + //writers[0] = new AudioDBFeatureWriter(); // ask Christophe how this should work + + // note that the default writer dumps everything to cerr + // but real writers can write to feature-specific and/or track-specific files + + // an rdf writer just needs to be passed the uri of the audiofile + + // it might make sense to build an audioDB writer from existing Goldsmiths code + + manager.addFeatureExtractor("vamp-example-plugins", "percussiononsets", writers); + manager.addFeatureExtractor("qm-vamp-plugins", "qm-chromagram", writers); + manager.addFeatureExtractor("vamp-example-plugins", "spectralcentroid", writers); + //manager.addFeatureExtractor("vamp-example-plugins", "amplitudefollower", writers); + //manager.addFeatureExtractor("vamp-example-plugins", "spectralcentroid", writers); + + // here we could easily iterate over a generic TrackCollection + // - this gives flexibility e.g. to gather tracks from iTunes using existing SB code + // - it should not be hard to extend this so that you can import a playlist for extraction + // this makes a simple practical tool with no need to build a new user interface + + // manager.setTrackCollection(new ITunesPlaylistTrackCollection("jazz playlist")); + // manager.extractFeaturesForCollection() { + // while (collection.hasMoreTrackUris()) { + // string trackUri = collection.nextTrackUri(); + // extractFeaturesFromStream(trackUri); + // } + // while (collection.hasMoreTrackFilepaths()) { + // string filepath = collection.nextTrackFilepath(); + // extractFeaturesFromFile(filepath); + // } + // } + + //string trackUri = "file:///Downloads/Toni%20Basil%20-%20Mickey.mp3"; + string trackUri = "http://dsp-cluster/music/yvesr/2%20MANY%20DJs/Soulwax%20Radio%20Session%20Part%201%20CD%202/00.%20As%20Heard%20On%20Radio%20Soulwax%20pt.%203.mp3"; + manager.extractFeaturesFromStream(trackUri); + + return 0; +} + + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mh...@us...> - 2007-12-07 16:27:20
|
Revision: 892 http://sv1.svn.sourceforge.net/sv1/?rev=892&view=rev Author: mhlevy Date: 2007-12-07 08:26:58 -0800 (Fri, 07 Dec 2007) Log Message: ----------- first working version with manager Modified Paths: -------------- runner/trunk/FeatureExtractionManager.cpp runner/trunk/FeatureExtractionManager.h runner/trunk/main.cpp runner/trunk/runner.pro Added Paths: ----------- runner/trunk/AudioDBFeatureWriter.cpp runner/trunk/AudioDBFeatureWriter.h runner/trunk/percussiononsets.n3 runner/trunk/qm-keydetector.n3 Removed Paths: ------------- runner/trunk/QTAudioFile.cpp runner/trunk/QTAudioFile.h Added: runner/trunk/AudioDBFeatureWriter.cpp =================================================================== --- runner/trunk/AudioDBFeatureWriter.cpp (rev 0) +++ runner/trunk/AudioDBFeatureWriter.cpp 2007-12-07 16:26:58 UTC (rev 892) @@ -0,0 +1,112 @@ +/* + * DefaultFeatureWriter.cpp + * vamphost + * + * Created by Mark Levy on 01/11/2007. + * Copyright 2007 Queen Mary, Univesity of London. All rights reserved. + * + */ + +#include <fstream> + +using namespace std; + +#include "AudioDBFeatureWriter.h" + +AudioDBFeatureWriter::AudioDBFeatureWriter(const string& catId, const string& dir) : +catalogueId(catId), baseDir(dir) +{ + +} + +AudioDBFeatureWriter::~AudioDBFeatureWriter() +{ + // close all the files + for (map<string, ofstream*>::iterator iter = dbfiles.begin(); iter != dbfiles.end(); ++iter) + iter->second->close(); + + // TODO: error handling on close +} + +void AudioDBFeatureWriter::write(const string& trackid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) +{ + // binary output for FeatureSet + + // feature-dimension feature-1 feature-2 ... + // timestamp-1 timestamp-2 ... + + // iterate through FeatureLists + + for (map<int, Vamp::Plugin::FeatureList>::const_iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) + { + Vamp::Plugin::FeatureList featureList = iter->second; + Vamp::Plugin::OutputDescriptor output = outputList[iter->first]; + for (int i = 0; i < featureList.size(); ++i) + { + if (output.binCount == 0) // this kind of feature just outputs timestamps and labels, assume of no interest to audioDB + continue; + + // audioDB has to write each feature to a different file + // assume a simple naming convention of + // <catalog-id>.<feature-id> + // with timestamps in a corresponding <catalog-id>.<feature-id>.timestamp file + + // the feature writer should hold a map of open file descriptors + // the catalog-id can get passed in to the feature writer's constructor + + // we open them lazily + + // for the feature-id we use the vamp identifier, which is guaranteed short + // and free of white space and punctuation + if (dbfiles.find(output.identifier) == dbfiles.end()) + if (!openDBFile(output.identifier)) + continue; + + // assume for now that we always want a timestamp file and + // that we always have timestamps in the features (which should be the case + // using the buffering adapter) + if (dbfiles.find(output.identifier + ".timestamp") == dbfiles.end()) + if (!openDBFile(output.identifier + ".timestamp")) + continue; + + // TODO: more robust handling of failed file open + // this solution is DANGEROUS if we manage to open it + // but only on a subsequent try!! + + if (trackid != m_trackid) + { + // end the rows in each file if we've finished with a track + if (m_trackid.length() > 0) + { + for (map<string, ofstream*>::iterator iter = dbfiles.begin(); iter != dbfiles.end(); ++iter) + *(iter->second) << endl; + } + + m_trackid = trackid; + + // write the feature length for the next track feature record + // binCount has to be set + // - it can be zero, i.e. if the output is really a set of labels + timestamps + *dbfiles[output.identifier] /*<< ios::binary*/ << output.binCount; + } + + for (int j = 0; j < featureList[i].values.size(); ++j) + *dbfiles[output.identifier] /*<< ios::binary*/ << featureList[i].values[j]; + + *dbfiles[output.identifier + ".timestamp"] /*<< ios::binary*/ << featureList[i].timestamp; + } + } +} + +bool AudioDBFeatureWriter::openDBFile(const string& identifier) +{ + string filepath = baseDir + "/" + catalogueId + "." + identifier; + ofstream* ofs = new ofstream(filepath.c_str()); + if (!*ofs) + { + cerr << "ERROR AudioDBFeatureWriter::openDBFile(): can't open file " << filepath << endl; + return false; + } + dbfiles.insert(pair<string, ofstream*>(identifier, ofs)); + return true; +} \ No newline at end of file Added: runner/trunk/AudioDBFeatureWriter.h =================================================================== --- runner/trunk/AudioDBFeatureWriter.h (rev 0) +++ runner/trunk/AudioDBFeatureWriter.h 2007-12-07 16:26:58 UTC (rev 892) @@ -0,0 +1,39 @@ +/* + * AudioDBFeatureWriter.h + * + * + * Created by Mark Levy on 14/11/2007. + * Copyright 2007 Queen Mary, University of London. All rights reserved. + * + */ + +#ifndef _AUDIO_DB_FEATURE_WRITER_H_ +#define _AUDIO_DB_FEATURE_WRITER_H_ + +#include <string> +#include <fstream> +#include <map> + +using std::string; +using std::ofstream; +using std::map; + +#include "FeatureWriter.h" + +class AudioDBFeatureWriter : public FeatureWriter +{ +public: + AudioDBFeatureWriter(const string& catId, const string& dir); + virtual ~AudioDBFeatureWriter(); + virtual void write(const string& trackid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); + +private: + string catalogueId; + string baseDir; + string m_trackid; + map<string, ofstream*> dbfiles; + + bool openDBFile(const string& identifier); +}; + +#endif \ No newline at end of file Modified: runner/trunk/FeatureExtractionManager.cpp =================================================================== --- runner/trunk/FeatureExtractionManager.cpp 2007-12-06 14:44:57 UTC (rev 891) +++ runner/trunk/FeatureExtractionManager.cpp 2007-12-07 16:26:58 UTC (rev 892) @@ -19,7 +19,11 @@ using Vamp::HostExt::PluginLoader; -#include "PluginBufferingAdapter.h" +#include "data/fileio/FileSource.h" +#include "data/fileio/AudioFileReader.h" +#include "data/fileio/AudioFileReaderFactory.h" +#include "base/TempDirectory.h" + #include "FeatureWriter.h" #include "FeatureExtractionManager.h" @@ -56,29 +60,57 @@ return false; } - // wrap in a buffering adapter, also ensures all features are timestamped - plugin = new Vamp::HostExt::PluginBufferingAdapter(plugin); - plugins.push_back(plugin); pluginWriters.push_back(writers); return true; } -void FeatureExtractionManager::extractFeatures(QTAudioFile qtfile) +void FeatureExtractionManager::extractFeatures(string audioSource) { - // currently we can impose a sample rate and number of channels on QTAudioFile - qtfile.init(m_sampleRate, m_channels); + cerr << "Creating FileSource..." << endl; - // arbitrary fixed block size for QuickTime + FileSource source(audioSource.c_str()); + if (!source.isAvailable()) + { + cerr << "ERROR: File or URL \"" << audioSource << "\" could not be located" << endl; + exit(1); + } + + cerr << "Retrieving or locating \"" << audioSource << "\"..." << endl; + + source.waitForData(); + + cerr << "Opening and/or decoding audio file..." << endl; + + AudioFileReader *reader = AudioFileReaderFactory::createReader(source, m_sampleRate); + + if (!reader) + { + cerr << "ERROR: File or URL \"" << audioSource << "\" could not be opened" << endl; + exit(1); + } + + // read using an arbitrary fixed block size int blockSize = 2048; int stepSize = 2048; - float **plugbuf = new float*[m_channels]; - for (int c = 0; c < m_channels; ++c) plugbuf[c] = new float[blockSize + 2]; - cerr << "Using block size = " << blockSize << ", step size = " << stepSize << endl; + size_t channels = reader->getChannelCount(); + + // reject file if it has too few channels, plugin will handle if it has too many + if (channels < m_channels) + { + cerr << "ERROR: File or URL \"" << audioSource << "\" has less than " << m_channels << " channels" << endl; + exit(1); + } + + // allocate audio buffers + float **data = new float *[m_channels]; + for (size_t c = 0; c < m_channels; ++c) + data[c] = new float[blockSize]; + for (int i = 0; i < plugins.size(); ++i) { int minch = plugins[i]->getMinChannelCount(); @@ -94,54 +126,42 @@ } } - // currently we need a buffer of doubles - easy to change - // - also its only a 1-d array due to the hard-coded mono - // output in QTAudioFile, need to change this - double* qtbuf = new double[blockSize]; - qtfile.setBuffer(qtbuf, blockSize); + size_t frameCount = reader->getFrameCount(); - int n; - int j = 0; - while ((n = qtfile.fillBuffer()) > 0) - { - for (int i = 0; i < n; ++i) - plugbuf[0][i] = (float) qtbuf[i]; + cerr << "file has " << frameCount << " frames" << endl; + + for (size_t i = 0; i < frameCount; i += stepSize) { + + //!!! inefficient, although much of the inefficiency may be + // susceptible to optimisation - // pad last block - for (int i = n; i < blockSize; ++i) - plugbuf[0][i] = 0.0; + SampleBlock frames; + reader->getInterleavedFrames(i, blockSize, frames); + + for (size_t j = 0; j < blockSize; ++j) { + for (size_t c = 0; c < m_channels; ++c) { + size_t index = j * m_channels + c; + if (index < frames.size()) { + data[c][j] = frames[index]; + } else { + data[c][j] = 0.f; + } + } + } + Vamp::RealTime timestamp = Vamp::RealTime::frame2RealTime(i, m_sampleRate); - Vamp::RealTime timestamp = Vamp::RealTime::frame2RealTime(j*blockSize, m_sampleRate); - - for (int i = 0; i < plugins.size(); ++i) + for (int k = 0; k < plugins.size(); ++k) { - Vamp::Plugin::FeatureSet featureSet = plugins[i]->process(plugbuf, timestamp); - for (int j = 0; j < pluginWriters[i].size(); ++j) - pluginWriters[i][j]->write("track01", plugins[i]->getOutputDescriptors(), featureSet); + Vamp::Plugin::FeatureSet featureSet = plugins[k]->process(data, timestamp); + for (int j = 0; j < pluginWriters[k].size(); ++j) + pluginWriters[k][j]->write("track01", plugins[k]->getOutputDescriptors(), featureSet); } - - ++j; } - for (int i = 0; i < plugins.size(); ++i) - for (int j = 0; j < pluginWriters[i].size(); ++j) - pluginWriters[i][j]->write("track01", plugins[i]->getOutputDescriptors(), plugins[i]->getRemainingFeatures()); + for (int k = 0; k < plugins.size(); ++k) + for (int j = 0; j < pluginWriters[k].size(); ++j) + pluginWriters[k][j]->write("track01", plugins[k]->getOutputDescriptors(), plugins[k]->getRemainingFeatures()); - delete [] qtbuf; - qtfile.close(); -} - -void FeatureExtractionManager::extractFeaturesFromFile(string filepath) -{ - QTAudioFile qtfile; - qtfile.open(filepath); - extractFeatures(qtfile); -} - -void FeatureExtractionManager::extractFeaturesFromStream(string url) -{ - QTAudioFile qtfile; - qtfile.openStream(url); - extractFeatures(qtfile); + TempDirectory::getInstance()->cleanup(); } \ No newline at end of file Modified: runner/trunk/FeatureExtractionManager.h =================================================================== --- runner/trunk/FeatureExtractionManager.h 2007-12-06 14:44:57 UTC (rev 891) +++ runner/trunk/FeatureExtractionManager.h 2007-12-07 16:26:58 UTC (rev 892) @@ -17,7 +17,6 @@ using std::string; #include <vamp-sdk/plugin.h> -#include "QTAudioFile.h" class FeatureWriter; @@ -29,9 +28,7 @@ void setChannels(int channels); void setSampleRate(int sampleRate); bool addFeatureExtractor(string library, string plugname, vector<FeatureWriter*> writers); - void extractFeaturesFromFile(string filepath); - void extractFeaturesFromStream(string url); - void extractFeatures(QTAudioFile qtfile); + void extractFeatures(string audioSource); private: vector<Vamp::Plugin*> plugins; vector<vector<FeatureWriter*> > pluginWriters; // parallel vector of writers for each plugin Deleted: runner/trunk/QTAudioFile.cpp =================================================================== --- runner/trunk/QTAudioFile.cpp 2007-12-06 14:44:57 UTC (rev 891) +++ runner/trunk/QTAudioFile.cpp 2007-12-07 16:26:58 UTC (rev 892) @@ -1,306 +0,0 @@ -/* - * QTAudioFile.cpp - * QTAudioFile - * - * Created by Chris Sutton on 02/10/2006. - * Copyright 2006 Chris Sutton and Mark Levy. All rights reserved. - * - */ - -#include "QTAudioFile.h" -#include <string> - -using std::string; - -#define DEBUGMSGS 1 -#define QTAudioFileException 10 - -/* - * Open the audio file at path for decoding, returning 1 on success. - */ -void QTAudioFile::open(string path) -{ -#ifdef WIN32 - theMovie = NULL; - short actualResId = DoTheRightThing; - error = 0; - - FSSpec theFSSpec; - short resRefNum = -1; - - InitializeQTML(0); - - // NOTE different for multi-threaded code... - //EnterMoviesOnThread(0); - EnterMovies(); - - error = NativePathNameToFSSpec(const_cast<char*>(path.c_str()), &theFSSpec, 0 /* flags */); - if (error) - { - printf("NativePathNameToFSSpec failed %d\n", error); - throw QTAudioFileException; - } - - error = OpenMovieFile(&theFSSpec, &resRefNum, 0); - if (error) - { - printf("OpenMovieFile failed %d for file\n%s\n", error, path.c_str()); - throw QTAudioFileException; - } - - error = NewMovieFromFile(&theMovie, resRefNum, &actualResId, (unsigned char *) 0, 0, (Boolean *) 0); - if (error) - { - printf("NewMovieFromFile failed %d\n", error); - throw QTAudioFileException; - } - - if (resRefNum != -1) - CloseMovieFile(resRefNum); -#else - CFURLRef fileLocation; - Handle dataRef; - OSType dataRefType; - long QTversion; - - error = Gestalt(gestaltQuickTime,&QTversion); - if ((error != noErr) || (QTversion < 0x07000000)) - { - printf("ERROR : QuickTime Version 7 or above is not installed !\n"); - throw QTAudioFileException; - } - else - { - dm("Initialising Quicktime, "); - - // NOTE different for multi-threaded code... - //EnterMoviesOnThread(0); - EnterMovies(); - - - dm("Setting fileLocation, "); - - - if (isStream) - { - // this works if the path passed in is a URL - so we can read a stream! - // ALSO it works if passed the raw location from the iTunes Library xml file - // (file://localhost/...) - CFStringRef myURLString = CFStringCreateWithCString(kCFAllocatorDefault, path.c_str(), kCFStringEncodingASCII); - fileLocation = CFURLCreateWithString(NULL, myURLString, NULL); - isStream = false; - } - else - { - // need to use this with a local filepath - dm(const_cast<char*>(path.c_str())); - fileLocation = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)path.c_str(), (CFIndex) path.length(), false); - } - - dm("Creating data reference, "); - - error = QTNewDataReferenceFromCFURL(fileLocation, 0, &dataRef, &dataRefType); - if (error) - { - printf("Error ! Code %d\n", error); - throw QTAudioFileException; - } - - dm("Creating new movie, "); - short fileID = movieInDataForkResID; - short flags = 0; - error = NewMovieFromDataRef(&theMovie, flags, &fileID, dataRef, dataRefType); - if (error) - { - printf("Error ! Code %d\n", error); - throw QTAudioFileException; - } - else dm("File open complete.\n"); - } -#endif - - dm("Checking for DRM... "); - Boolean isProtected = 0; - Track aTrack = GetMovieIndTrackType(theMovie, 1, SoundMediaType, - movieTrackMediaType | movieTrackEnabledOnly); - if (aTrack) - { - Media aMedia = GetTrackMedia(aTrack); // get the track media - if (aMedia) - { - MediaHandler mh = GetMediaHandler(aMedia); // get the media handler we can query - if (mh) - { - error = QTGetComponentProperty(mh, - kQTPropertyClass_DRM, - kQTDRMPropertyID_IsProtected, - sizeof(Boolean), &isProtected,nil); - } - else - error=1; - } - else - error=1; - } - else - error=1; - - if (error && error !=kQTPropertyNotSupportedErr) - { - printf("Error checking for DRM ! Code %d\n", error); - throw QTAudioFileException; - } - else if (!error && isProtected) - { - printf("File is protected with DRM !\n"); - throw QTAudioFileException; - } - else if (error == kQTPropertyNotSupportedErr && !isProtected) - dm("File is not protected with DRM.\n"); -} - -void QTAudioFile::openStream(string url) -{ - isStream = true; - open(url); -} - -/* - * Initialise the movie and set correct output format - */ -void QTAudioFile::init(int sampleRate, int channels) -{ - dm("Setting movie active, "); - SetMovieActive(theMovie, TRUE); - - dm("Beginning extraction session, "); - error = MovieAudioExtractionBegin(theMovie, 0, &extractionSessionRef); - if (error) printf("Error ! Code %d\n", error); - - dm("Setting mono output, "); - AudioChannelLayout monoLayout = {0}; - monoLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono; - error = MovieAudioExtractionSetProperty(extractionSessionRef, - kQTPropertyClass_MovieAudioExtraction_Audio, - kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, - sizeof(monoLayout), &monoLayout); - if (error) printf("Error ! Code %d\n", error); - - dm("Getting default output format : \n"); - error = MovieAudioExtractionGetProperty(extractionSessionRef, - kQTPropertyClass_MovieAudioExtraction_Audio, kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, - sizeof (asbd), &asbd, nil); - if (error) printf("Error ! Code %d\n", error); - printASBD(asbd); - - dm("Setting new output format (22kHz doubles) : \n"); - /* Desired ASBD : */ - asbd.mFormatFlags = kAudioFormatFlagIsFloat | - kAudioFormatFlagIsPacked | - kAudioFormatFlagsNativeEndian; - asbd.mChannelsPerFrame = 1; - asbd.mBitsPerChannel = sizeof(double) * 8; - asbd.mBytesPerFrame = sizeof(double) * asbd.mChannelsPerFrame; - asbd.mBytesPerPacket = asbd.mBytesPerFrame; - asbd.mSampleRate = sampleRate; - - error = MovieAudioExtractionSetProperty(extractionSessionRef, - kQTPropertyClass_MovieAudioExtraction_Audio, kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, - sizeof (asbd), &asbd); - if (error) - printf("Error ! Code %d\n", error); - printASBD(asbd); - - dm("Init complete.\n"); -} - -/* - * Set up output buffers for samples - */ -void QTAudioFile::setBuffer(double* buf, int buflen) -{ - dm("Setting up buffers, "); - UInt32 sampleCount; - numFrames = buflen; - - buffer = (AudioBufferList*) calloc(sizeof(AudioBufferList), 1); - - buffer->mNumberBuffers = 1; - buffer->mBuffers[0].mNumberChannels = asbd.mChannelsPerFrame; - buffer->mBuffers[0].mDataByteSize = sizeof(double) * buffer->mBuffers[0].mNumberChannels * numFrames; - - // samples = (double*) calloc(buffer->mBuffers[0].mDataByteSize, 1); - buffer->mBuffers[0].mData = buf; - sampleCount = numFrames * buffer->mBuffers[0].mNumberChannels; - - dm("Success.\n"); - -} - -/* - * Read numFrames worth of samples into buffers from last position in file - */ -int QTAudioFile::fillBuffer() -{ - UInt32 extractionFlags = 0; - error = MovieAudioExtractionFillBuffer(extractionSessionRef, &numFrames, buffer, &extractionFlags); - if (error) - printf("Error ! Code %d\n", error); - - return numFrames; -} - -/* - * Close audio file and shut down quicktime - */ -void QTAudioFile::close() -{ - dm("Ending extraction session, "); - error = MovieAudioExtractionEnd(extractionSessionRef); - if (error) - printf("Error ! Code %d\n", error); - - dm("Shutting down QuickTime. "); - - // NOTE different for multi-threaded code... - //ExitMoviesOnThread(); - ExitMovies(); - - dm("Success.\n"); -} - -/* - * Pretty printer for ASBDs - */ -void QTAudioFile::printASBD(AudioStreamBasicDescription asbd) -{ - if (DEBUGMSGS) - { - switch(asbd.mFormatID) - { - case kAudioFormatLinearPCM : - printf("ASBD : Format : Linear PCM, "); break; - case kAudioFormatMPEGLayer3 : - printf("ASBD : Format : MP3, "); break; - case kAudioFormatMPEG4AAC : - printf("ASBD : Format : AAC, "); break; - default : - printf("ASBD : Format : Other, enum code %d, ",asbd.mFormatID); break; - } - - // printf("ASBD : Format : %d, ",asbd.mFormatID); - printf("Flags : %d\n",asbd.mFormatFlags); - printf(" Channels : %d\n",asbd.mChannelsPerFrame); - printf(" Fs : %dHz\n",(int)asbd.mSampleRate); - printf(" %d bytes per frame, %d frames per packet\n", asbd.mBytesPerFrame, asbd.mFramesPerPacket); - } -} - -/* - * Output function for debugging info - */ -void QTAudioFile::dm(char msg[]) -{ - if (DEBUGMSGS) printf(msg); -} - Deleted: runner/trunk/QTAudioFile.h =================================================================== --- runner/trunk/QTAudioFile.h 2007-12-06 14:44:57 UTC (rev 891) +++ runner/trunk/QTAudioFile.h 2007-12-07 16:26:58 UTC (rev 892) @@ -1,43 +0,0 @@ -/* - * QTAudioFile.h - * QTAudioFile - * - * Created by Chris Sutton on 02/10/2006. - * Copyright 2006 Chris Sutton and Mark Levy. All rights reserved. - * - */ - -#ifdef WIN32 - #include <QTML.h> - #include <Movies.h> -#else - #include "QuickTime/QuickTime.h" -#endif - -#include <string> - -using std::string; - -class QTAudioFile -{ -public: - QTAudioFile() : isStream(false) { } - virtual ~QTAudioFile() { } - void open(string path); - void openStream(string url); - void init(int sampleRate, int channels); - void setBuffer(double* buf, int buflen); - int fillBuffer(); - void close(); - void printASBD(AudioStreamBasicDescription asbd); - void dm(char msg[]); - - UInt32 numFrames; //Used to indicate how many frames to read and how many have just been read. -private: - MovieAudioExtractionRef extractionSessionRef; - AudioBufferList* buffer; - OSErr error; - AudioStreamBasicDescription asbd; - Movie theMovie; - bool isStream; -}; Modified: runner/trunk/main.cpp =================================================================== --- runner/trunk/main.cpp 2007-12-06 14:44:57 UTC (rev 891) +++ runner/trunk/main.cpp 2007-12-07 16:26:58 UTC (rev 892) @@ -16,41 +16,32 @@ #include "FeatureExtractionManager.h" #include "DefaultFeatureWriter.h" #include "SimpleRDFFeatureWriter.h" +#include "AudioDBFeatureWriter.h" -int main() +int main(int argc, char **argv) { FeatureExtractionManager manager; + + // the manager dictates the sample rate and number of channels + // to work at - files with too few channels are rejected, + // too many channels are handled as usual by the Vamp plugin manager.setSampleRate(22050); // always work at this rate manager.setChannels(1); - // need a strategy for who decides on these... - // - in principle the experimenter should be able to set them - // but each plugin may be allowed to complain in initialise() - // - alternatively the manager should be allowed to reject files + vector<FeatureWriter*> writers; + writers.push_back(new DefaultFeatureWriter()); // for debug - // note that at present the channel adapter does some of this management silently within the plugin loader + string writerType = ""; + if (argc > 1) + writerType = argv[1]; + if (writerType == "rdf") + writers.push_back(new SimpleRDFFeatureWriter()); + if (writerType == "adb") + writers.push_back(new AudioDBFeatureWriter("catalog01", "audiodb")); - // TODO: - // currently QTAudioFile is hard-coded to give mono output - add code to act on channels parameter to init() - - // ISSUE: - // we may want to let the experimenter decide to reject tracks that - // have too low a sample rate or too few channels - // - responsibility may have to be refactored out of QTAudioFile - // and PluginChannelAdapter - - vector<FeatureWriter*> writers(1); - //writers[0] = new DefaultFeatureWriter(); // for debug - writers[0] = new SimpleRDFFeatureWriter(); - //writers[0] = new AudioDBFeatureWriter(); // ask Christophe how this should work - // note that the default writer dumps everything to cerr // but real writers can write to feature-specific and/or track-specific files - // an rdf writer just needs to be passed the uri of the audiofile - - // it might make sense to build an audioDB writer from existing Goldsmiths code - manager.addFeatureExtractor("vamp-example-plugins", "percussiononsets", writers); manager.addFeatureExtractor("qm-vamp-plugins", "qm-chromagram", writers); manager.addFeatureExtractor("vamp-example-plugins", "spectralcentroid", writers); @@ -75,8 +66,11 @@ // } //string trackUri = "file:///Downloads/Toni%20Basil%20-%20Mickey.mp3"; - string trackUri = "http://dsp-cluster/music/yvesr/2%20MANY%20DJs/Soulwax%20Radio%20Session%20Part%201%20CD%202/00.%20As%20Heard%20On%20Radio%20Soulwax%20pt.%203.mp3"; - manager.extractFeaturesFromStream(trackUri); + //string trackUri = "http://dsp-cluster/music/yvesr/2%20MANY%20DJs/Soulwax%20Radio%20Session%20Part%201%20CD%202/00.%20As%20Heard%20On%20Radio%20Soulwax%20pt.%203.mp3"; + string trackUri = "/users/mark/documents/tags/audio/999.mp3"; + if (argc > 2) + trackUri = argv[2]; + manager.extractFeatures(trackUri); return 0; } Added: runner/trunk/percussiononsets.n3 =================================================================== --- runner/trunk/percussiononsets.n3 (rev 0) +++ runner/trunk/percussiononsets.n3 2007-12-07 16:26:58 UTC (rev 892) @@ -0,0 +1,70 @@ +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>. +@prefix xsd: <http://www.w3.org/2001/XMLSchema#>. +@prefix vamp: <http://www.vamp-plugins.org/ontology/> . +@prefix vampex: <http://www.vamp-plugins.org/examples/> . +@prefix owl: <http://www.w3.org/2002/07/owl#> . +@prefix dc: <http://purl.org/dc/elements/1.1/> . +@prefix af: <http://purl.org/ontology/af/> . +@prefix foaf: <http://xmlns.com/foaf/0.1/> . +@prefix cc: <http://web.resource.org/cc/> . +@prefix thisplug: <http://www.vamp-plugins.org/examples/percussiononsets#>. +@prefix : <> . + +<> a vamp:PluginDescription ; + foaf:maker <http://chrissutton.org/me> ; + foaf:primaryTopic vampex:percussiononsets . + +vampex:percussiononsets a vamp:Plugin ; + dc:title "Simple Percussion Onset Detector" ; + dc:description "Detect percussive note onsets by identifying broadband energy rises"; + foaf:maker <http://www.all-day-breakfast.com/cannam> ; #we'll pretend this is his URI + cc:license <http://creativecommons.org/licenses/BSD/> ; + vamp:identifier "percussiononsets" ; # The Vamp identifier for the plugin + vamp:vamp_API_version vamp:version_v1.1b ; # Made up - this plugin doesn't actually specify it + owl:versionInfo "2" ; + vamp:input_domain vamp:TimeDomain ; # Made up - this plugin doesn't actually specify it + + vamp:parameter_descriptor thisplug:pd1 ; + vamp:parameter_descriptor thisplug:pd2 ; + vamp:output_descriptor thisplug:od1 ; + vamp:output_descriptor thisplug:od2 . + + +thisplug:pd1 a vamp:ParameterDescriptor ; + vamp:identifier "threshold" ; + dc:title "Energy Rise threshold" ; + dc:description "Energy rise within a frequency bin necessary to count toward broadband total" ; + dc:format "dB" ; + vamp:minValue 0 ; #might be useful when interpreting plugin output + vamp:maxValue 20 ; + vamp:defaultValue 3 . + + +thisplug:pd2 a vamp:ParameterDescriptor ; + vamp:identifier "sensitivity" ; + dc:title "Sensitivity" ; + dc:description "Sensitivity of peak detector applied to broadband detection function" ; + dc:format "%" ; + vamp:minValue 0 ; #might be useful when interpreting plugin output + vamp:maxValue 100 ; + vamp:defaultValue 40 . + +thisplug:od1 a vamp:OutputDescriptor ; + vamp:identifier "onsets" ; + dc:title "Onsets" ; + dc:description "Percussive note onset locations" ; + dc:format "" ; + vamp:fixed_bin_count "true" ; + vamp:bin_count 0 ; + vamp:sample_type vamp:VariableSampleRate ; + vamp:computes_event_type af:Onset . # af:Onset is pending some thought + +thisplug:od2 a vamp:OutputDescriptor ; + vamp:identifier "detectionfunction" ; + dc:title "Detection Function" ; + dc:description "Broadband energy rise detection function"; + dc:format "" ; + vamp:fixed_bin_count "true" ; + vamp:bin_count 1 ; + vamp:sample_type vamp:OneSamplePerStep ; + vamp:computes_feature_type af:OnsetDetectionFunction . Added: runner/trunk/qm-keydetector.n3 =================================================================== --- runner/trunk/qm-keydetector.n3 (rev 0) +++ runner/trunk/qm-keydetector.n3 2007-12-07 16:26:58 UTC (rev 892) @@ -0,0 +1,77 @@ +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>. +@prefix xsd: <http://www.w3.org/2001/XMLSchema#>. +@prefix vamp: <http://www.vamp-plugins.org/ontology/> . +@prefix vampex: <http://www.vamp-plugins.org/examples/> . +@prefix qvp: <http://vamp-plugins.org/plugin/qm-vamp-plugins/>. +@prefix owl: <http://www.w3.org/2002/07/owl#> . +@prefix dc: <http://purl.org/dc/elements/1.1/> . +@prefix af: <http://purl.org/ontology/af/> . +@prefix foaf: <http://xmlns.com/foaf/0.1/> . +@prefix cc: <http://web.resource.org/cc/> . +@prefix thisplug: <http://vamp-plugins.org/plugin/qm-vamp-plugins/qm-keydetector#> . +@prefix : <> . + +<> a vamp:PluginDescription ; + foaf:maker <http://chrissutton.org/me> ; + foaf:primaryTopic qvp:qm-keydetector . + +qvp:qm-keydetector a vamp:Plugin ; + dc:title "Key Detector" ; + dc:description ""; + foaf:maker :katynoland, :chrislandone ; +# cc:license <http://creativecommons.org/licenses/BSD/> ; what is the license for QM Vamp plugins ? + vamp:identifier "qm-keydetector" ; # The Vamp identifier for the plugin + vamp:vamp_API_version vamp:version_v1.1b ; # Made up - this plugin doesn't actually specify it + owl:versionInfo "2" ; + vamp:input_domain vamp:TimeDomain ; + + vamp:parameter_descriptor thisplug:pd1 ; + vamp:parameter_descriptor thisplug:pd2 ; + vamp:output_descriptor thisplug:od1 ; + vamp:output_descriptor thisplug:od2 ; + vamp:output_descriptor thisplug:od3 . + +:katynoland a foaf:Person; + foaf:name "Katy Noland" . +:chrislandone a foaf:Person; + foaf:name "Christian Landone" . + +# Note : any need for these to have proper URIs ? +thisplug:pd1 a vamp:ParameterDescriptor ; + vamp:identifier "tuning" ; + dc:title "Tuning Frequency" ; + dc:format "Hz" ; + vamp:minValue 420 ; #might be useful when interpreting plugin output + vamp:maxValue 460 ; + vamp:defaultValue 440 . + +thisplug:pd2 a vamp:ParameterDescriptor ; + vamp:identifier "length" ; + dc:title "Window Length" ; + vamp:minValue 1 ; #might be useful when interpreting plugin output + vamp:maxValue 30 ; + vamp:defaultValue 10 . + +thisplug:od1 a vamp:OutputDescriptor ; + vamp:identifier "tonic" ; + dc:title "Tonic Pitch" ; + vamp:fixed_bin_count "true" ; + vamp:bin_count 1 ; + vamp:sample_type vamp:OneSamplePerStep . + + +thisplug:od2 a vamp:OutputDescriptor ; + vamp:identifier "mode" ; + dc:title "Key Mode" ; + vamp:fixed_bin_count "true" ; + vamp:bin_count 1 ; + vamp:bin_names "Major = 0, Minor = 1" ; # might need a rethink + vamp:sample_type vamp:OneSamplePerStep . + +thisplug:od3 a vamp:OutputDescriptor ; + vamp:identifier "key" ; + dc:title "Key" ; + vamp:fixed_bin_count "true" ; + vamp:bin_count 1 ; + vamp:sample_type vamp:OneSamplePerStep ; + vamp:computes_feature_type <http://purl.org/NET/c4dm/keys.owl#Key> . Modified: runner/trunk/runner.pro =================================================================== --- runner/trunk/runner.pro 2007-12-06 14:44:57 UTC (rev 891) +++ runner/trunk/runner.pro 2007-12-07 16:26:58 UTC (rev 892) @@ -28,7 +28,7 @@ # Input HEADERS += -SOURCES += runner.cpp +SOURCES += main.cpp DefaultFeatureWriter.cpp SimpleRDFFeatureWriter.cpp FeatureExtractionManager.cpp AudioDBFeatureWriter.cpp This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mh...@us...> - 2007-12-10 12:50:43
|
Revision: 895 http://sv1.svn.sourceforge.net/sv1/?rev=895&view=rev Author: mhlevy Date: 2007-12-10 04:49:58 -0800 (Mon, 10 Dec 2007) Log Message: ----------- primitive use of Transform struct to record extraction parameters Modified Paths: -------------- runner/trunk/FeatureExtractionManager.cpp runner/trunk/FeatureExtractionManager.h runner/trunk/main.cpp Removed Paths: ------------- runner/trunk/PluginBufferingAdapter.cpp runner/trunk/PluginBufferingAdapter.h Modified: runner/trunk/FeatureExtractionManager.cpp =================================================================== --- runner/trunk/FeatureExtractionManager.cpp 2007-12-07 16:47:31 UTC (rev 894) +++ runner/trunk/FeatureExtractionManager.cpp 2007-12-10 12:49:58 UTC (rev 895) @@ -1,6 +1,6 @@ /* * FeatureExtractionManager.cpp - * vamphost + * runner * * Created by Mark Levy on 31/10/2007. * Copyright 2007 Queen Mary, University of London. All rights reserved. @@ -23,10 +23,12 @@ #include "data/fileio/AudioFileReader.h" #include "data/fileio/AudioFileReaderFactory.h" #include "base/TempDirectory.h" +#include "plugin/transform/TransformFactory.h" #include "FeatureWriter.h" #include "FeatureExtractionManager.h" +#include <QTextStream> FeatureExtractionManager::FeatureExtractionManager() { @@ -63,6 +65,12 @@ plugins.push_back(plugin); pluginWriters.push_back(writers); + // create a Transform recording all the parameter settings etc. + Transform transform; + transform = TransformFactory::getInstance()->getDefaultTransformFor(("vamp:" + library + ":" + plugname).c_str(), m_sampleRate); // transformId starts with the plugin subdirectory + TransformFactory::getInstance()->setParametersFromPlugin(transform, plugin); + transforms.push_back(transform); + return true; } @@ -160,8 +168,28 @@ } for (int k = 0; k < plugins.size(); ++k) + { for (int j = 0; j < pluginWriters[k].size(); ++j) + { pluginWriters[k][j]->write("track01", plugins[k]->getOutputDescriptors(), plugins[k]->getRemainingFeatures()); + + // we may want to set the start and duration times for extraction + // in the transform record (defaults of zero indicate extraction + // from the whole file) + transforms[k].setStartTime(RealTime()); + transforms[k].setDuration(RealTime::frame2RealTime(reader->getFrameCount(), m_sampleRate)); + + // show the transform + QString qs; + QTextStream qts(&qs); + transforms[k].toXml(qts); + cerr << qs.toStdString() << endl << endl; + + // guess we could now pass it to the writers + // in case they wanted to add header information + // or even rename files according to some convention + } + } TempDirectory::getInstance()->cleanup(); } \ No newline at end of file Modified: runner/trunk/FeatureExtractionManager.h =================================================================== --- runner/trunk/FeatureExtractionManager.h 2007-12-07 16:47:31 UTC (rev 894) +++ runner/trunk/FeatureExtractionManager.h 2007-12-10 12:49:58 UTC (rev 895) @@ -1,6 +1,6 @@ /* * FeatureExtractionManager.h - * vamphost + * runner * * Created by Mark Levy on 31/10/2007. * Copyright 2007 Queen Mary, University of London. All rights reserved. @@ -17,6 +17,7 @@ using std::string; #include <vamp-sdk/plugin.h> +#include <plugin/transform/Transform.h> class FeatureWriter; @@ -32,6 +33,7 @@ private: vector<Vamp::Plugin*> plugins; vector<vector<FeatureWriter*> > pluginWriters; // parallel vector of writers for each plugin + vector<Transform> transforms; // parallel vector of transform records for each plugin int m_sampleRate; int m_channels; }; Deleted: runner/trunk/PluginBufferingAdapter.cpp =================================================================== --- runner/trunk/PluginBufferingAdapter.cpp 2007-12-07 16:47:31 UTC (rev 894) +++ runner/trunk/PluginBufferingAdapter.cpp 2007-12-10 12:49:58 UTC (rev 895) @@ -1,286 +0,0 @@ -/* - * PluginBufferingAdapter.cpp - * vamphost - * - * Created by Mark Levy on 29/10/2007. - * Copyright 2007 Queen Mary, University of London. All rights reserved. - * - */ - -#include <vector> -#include <map> - -using std::vector; -using std::map; - -#include "PluginBufferingAdapter.h" - -namespace Vamp { - - namespace HostExt { - - class PluginBufferingAdapter::Impl - { -public: - Impl(Plugin *plugin, size_t inputSampleRate); - ~Impl(); - - bool initialise(size_t channels, size_t stepSize, size_t blockSize); - - FeatureSet process(const float *const *inputBuffers, RealTime timestamp); - - FeatureSet getRemainingFeatures(); - - OutputList getOutputDescriptors() const; - -protected: - Plugin *m_plugin; - size_t m_inputStepSize; - size_t m_inputBlockSize; - size_t m_stepSize; - size_t m_blockSize; - size_t m_channels; - vector<vector<float> > m_queue; - float **m_buffers; // in fact an array of pointers into the queue - size_t m_inputPos; // start position in the queue of next input block - size_t m_inputSampleRate; - RealTime m_timestamp; - OutputList m_outputs; - - void processBlock(FeatureSet& allFeatureSets, RealTime timestamp); - }; - - PluginBufferingAdapter::PluginBufferingAdapter(Plugin *plugin) : - PluginWrapper(plugin) - { - m_impl = new Impl(plugin, m_inputSampleRate); - } - - PluginBufferingAdapter::~PluginBufferingAdapter() - { - delete m_impl; - } - - bool - PluginBufferingAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize) - { - return m_impl->initialise(channels, stepSize, blockSize); - } - - PluginBufferingAdapter::FeatureSet - PluginBufferingAdapter::process(const float *const *inputBuffers, - RealTime timestamp) - { - return m_impl->process(inputBuffers, timestamp); - } - - PluginBufferingAdapter::FeatureSet - PluginBufferingAdapter::getRemainingFeatures() - { - return m_impl->getRemainingFeatures(); - } - - PluginBufferingAdapter::OutputList - PluginBufferingAdapter::getOutputDescriptors() const - { - return m_impl->getOutputDescriptors(); - } - - - PluginBufferingAdapter::Impl::Impl(Plugin *plugin, size_t inputSampleRate) : - m_plugin(plugin), - m_inputStepSize(0), - m_inputBlockSize(0), - m_stepSize(0), - m_blockSize(0), - m_channels(0), - m_buffers(0), - m_inputPos(0), - m_inputSampleRate(inputSampleRate), - m_timestamp(), - m_outputs(m_plugin->getOutputDescriptors()) - { - } - - PluginBufferingAdapter::Impl::~Impl() - { - // the adapter will delete the plugin - - delete [] m_buffers; - } - - PluginBufferingAdapter::OutputList - PluginBufferingAdapter::Impl::getOutputDescriptors() const - { - OutputList outputs; - // adapter always sets the timestamp, alert clients by setting sampleType - for (int i = 0; i < m_outputs.size(); ++i) - { - outputs.push_back(OutputDescriptor(m_outputs[i])); - outputs[i].sampleType = OutputDescriptor::VariableSampleRate; - } - return outputs; - } - - - bool - PluginBufferingAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize) - { - m_channels = channels; - m_inputStepSize = stepSize; - m_inputBlockSize = blockSize; - - // use the step and block sizes which the plugin prefers - m_stepSize = m_plugin->getPreferredStepSize(); - m_blockSize = m_plugin->getPreferredBlockSize(); - - // or sensible defaults if it has no preference - if (m_blockSize == 0) { - m_blockSize = 1024; - } - if (m_stepSize == 0) { - if (m_plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain) { - m_stepSize = m_blockSize/2; - } else { - m_stepSize = m_blockSize; - } - } else if (m_stepSize > m_blockSize) { - if (m_plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain) { - m_blockSize = m_stepSize * 2; - } else { - m_blockSize = m_stepSize; - } - } - - std::cerr << "PluginBufferingAdapter::initialise: stepSize " << m_inputStepSize << " -> " << m_stepSize - << ", blockSize " << m_inputBlockSize << " -> " << m_blockSize << std::endl; - - // current implementation breaks if step is greater than block - if (m_stepSize > m_blockSize) { - std::cerr << "PluginBufferingAdapter::initialise: plugin's preferred stepSize greater than blockSize, giving up!" << std::endl; - return false; - } - - m_queue.resize(m_channels); - m_buffers = new float*[m_channels]; - - return m_plugin->initialise(m_channels, m_stepSize, m_blockSize); - } - - PluginBufferingAdapter::FeatureSet - PluginBufferingAdapter::Impl::process(const float *const *inputBuffers, - RealTime timestamp) - { - FeatureSet allFeatureSets; - - // queue the new input - - //std::cerr << "unread " << m_queue[0].size() - m_inputPos << " samples" << std::endl; - //std::cerr << "queueing " << m_inputBlockSize - (m_queue[0].size() - m_inputPos) << " samples" << std::endl; - - for (int i = 0; i < m_channels; ++i) - for (int j = m_queue[0].size() - m_inputPos; j < m_inputBlockSize; ++j) - m_queue[i].push_back(inputBuffers[i][j]); - - m_inputPos += m_inputStepSize; - - // process as much as we can - while (m_queue[0].size() >= m_blockSize) - { - processBlock(allFeatureSets, timestamp); - m_inputPos -= m_stepSize; - - //std::cerr << m_queue[0].size() << " samples still left in queue" << std::endl; - //std::cerr << "inputPos = " << m_inputPos << std::endl; - } - - return allFeatureSets; - } - - PluginBufferingAdapter::FeatureSet - PluginBufferingAdapter::Impl::getRemainingFeatures() - { - FeatureSet allFeatureSets; - - // process remaining samples in queue - while (m_queue[0].size() >= m_blockSize) - { - processBlock(allFeatureSets, m_timestamp); - } - - // pad any last samples remaining and process - if (m_queue[0].size() > 0) - { - for (int i = 0; i < m_channels; ++i) - while (m_queue[i].size() < m_blockSize) - m_queue[i].push_back(0.0); - processBlock(allFeatureSets, m_timestamp); - } - - // get remaining features - FeatureSet featureSet = m_plugin->getRemainingFeatures(); - for (map<int, FeatureList>::iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) - { - FeatureList featureList = iter->second; - for (int i = 0; i < featureList.size(); ++i) - allFeatureSets[iter->first].push_back(featureList[i]); - } - - return allFeatureSets; - } - - void - PluginBufferingAdapter::Impl::processBlock(FeatureSet& allFeatureSets, RealTime timestamp) - { - //std::cerr << m_queue[0].size() << " samples left in queue" << std::endl; - - // point the buffers to the head of the queue - for (int i = 0; i < m_channels; ++i) - m_buffers[i] = &m_queue[i][0]; - - FeatureSet featureSet = m_plugin->process(m_buffers, m_timestamp); - - for (map<int, FeatureList>::iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) - { - - FeatureList featureList = iter->second; - int outputNo = iter->first; - - for (int i = 0; i < featureList.size(); ++i) - { - - // make sure the timestamp is set - switch (m_outputs[outputNo].sampleType) - { - case OutputDescriptor::OneSamplePerStep: - featureList[i].timestamp = m_timestamp; // use our internal timestamp - OK???? - break; - case OutputDescriptor::FixedSampleRate: - featureList[i].timestamp = m_timestamp; // use our internal timestamp - break; - case OutputDescriptor::VariableSampleRate: - break; // plugin must set timestamp - default: - break; - } - - allFeatureSets[outputNo].push_back(featureList[i]); - } - } - - // step forward - for (int i = 0; i < m_channels; ++i) - m_queue[i].erase(m_queue[i].begin(), m_queue[i].begin() + m_stepSize); - - // fake up the timestamp each time we step forward - //std::cerr << m_timestamp; - long frame = RealTime::realTime2Frame(m_timestamp, m_inputSampleRate); - m_timestamp = RealTime::frame2RealTime(frame + m_stepSize, m_inputSampleRate); - //std::cerr << "--->" << m_timestamp << std::endl; - } - - } - -} - - Deleted: runner/trunk/PluginBufferingAdapter.h =================================================================== --- runner/trunk/PluginBufferingAdapter.h 2007-12-07 16:47:31 UTC (rev 894) +++ runner/trunk/PluginBufferingAdapter.h 2007-12-10 12:49:58 UTC (rev 895) @@ -1,64 +0,0 @@ -/* - * PluginBufferingAdapter.h - * vamphost - * - * Created by Mark Levy on 29/10/2007. - * Copyright 2007 Queen Mary, University of London. All rights reserved. - * - */ - -#ifndef _VAMP_PLUGIN_BUFFERING_ADAPTER_H_ -#define _VAMP_PLUGIN_BUFFERING_ADAPTER_H_ - -#include <vamp-sdk/hostext/PluginWrapper.h> - -namespace Vamp { - - namespace HostExt { - - /** - * \class PluginBufferingAdapter PluginBufferingAdapter.h - * - * PluginBufferingAdapter is a Vamp plugin adapter that allows plugins - * to be used by a host supplying an audio stream in non-overlapping buffers - * of arbitrary size. - * A host using PluginBufferingAdapter may ignore the getPreferredStepSize - * and getPreferredBlockSize reported by the plugin, and still expect the - * plugin to run. The value of blockSize passed to initialise should be the - * size of the buffer which the host will supply. Any dummy value for stepSize - * can be passed to initialise and will be ignored. - * - * In every respect other than its management of buffering, the - * PluginBufferingAdapter behaves identically to the plugin that it - * wraps. The wrapped plugin will be deleted when the wrapper is - * deleted. - * - * NO! - this adapter now ensures that a timestamp is set - * in every output feature - * - */ - - class PluginBufferingAdapter : public PluginWrapper - { - public: - PluginBufferingAdapter(Plugin *plugin); // I take ownership of plugin - virtual ~PluginBufferingAdapter(); - - bool initialise(size_t channels, size_t stepSize, size_t blockSize); - - FeatureSet process(const float *const *inputBuffers, RealTime timestamp); - - FeatureSet getRemainingFeatures(); - - OutputList getOutputDescriptors() const; - - protected: - class Impl; - Impl *m_impl; - }; - - } - -} - -#endif Modified: runner/trunk/main.cpp =================================================================== --- runner/trunk/main.cpp 2007-12-07 16:47:31 UTC (rev 894) +++ runner/trunk/main.cpp 2007-12-10 12:49:58 UTC (rev 895) @@ -39,6 +39,17 @@ if (writerType == "adb") writers.push_back(new AudioDBFeatureWriter("catalog01", "audiodb")); + /* + // list all the available plugins as transforms + TransformList transforms = TransformFactory::getInstance()->getAllTransformDescriptions(); + for (TransformList::iterator iter = transforms.begin(); iter != transforms.end(); ++iter) + { + TransformDescription transform = *iter; + + cerr << transform.identifier.toStdString() << endl << endl; + } + */ + // note that the default writer dumps everything to cerr // but real writers can write to feature-specific and/or track-specific files This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mh...@us...> - 2007-12-10 16:42:31
|
Revision: 898 http://sv1.svn.sourceforge.net/sv1/?rev=898&view=rev Author: mhlevy Date: 2007-12-10 08:42:27 -0800 (Mon, 10 Dec 2007) Log Message: ----------- now running from saved transform xml files Modified Paths: -------------- runner/trunk/FeatureExtractionManager.cpp runner/trunk/FeatureExtractionManager.h runner/trunk/main.cpp Added Paths: ----------- runner/trunk/transforms/ runner/trunk/transforms/chromagram.xml runner/trunk/transforms/percussiononsets.xml runner/trunk/transforms/spectralcentroid.xml Modified: runner/trunk/FeatureExtractionManager.cpp =================================================================== --- runner/trunk/FeatureExtractionManager.cpp 2007-12-10 15:32:40 UTC (rev 897) +++ runner/trunk/FeatureExtractionManager.cpp 2007-12-10 16:42:27 UTC (rev 898) @@ -11,13 +11,16 @@ using namespace std; -#include <vamp-sdk/PluginHostAdapter.h> #include <vamp-sdk/hostext/PluginChannelAdapter.h> +#include <vamp-sdk/hostext/PluginBufferingAdapter.h> #include <vamp-sdk/hostext/PluginInputDomainAdapter.h> #include <vamp-sdk/hostext/PluginLoader.h> -#include <vamp/vamp.h> +using Vamp::Plugin; using Vamp::HostExt::PluginLoader; +using Vamp::HostExt::PluginChannelAdapter; +using Vamp::HostExt::PluginBufferingAdapter; +using Vamp::HostExt::PluginInputDomainAdapter; #include "data/fileio/FileSource.h" #include "data/fileio/AudioFileReader.h" @@ -29,6 +32,7 @@ #include "FeatureExtractionManager.h" #include <QTextStream> +#include <QFile> FeatureExtractionManager::FeatureExtractionManager() { @@ -56,7 +60,7 @@ PluginLoader::PluginKey key = loader->composePluginKey(library, plugname); - Vamp::Plugin *plugin = loader->loadPlugin(key, m_sampleRate, PluginLoader::ADAPT_ALL); + Plugin* plugin = loader->loadPlugin(key, m_sampleRate, PluginLoader::ADAPT_ALL); if (!plugin) { cerr << "ERROR: Failed to load plugin \"" << plugin << "\" from library \"" << library << "\"" << endl; return false; @@ -68,12 +72,50 @@ // create a Transform recording all the parameter settings etc. Transform transform; transform = TransformFactory::getInstance()->getDefaultTransformFor(("vamp:" + library + ":" + plugname).c_str(), m_sampleRate); // transformId starts with the plugin subdirectory + // we can probably get this from PluginLoader::getLibraryPathForPlugin(PluginKey plugin)... if that makes sense in our workflow TransformFactory::getInstance()->setParametersFromPlugin(transform, plugin); transforms.push_back(transform); return true; } +bool FeatureExtractionManager::addFeatureExtractor(string transformXmlFile, vector<FeatureWriter*> writers) +{ + FILE* file = fopen(transformXmlFile.c_str(),"r"); + QTextStream qts(file); + QString qs = qts.readAll(); + fclose(file); + Transform transform(qs); + + if (transform.getSampleRate() != m_sampleRate) + { + cerr << "ERROR: transform sample rate " << transform.getSampleRate() << " doesn't match the one you set for audio extraction " << m_sampleRate << endl; + print(transform); + cerr << endl; + return false; + } + + Plugin* plugin = TransformFactory::getInstance()->downcastVampPlugin(TransformFactory::getInstance()->instantiatePluginFor(transform)); + if (!plugin) { + cerr << "ERROR: Failed to load plugin from transform " << transformXmlFile << endl; + print(transform); + cerr << endl; + return false; + } + + // adapt the plugin for buffering, channels, etc. + if (plugin->getInputDomain() == Plugin::FrequencyDomain) + plugin = new PluginInputDomainAdapter(plugin); + plugin = new PluginBufferingAdapter(plugin); + plugin = new PluginChannelAdapter(plugin); + + plugins.push_back(plugin); + pluginWriters.push_back(writers); + transforms.push_back(transform); + + return true; +} + void FeatureExtractionManager::extractFeatures(string audioSource) { cerr << "Creating FileSource..." << endl; @@ -138,6 +180,10 @@ cerr << "file has " << frameCount << " frames" << endl; + // we may want to control the start and end times + // for feature extraction - this code just process + // the whole file + for (size_t i = 0; i < frameCount; i += stepSize) { //!!! inefficient, although much of the inefficiency may be @@ -169,27 +215,29 @@ for (int k = 0; k < plugins.size(); ++k) { + // we may want to set the start and duration times for extraction + // in the transform record (defaults of zero indicate extraction + // from the whole file) + transforms[k].setStartTime(RealTime()); + transforms[k].setDuration(RealTime::frame2RealTime(reader->getFrameCount(), m_sampleRate)); + + print(transforms[k]); + + // guess we could now pass it to the writers + // in case they wanted to add header information + // or even rename files according to some convention + for (int j = 0; j < pluginWriters[k].size(); ++j) - { pluginWriters[k][j]->write("track01", plugins[k]->getOutputDescriptors(), plugins[k]->getRemainingFeatures()); - - // we may want to set the start and duration times for extraction - // in the transform record (defaults of zero indicate extraction - // from the whole file) - transforms[k].setStartTime(RealTime()); - transforms[k].setDuration(RealTime::frame2RealTime(reader->getFrameCount(), m_sampleRate)); - - // show the transform - QString qs; - QTextStream qts(&qs); - transforms[k].toXml(qts); - cerr << qs.toStdString() << endl << endl; - - // guess we could now pass it to the writers - // in case they wanted to add header information - // or even rename files according to some convention - } } TempDirectory::getInstance()->cleanup(); +} + +void FeatureExtractionManager::print(Transform transform) const +{ + QString qs; + QTextStream qts(&qs); + transform.toXml(qts); + cerr << qs.toStdString() << endl; } \ No newline at end of file Modified: runner/trunk/FeatureExtractionManager.h =================================================================== --- runner/trunk/FeatureExtractionManager.h 2007-12-10 15:32:40 UTC (rev 897) +++ runner/trunk/FeatureExtractionManager.h 2007-12-10 16:42:27 UTC (rev 898) @@ -28,6 +28,7 @@ virtual ~FeatureExtractionManager(); void setChannels(int channels); void setSampleRate(int sampleRate); + bool FeatureExtractionManager::addFeatureExtractor(string transformXmlFile, vector<FeatureWriter*> writers); bool addFeatureExtractor(string library, string plugname, vector<FeatureWriter*> writers); void extractFeatures(string audioSource); private: @@ -36,6 +37,8 @@ vector<Transform> transforms; // parallel vector of transform records for each plugin int m_sampleRate; int m_channels; + + void print(Transform transform) const; }; #endif \ No newline at end of file Modified: runner/trunk/main.cpp =================================================================== --- runner/trunk/main.cpp 2007-12-10 15:32:40 UTC (rev 897) +++ runner/trunk/main.cpp 2007-12-10 16:42:27 UTC (rev 898) @@ -50,14 +50,23 @@ } */ + // we may want to work from saved transforms here if we + // already know what features we want + // - this is the audioDB scenario + manager.addFeatureExtractor("/users/mark/documents/src/runner/transforms/percussiononsets.xml", writers); + manager.addFeatureExtractor("/users/mark/documents/src/runner/transforms/chromagram.xml", writers); + manager.addFeatureExtractor("/users/mark/documents/src/runner/transforms/spectralcentroid.xml", writers); + // note that the default writer dumps everything to cerr // but real writers can write to feature-specific and/or track-specific files + /* manager.addFeatureExtractor("vamp-example-plugins", "percussiononsets", writers); manager.addFeatureExtractor("qm-vamp-plugins", "qm-chromagram", writers); manager.addFeatureExtractor("vamp-example-plugins", "spectralcentroid", writers); //manager.addFeatureExtractor("vamp-example-plugins", "amplitudefollower", writers); //manager.addFeatureExtractor("vamp-example-plugins", "spectralcentroid", writers); + */ // here we could easily iterate over a generic TrackCollection // - this gives flexibility e.g. to gather tracks from iTunes using existing SB code Added: runner/trunk/transforms/chromagram.xml =================================================================== --- runner/trunk/transforms/chromagram.xml (rev 0) +++ runner/trunk/transforms/chromagram.xml 2007-12-10 16:42:27 UTC (rev 898) @@ -0,0 +1,7 @@ +<transform id="vamp:qm-vamp-plugins:qm-chromagram" program="" stepSize="4096" blockSize="32768" windowType="hanning" startTime="0.000000000" duration="0.000000000" sampleRate="22050" > + <parameter name="bpo" value="12"/> + <parameter name="maxpitch" value="96"/> + <parameter name="minpitch" value="12"/> + <parameter name="normalized" value="1"/> + <parameter name="tuning" value="440"/> +</transform> \ No newline at end of file Added: runner/trunk/transforms/percussiononsets.xml =================================================================== --- runner/trunk/transforms/percussiononsets.xml (rev 0) +++ runner/trunk/transforms/percussiononsets.xml 2007-12-10 16:42:27 UTC (rev 898) @@ -0,0 +1,4 @@ +<transform id="vamp:vamp-example-plugins:percussiononsets" program="" stepSize="512" blockSize="1024" windowType="hanning" startTime="0.000000000" duration="0.000000000" sampleRate="22050" > + <parameter name="sensitivity" value="40"/> + <parameter name="threshold" value="3"/> +</transform> \ No newline at end of file Added: runner/trunk/transforms/spectralcentroid.xml =================================================================== --- runner/trunk/transforms/spectralcentroid.xml (rev 0) +++ runner/trunk/transforms/spectralcentroid.xml 2007-12-10 16:42:27 UTC (rev 898) @@ -0,0 +1 @@ +<transform id="vamp:vamp-example-plugins:spectralcentroid" program="" stepSize="512" blockSize="1024" windowType="hanning" startTime="0.000000000" duration="0.000000000" sampleRate="22050" /> \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ca...@us...> - 2007-12-10 16:56:39
|
Revision: 899 http://sv1.svn.sourceforge.net/sv1/?rev=899&view=rev Author: cannam Date: 2007-12-10 08:56:36 -0800 (Mon, 10 Dec 2007) Log Message: ----------- * Make the code compile Modified Paths: -------------- runner/trunk/AudioDBFeatureWriter.h runner/trunk/DefaultFeatureWriter.h runner/trunk/FeatureExtractionManager.h runner/trunk/FeatureWriter.h runner/trunk/SimpleRDFFeatureWriter.cpp runner/trunk/SimpleRDFFeatureWriter.h runner/trunk/runner.pro Modified: runner/trunk/AudioDBFeatureWriter.h =================================================================== --- runner/trunk/AudioDBFeatureWriter.h 2007-12-10 16:42:27 UTC (rev 898) +++ runner/trunk/AudioDBFeatureWriter.h 2007-12-10 16:56:36 UTC (rev 899) @@ -36,4 +36,4 @@ bool openDBFile(const string& identifier); }; -#endif \ No newline at end of file +#endif Modified: runner/trunk/DefaultFeatureWriter.h =================================================================== --- runner/trunk/DefaultFeatureWriter.h 2007-12-10 16:42:27 UTC (rev 898) +++ runner/trunk/DefaultFeatureWriter.h 2007-12-10 16:56:36 UTC (rev 899) @@ -20,4 +20,4 @@ virtual void write(const string& trackid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); }; -#endif \ No newline at end of file +#endif Modified: runner/trunk/FeatureExtractionManager.h =================================================================== --- runner/trunk/FeatureExtractionManager.h 2007-12-10 16:42:27 UTC (rev 898) +++ runner/trunk/FeatureExtractionManager.h 2007-12-10 16:56:36 UTC (rev 899) @@ -16,7 +16,7 @@ using std::vector; using std::string; -#include <vamp-sdk/plugin.h> +#include <vamp-sdk/Plugin.h> #include <plugin/transform/Transform.h> class FeatureWriter; @@ -28,7 +28,7 @@ virtual ~FeatureExtractionManager(); void setChannels(int channels); void setSampleRate(int sampleRate); - bool FeatureExtractionManager::addFeatureExtractor(string transformXmlFile, vector<FeatureWriter*> writers); + bool addFeatureExtractor(string transformXmlFile, vector<FeatureWriter*> writers); bool addFeatureExtractor(string library, string plugname, vector<FeatureWriter*> writers); void extractFeatures(string audioSource); private: @@ -41,4 +41,4 @@ void print(Transform transform) const; }; -#endif \ No newline at end of file +#endif Modified: runner/trunk/FeatureWriter.h =================================================================== --- runner/trunk/FeatureWriter.h 2007-12-10 16:42:27 UTC (rev 898) +++ runner/trunk/FeatureWriter.h 2007-12-10 16:56:36 UTC (rev 899) @@ -23,4 +23,4 @@ virtual void write(const string& trackid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) = 0; }; -#endif \ No newline at end of file +#endif Modified: runner/trunk/SimpleRDFFeatureWriter.cpp =================================================================== --- runner/trunk/SimpleRDFFeatureWriter.cpp 2007-12-10 16:42:27 UTC (rev 898) +++ runner/trunk/SimpleRDFFeatureWriter.cpp 2007-12-10 16:56:36 UTC (rev 899) @@ -148,4 +148,4 @@ fe_count++; } } -} \ No newline at end of file +} Modified: runner/trunk/SimpleRDFFeatureWriter.h =================================================================== --- runner/trunk/SimpleRDFFeatureWriter.h 2007-12-10 16:42:27 UTC (rev 898) +++ runner/trunk/SimpleRDFFeatureWriter.h 2007-12-10 16:56:36 UTC (rev 899) @@ -21,4 +21,4 @@ virtual void write(const string& trackid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); }; -#endif \ No newline at end of file +#endif Modified: runner/trunk/runner.pro =================================================================== --- runner/trunk/runner.pro 2007-12-10 16:42:27 UTC (rev 898) +++ runner/trunk/runner.pro 2007-12-10 16:56:36 UTC (rev 899) @@ -1,7 +1,7 @@ TEMPLATE = app -SV_UNIT_PACKAGES = vamp vamp-hostsdk samplerate mad id3tag oggz fishsound sndfile +SV_UNIT_PACKAGES = vamp vamp-hostsdk samplerate mad id3tag oggz fishsound sndfile lrdf load(../sonic-visualiser/sv.prf) CONFIG += sv qt thread warn_on stl rtti exceptions This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <je...@us...> - 2007-12-13 17:32:41
|
Revision: 910 http://sv1.svn.sourceforge.net/sv1/?rev=910&view=rev Author: jerrell Date: 2007-12-13 09:32:36 -0800 (Thu, 13 Dec 2007) Log Message: ----------- Got RDFFeatureWriter doing approximately what it should Modified Paths: -------------- runner/trunk/AudioDBFeatureWriter.cpp runner/trunk/AudioDBFeatureWriter.h runner/trunk/DefaultFeatureWriter.cpp runner/trunk/DefaultFeatureWriter.h runner/trunk/FeatureExtractionManager.cpp runner/trunk/FeatureWriter.h runner/trunk/SimpleRDFFeatureWriter.cpp runner/trunk/SimpleRDFFeatureWriter.h runner/trunk/main.cpp runner/trunk/runner.pro Added Paths: ----------- runner/trunk/RDFFeatureWriter.cpp runner/trunk/RDFFeatureWriter.h runner/trunk/RDFSingleFeatureWriter.cpp runner/trunk/RDFSingleFeatureWriter.h Modified: runner/trunk/AudioDBFeatureWriter.cpp =================================================================== --- runner/trunk/AudioDBFeatureWriter.cpp 2007-12-13 17:14:33 UTC (rev 909) +++ runner/trunk/AudioDBFeatureWriter.cpp 2007-12-13 17:32:36 UTC (rev 910) @@ -37,7 +37,7 @@ // TODO: error handling on close } -void AudioDBFeatureWriter::write(const string& trackid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) +void AudioDBFeatureWriter::write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) { // binary output for FeatureSet Modified: runner/trunk/AudioDBFeatureWriter.h =================================================================== --- runner/trunk/AudioDBFeatureWriter.h 2007-12-13 17:14:33 UTC (rev 909) +++ runner/trunk/AudioDBFeatureWriter.h 2007-12-13 17:32:36 UTC (rev 910) @@ -23,7 +23,7 @@ public: AudioDBFeatureWriter(const string& catId, const string& dir); virtual ~AudioDBFeatureWriter(); - virtual void write(const string& trackid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); + virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); private: string catalogueId; Modified: runner/trunk/DefaultFeatureWriter.cpp =================================================================== --- runner/trunk/DefaultFeatureWriter.cpp 2007-12-13 17:14:33 UTC (rev 909) +++ runner/trunk/DefaultFeatureWriter.cpp 2007-12-13 17:32:36 UTC (rev 910) @@ -14,7 +14,7 @@ #include "DefaultFeatureWriter.h" -void DefaultFeatureWriter::write(const string& trackid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) +void DefaultFeatureWriter::write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) { // generic XML output for FeatureSet Modified: runner/trunk/DefaultFeatureWriter.h =================================================================== --- runner/trunk/DefaultFeatureWriter.h 2007-12-13 17:14:33 UTC (rev 909) +++ runner/trunk/DefaultFeatureWriter.h 2007-12-13 17:32:36 UTC (rev 910) @@ -17,7 +17,7 @@ { public: virtual ~DefaultFeatureWriter() { } - virtual void write(const string& trackid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); + virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); }; #endif Modified: runner/trunk/FeatureExtractionManager.cpp =================================================================== --- runner/trunk/FeatureExtractionManager.cpp 2007-12-13 17:14:33 UTC (rev 909) +++ runner/trunk/FeatureExtractionManager.cpp 2007-12-13 17:32:36 UTC (rev 910) @@ -219,7 +219,7 @@ { Vamp::Plugin::FeatureSet featureSet = plugins[k]->process(data, timestamp); for (int j = 0; j < pluginWriters[k].size(); ++j) - pluginWriters[k][j]->write("track01", plugins[k]->getOutputDescriptors(), featureSet); + pluginWriters[k][j]->write("track01", plugins[k]->getIdentifier(), plugins[k]->getOutputDescriptors(), featureSet); } } @@ -238,7 +238,7 @@ // or even rename files according to some convention for (int j = 0; j < pluginWriters[k].size(); ++j) - pluginWriters[k][j]->write("track01", plugins[k]->getOutputDescriptors(), plugins[k]->getRemainingFeatures()); + pluginWriters[k][j]->write("track01", plugins[k]->getIdentifier(), plugins[k]->getOutputDescriptors(), plugins[k]->getRemainingFeatures()); } TempDirectory::getInstance()->cleanup(); Modified: runner/trunk/FeatureWriter.h =================================================================== --- runner/trunk/FeatureWriter.h 2007-12-13 17:14:33 UTC (rev 909) +++ runner/trunk/FeatureWriter.h 2007-12-13 17:32:36 UTC (rev 910) @@ -20,7 +20,7 @@ { public: virtual ~FeatureWriter() { } - virtual void write(const string& trackid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) = 0; + virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) = 0; }; #endif Added: runner/trunk/RDFFeatureWriter.cpp =================================================================== --- runner/trunk/RDFFeatureWriter.cpp (rev 0) +++ runner/trunk/RDFFeatureWriter.cpp 2007-12-13 17:32:36 UTC (rev 910) @@ -0,0 +1,79 @@ +/* + * RDFFeatureWriter.cpp + * runner + * + * Created by Chris Sutton 13/12/2007. + * Copyright 2007 Queen Mary, Univesity of London. All rights reserved. + * + */ + +#include <fstream> + +using namespace std; + +#include "RDFFeatureWriter.h" + +RDFFeatureWriter::RDFFeatureWriter(const string& catId, const string& dir) : +catalogueId(catId), baseDir(dir) +{ + +} + +RDFFeatureWriter::~RDFFeatureWriter() +{ + // close all open files + for (map<string, RDFSingleFeatureWriter*>::iterator iter = featureWriters.begin(); iter != featureWriters.end(); ++iter) + { + delete iter->second; + } +} + +void RDFFeatureWriter::write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) +{ + + + // iterate through FeatureLists + for (map<int, Vamp::Plugin::FeatureList>::const_iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) + { + Vamp::Plugin::FeatureList featureList = iter->second; + Vamp::Plugin::OutputDescriptor output = outputList[iter->first]; + + for (unsigned int i = 0; i < featureList.size(); ++i) + { + // replace output files if necessary + replaceFeatureWriter(trackid, pluginid); + featureWriters[pluginid]->write(trackid, pluginid, outputList, featureSet); + } + } +} + +bool RDFFeatureWriter::newFeatureWriter(const string& trackid, const string& identifier) +{ +// string filepath = baseDir + "/" + catalogueId + "/" + trackid + "." + identifier + ".rdf"; + string filepath = trackid +"."+ identifier +".rdf"; + featureWriters[identifier] = new RDFSingleFeatureWriter(trackid, filepath); + if (!(featureWriters[identifier]->out)) + return false; + return true; +} + +// replace writer if no writer open for this track&feature, else return false +bool RDFFeatureWriter::replaceFeatureWriter(const string& trackid, const string& identifier) +{ + if (featureWriters.find(identifier) != featureWriters.end()) + { + if (featureWriters[identifier]->trackid == trackid) + return false; // have a feature writer for this track & feature + else // track has changed + { + cerr<<"found feature writer with old track"<<endl; + cerr<<"new : "<<trackid<<", old : "<<featureWriters[identifier]->trackid<<endl; + delete featureWriters[identifier]; + } + } + cerr<<"allocating new feature writer"<<endl; + newFeatureWriter(trackid, identifier); + return true; +} + + \ No newline at end of file Added: runner/trunk/RDFFeatureWriter.h =================================================================== --- runner/trunk/RDFFeatureWriter.h (rev 0) +++ runner/trunk/RDFFeatureWriter.h 2007-12-13 17:32:36 UTC (rev 910) @@ -0,0 +1,39 @@ +/* + * RDFFeatureWriter.h + * runner + * + * Created by Chris Sutton on 13/12/2007. + * Copyright 2007 Queen Mary, University of London. All rights reserved. + * + */ + +#ifndef _RDF_FEATURE_WRITER_H_ +#define _RDF_FEATURE_WRITER_H_ + +#include <string> +#include <map> + +using std::string; +using std::map; + +#include "FeatureWriter.h" +#include "RDFSingleFeatureWriter.h" + +class RDFFeatureWriter : public FeatureWriter +{ +public: + RDFFeatureWriter(const string& catId, const string& dir); + virtual ~RDFFeatureWriter(); + virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); + +private: + string catalogueId; + string baseDir; + + map<string, RDFSingleFeatureWriter*> featureWriters; + + bool newFeatureWriter(const string& trackid, const string& identifier); + bool replaceFeatureWriter(const string& trackid, const string& identifier); +}; + +#endif Added: runner/trunk/RDFSingleFeatureWriter.cpp =================================================================== --- runner/trunk/RDFSingleFeatureWriter.cpp (rev 0) +++ runner/trunk/RDFSingleFeatureWriter.cpp 2007-12-13 17:32:36 UTC (rev 910) @@ -0,0 +1,157 @@ +/* + * RDFSingleFeatureWriter.cpp + * vamphost + * + * Created by Chris Sutton on 13/12/2007. + * Copyright 2007 Queen Mary, University of London. All rights reserved. + * + */ + +#include <iostream> +#include <fstream> +#include <map> +using namespace std; + +#include "RDFSingleFeatureWriter.h" +using Vamp::Plugin; + +string timelineURI = ":tl"; //FIXME ? + +RDFSingleFeatureWriter::RDFSingleFeatureWriter(const string& tid, const string& outfilename) : trackid(tid), am_initialised(false), fe_count(0) +{ + out = new ofstream(outfilename.c_str()); + if (!*out) + { + cerr << "ERROR RDFSingleFeatureWriter(): can't open file " << outfilename << endl; +// out = cout; // ‽ + } +} + +void RDFSingleFeatureWriter::init(const string& trackid, const Plugin::OutputList& outputList) +{ + cerr << "RDFSingleFeatureWriter init()"<<endl; + + // FIXME namespaces : + *out << "@prefix dc: <http://purl.org/dc/elements/1.1/> .\n" + << "@prefix mo: <http://purl.org/ontology/mo/> .\n" + << "@prefix af: <http://purl.org/ontology/af/>.\n" + << "@prefix event: <http://purl.org/NET/c4dm/event.owl#>.\n" + << "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.\n" + << "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.\n" + << "@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.\n" + << "@prefix timeline: <http://purl.org/NET/c4dm/timeline.owl#>.\n" + << "@prefix time: <http://www.w3.org/2006/time#>.\n" + << "@prefix : <>.\n\n" + << endl; + + /* + * Describe signal we're analysing (AudioFile, Signal, TimeLine, etc.) + */ + *out << "<"<<trackid<<"> a mo:AudioFile .\n\n" + << ":signal a mo:Signal ;\n" + << " mo:available_as <"<<trackid<<"> ;\n" + << " mo:time :sig_int .\n" + << ":sig_int a time:Interval ;\n" + << " timeline:onTimeLine :tl.\n"; + + /* + * Describe feature events and features. + */ + // TODO : The URIs should be specified in a doc accompanying the Vamp plugin. + // For now, we'll make up local names based on plugin identifier + for (int i=0; i < outputList.size(); i++) + { + Plugin::OutputDescriptor od = outputList[i]; + *out << ":fetype_" << od.identifier << " rdfs:subClassOf af:FeatureEvent;\n" + << " dc:title \"" << od.name << "\"; \n" + << " dc:description \"" << od.description << " event\".\n" + << endl; + + *out << ":ftype_" << od.identifier << " rdfs:subClassOf af:Feature;\n" + << " dc:title \"" << od.name << "\"; \n" + << " dc:description \"" << od.description << "\";\n" + << " dc:format \"" << od.unit << "\".\n\n" + << endl; + } + am_initialised = true; +} + +void RDFSingleFeatureWriter::write(const string& trackid, const string& pluginid, const Plugin::OutputList& outputList, const Plugin::FeatureSet& featureSet) +{ + if (!am_initialised) + init(trackid, outputList); + + if (featureSet.size() == 0) + return; + + // iterate through FeatureLists + //cerr << featureSet.size() << " featurelists in set" << endl; + for (map<int, Plugin::FeatureList>::const_iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) + { + Plugin::FeatureList featureList = iter->second; + Plugin::OutputDescriptor od = outputList[iter->first]; + for (unsigned int i = 0; i < featureList.size(); ++i) + { + Plugin::Feature feature = featureList[i]; + *out << ":fe_" << fe_count << " rdf:type :fetype_" << od.identifier << ";\n"; + + /* + * Add timestamp + * In current design this is handled by the rebuffering, s.t. all outputs are VariableSampleRate and have a valid timestamp. + */ + if (od.sampleType == Plugin::OutputDescriptor::VariableSampleRate) + { + *out<< " event:time [ rdf:type time:Instant;\n" //location of the event in time + << " time:onTimeLine " << timelineURI << ";\n" + << " time:atDuration \"PT" << feature.timestamp.toString() << "S\"^^xsd:duration;];\n"; + } + else if (od.sampleType == Plugin::OutputDescriptor::OneSamplePerStep) + { + /* + *out<< " event:time [ rdf:type time:Instant;\n" //location of the event in time + << " time:onTimeLine " << timelineURI << ";\n" + << " time:atDuration \"PT" << timestamp.toString() << "S\"^^xsd:duration;];\n"; + */ + cerr<<"Arg, got a OneSamplePerStep plugin but no timestamp, not sure what to do"<<endl; + } + else if (od.sampleType == Plugin::OutputDescriptor::FixedSampleRate) + { + cerr<<"Arg, got a FixedSampleRate plugin, not sure what to do"<<endl; +/* +16:48 < cannam> FixedSampleRate -> somewhat open to interpretation, but I'd say that the return from the first process call would be timestamped with the stamp passed in to the process call +16:48 < cannam> and subsequent ones would increment by 1 / (the sample rate specified in the output descriptor) +16:49 < cannam> I'm not 100% sure, but I think that no actual plugin uses FixedSampleRate at the moment +*/ + } + *out << " af:hasFeature :f_"<<fe_count<<"."<<endl; + + /* + * Add Feature resource + */ + + *out << ":f_"<<fe_count<<" rdf:type :ftype_"<<od.identifier<<""; + if (feature.label.length() > 0) + *out<< ";\n rdfs:label \"" << feature.label << "\""; + + if (feature.values.size() > 0) + { + *out<<";\n"; + + // TODO : If the plugin names its bins we should do one triple per value + // hopefully we have type URIs for the bins from the plugin's RDF file + + + // If the plugin doesn't name its bins there's probably no point separating them, + // so we'll do a CSV literal : + *out << " af:value \""<< feature.values[0]; + for (unsigned int j = 1; j < feature.values.size(); ++j) + *out << "," << feature.values[j]; + *out << "\"." << endl; + } + else + *out<< ".\n"; + + fe_count++; + } + } +} Added: runner/trunk/RDFSingleFeatureWriter.h =================================================================== --- runner/trunk/RDFSingleFeatureWriter.h (rev 0) +++ runner/trunk/RDFSingleFeatureWriter.h 2007-12-13 17:32:36 UTC (rev 910) @@ -0,0 +1,30 @@ +/* + * RDFSingleFeatureWriter.h + * vamphost + * + * Created by Chris Sutton on 13/12/2007. + * Copyright 2007 Queen Mary, University of London. All rights reserved. + * + */ + +#ifndef _RDF_SINGLE_FEATURE_WRITER_H_ +#define _RDF_SINGLE_FEATURE_WRITER_H_ + +#include <fstream> +using std::ostream; +#include "FeatureWriter.h" + +class RDFSingleFeatureWriter : public FeatureWriter +{ +public: + RDFSingleFeatureWriter(const string& trackid, const string& outfilename); + virtual ~RDFSingleFeatureWriter() { } + virtual void init(const string& trackid, const Vamp::Plugin::OutputList& outputList); + virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); + bool am_initialised; + int fe_count; + string trackid; + ostream* out; +}; + +#endif Modified: runner/trunk/SimpleRDFFeatureWriter.cpp =================================================================== --- runner/trunk/SimpleRDFFeatureWriter.cpp 2007-12-13 17:14:33 UTC (rev 909) +++ runner/trunk/SimpleRDFFeatureWriter.cpp 2007-12-13 17:32:36 UTC (rev 910) @@ -70,7 +70,7 @@ am_initialised = true; } -void SimpleRDFFeatureWriter::write(const string& trackid, const Plugin::OutputList& outputList, const Plugin::FeatureSet& featureSet) +void SimpleRDFFeatureWriter::write(const string& trackid, const string& pluginid, const Plugin::OutputList& outputList, const Plugin::FeatureSet& featureSet) { if (!am_initialised) init(trackid, outputList); Modified: runner/trunk/SimpleRDFFeatureWriter.h =================================================================== --- runner/trunk/SimpleRDFFeatureWriter.h 2007-12-13 17:14:33 UTC (rev 909) +++ runner/trunk/SimpleRDFFeatureWriter.h 2007-12-13 17:32:36 UTC (rev 910) @@ -18,7 +18,7 @@ public: virtual ~SimpleRDFFeatureWriter() { } virtual void init(const string& trackid, const Vamp::Plugin::OutputList& outputList); - virtual void write(const string& trackid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); + virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); }; #endif Modified: runner/trunk/main.cpp =================================================================== --- runner/trunk/main.cpp 2007-12-13 17:14:33 UTC (rev 909) +++ runner/trunk/main.cpp 2007-12-13 17:32:36 UTC (rev 910) @@ -15,7 +15,7 @@ #include "FeatureExtractionManager.h" #include "DefaultFeatureWriter.h" -#include "SimpleRDFFeatureWriter.h" +#include "RDFFeatureWriter.h" #include "AudioDBFeatureWriter.h" int main(int argc, char **argv) @@ -35,7 +35,7 @@ if (argc > 1) writerType = argv[1]; if (writerType == "rdf") - writers.push_back(new SimpleRDFFeatureWriter()); + writers.push_back(new RDFFeatureWriter(".", "."));// For now, dump RDF adjacent to audio if (writerType == "adb") writers.push_back(new AudioDBFeatureWriter("catalog01", "audiodb")); @@ -53,9 +53,9 @@ // we may want to work from saved transforms here if we // already know what features we want // - this is the audioDB scenario - manager.addFeatureExtractor("/users/mark/documents/src/runner/transforms/percussiononsets.xml", writers); - manager.addFeatureExtractor("/users/mark/documents/src/runner/transforms/chromagram.xml", writers); - manager.addFeatureExtractor("/users/mark/documents/src/runner/transforms/spectralcentroid.xml", writers); + manager.addFeatureExtractor("transforms/percussiononsets.xml", writers); + manager.addFeatureExtractor("transforms/chromagram.xml", writers); + manager.addFeatureExtractor("transforms/spectralcentroid.xml", writers); // note that the default writer dumps everything to cerr // but real writers can write to feature-specific and/or track-specific files @@ -85,7 +85,7 @@ // } // } - //string trackUri = "file:///Downloads/Toni%20Basil%20-%20Mickey.mp3"; + //string trackUri = "./test.mp3"; //string trackUri = "http://dsp-cluster/music/yvesr/2%20MANY%20DJs/Soulwax%20Radio%20Session%20Part%201%20CD%202/00.%20As%20Heard%20On%20Radio%20Soulwax%20pt.%203.mp3"; string trackUri = "/users/mark/documents/tags/audio/999.mp3"; if (argc > 2) Modified: runner/trunk/runner.pro =================================================================== --- runner/trunk/runner.pro 2007-12-13 17:14:33 UTC (rev 909) +++ runner/trunk/runner.pro 2007-12-13 17:32:36 UTC (rev 910) @@ -28,7 +28,7 @@ # Input HEADERS += -SOURCES += main.cpp DefaultFeatureWriter.cpp SimpleRDFFeatureWriter.cpp FeatureExtractionManager.cpp AudioDBFeatureWriter.cpp +SOURCES += main.cpp DefaultFeatureWriter.cpp RDFFeatureWriter.cpp RDFSingleFeatureWriter.cpp FeatureExtractionManager.cpp AudioDBFeatureWriter.cpp This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <je...@us...> - 2008-01-02 13:03:00
|
Revision: 915 http://sv1.svn.sourceforge.net/sv1/?rev=915&view=rev Author: jerrell Date: 2008-01-02 05:02:55 -0800 (Wed, 02 Jan 2008) Log Message: ----------- Made runner use RDF descriptions of plugins Modified Paths: -------------- runner/trunk/RDFFeatureWriter.cpp runner/trunk/RDFFeatureWriter.h runner/trunk/runner.pro Added Paths: ----------- runner/trunk/RDFSinglePluginWriter.cpp runner/trunk/RDFSinglePluginWriter.h Removed Paths: ------------- runner/trunk/RDFSingleFeatureWriter.cpp runner/trunk/RDFSingleFeatureWriter.h Modified: runner/trunk/RDFFeatureWriter.cpp =================================================================== --- runner/trunk/RDFFeatureWriter.cpp 2007-12-18 10:35:55 UTC (rev 914) +++ runner/trunk/RDFFeatureWriter.cpp 2008-01-02 13:02:55 UTC (rev 915) @@ -11,6 +11,12 @@ using namespace std; +#include "vamp-sdk/PluginHostAdapter.h" +#include "vamp-sdk/hostext/PluginLoader.h" + +using Vamp::HostExt::PluginLoader; +using Vamp::PluginHostAdapter; + #include "RDFFeatureWriter.h" RDFFeatureWriter::RDFFeatureWriter(const string& catId, const string& dir) : @@ -22,7 +28,7 @@ RDFFeatureWriter::~RDFFeatureWriter() { // close all open files - for (map<string, RDFSingleFeatureWriter*>::iterator iter = featureWriters.begin(); iter != featureWriters.end(); ++iter) + for (map<string, RDFSinglePluginWriter*>::iterator iter = featureWriters.begin(); iter != featureWriters.end(); ++iter) { delete iter->second; } @@ -49,31 +55,83 @@ bool RDFFeatureWriter::newFeatureWriter(const string& trackid, const string& identifier) { -// string filepath = baseDir + "/" + catalogueId + "/" + trackid + "." + identifier + ".rdf"; - string filepath = trackid +"."+ identifier +".rdf"; - featureWriters[identifier] = new RDFSingleFeatureWriter(trackid, filepath); + string filepath = baseDir + "/" + catalogueId + "/" + trackid + "." + identifier + ".rdf"; + featureWriters[identifier] = new RDFSinglePluginWriter(trackid, filepath); if (!(featureWriters[identifier]->out)) return false; return true; } -// replace writer if no writer open for this track&feature, else return false -bool RDFFeatureWriter::replaceFeatureWriter(const string& trackid, const string& identifier) +// replace writer if no writer open for this track&plugin, else return false +bool RDFFeatureWriter::replaceFeatureWriter(const string& trackid, const string& pluginid) { - if (featureWriters.find(identifier) != featureWriters.end()) + if (featureWriters.find(pluginid) != featureWriters.end()) { - if (featureWriters[identifier]->trackid == trackid) - return false; // have a feature writer for this track & feature + if (featureWriters[pluginid]->trackid == trackid) + return false; // have a feature writer for this track & plugin else // track has changed { cerr<<"found feature writer with old track"<<endl; - cerr<<"new : "<<trackid<<", old : "<<featureWriters[identifier]->trackid<<endl; - delete featureWriters[identifier]; + cerr<<"new : "<<trackid<<", old : "<<featureWriters[pluginid]->trackid<<endl; + delete featureWriters[pluginid]; } } - cerr<<"allocating new feature writer"<<endl; - newFeatureWriter(trackid, identifier); + cerr<<"allocating new RDFSinglePluginWriter"<<endl; + newFeatureWriter(trackid, pluginid); return true; } + +string RDFFeatureWriter::getDescriptionFileForPlugin(const string& pluginid) +{ + string path = ""; + vector<string> paths = PluginHostAdapter::getPluginPath(); + + vector<string> rdf_exts; + rdf_exts.push_back("rdf"); rdf_exts.push_back("RDF"); + rdf_exts.push_back("n3"); rdf_exts.push_back("N3"); + + PluginLoader *loader = PluginLoader::getInstance(); + vector<string> keys = loader->listPlugins(); + string libname = ""; + for (vector<string>::iterator kitr = keys.begin(); kitr != keys.end(); kitr++) + { + string::size_type ci = (*kitr).find(':'); + if (ci != string::npos && (*kitr).substr(ci + 1) == pluginid) + { + libname = (*kitr).substr(0,ci); + cerr<<"Found library name for plugin : "<<libname<<endl; + } + } + if (libname == "") + cerr<<"Couldn't find library name for plugin "<<pluginid<<" !"<<endl; - \ No newline at end of file + // Search each Vamp plugin path for a .rdf file matching the plugin identifier + // (possibly in a library-named directory) + + for (vector<string>::const_iterator pitr = paths.begin(); pitr != paths.end(); pitr++) + { + for (vector<string>::const_iterator eitr = rdf_exts.begin(); eitr != rdf_exts.end(); eitr++) + { + path = *pitr + "/" + pluginid + "." + *eitr; + cerr<<"Looking for "<<path<<endl; + // Check for file + if (fileExists(path)) + return path; + + path = *pitr + "/" + libname + "/" + pluginid + "." + *eitr; // is dir delimiter "/" portable ? + cerr<<"Looking for "<<path<<endl; + // Check for file + if (fileExists(path)) + return path; + } + } + + cerr<<"Couldn't find description of plugin !"<<endl; + return ""; +} + +bool fileExists(string filepath) +{ + std::ifstream fin(filepath.c_str()); + return (fin != NULL); +} Modified: runner/trunk/RDFFeatureWriter.h =================================================================== --- runner/trunk/RDFFeatureWriter.h 2007-12-18 10:35:55 UTC (rev 914) +++ runner/trunk/RDFFeatureWriter.h 2008-01-02 13:02:55 UTC (rev 915) @@ -17,7 +17,7 @@ using std::map; #include "FeatureWriter.h" -#include "RDFSingleFeatureWriter.h" +#include "RDFSinglePluginWriter.h" class RDFFeatureWriter : public FeatureWriter { @@ -25,15 +25,18 @@ RDFFeatureWriter(const string& catId, const string& dir); virtual ~RDFFeatureWriter(); virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); + static string getDescriptionFileForPlugin(const string& pluginid); private: string catalogueId; string baseDir; - map<string, RDFSingleFeatureWriter*> featureWriters; + map<string, RDFSinglePluginWriter*> featureWriters; bool newFeatureWriter(const string& trackid, const string& identifier); bool replaceFeatureWriter(const string& trackid, const string& identifier); }; +bool fileExists(string filepath); + #endif Deleted: runner/trunk/RDFSingleFeatureWriter.cpp =================================================================== --- runner/trunk/RDFSingleFeatureWriter.cpp 2007-12-18 10:35:55 UTC (rev 914) +++ runner/trunk/RDFSingleFeatureWriter.cpp 2008-01-02 13:02:55 UTC (rev 915) @@ -1,157 +0,0 @@ -/* - * RDFSingleFeatureWriter.cpp - * vamphost - * - * Created by Chris Sutton on 13/12/2007. - * Copyright 2007 Queen Mary, University of London. All rights reserved. - * - */ - -#include <iostream> -#include <fstream> -#include <map> -using namespace std; - -#include "RDFSingleFeatureWriter.h" -using Vamp::Plugin; - -string timelineURI = ":tl"; //FIXME ? - -RDFSingleFeatureWriter::RDFSingleFeatureWriter(const string& tid, const string& outfilename) : trackid(tid), am_initialised(false), fe_count(0) -{ - out = new ofstream(outfilename.c_str()); - if (!*out) - { - cerr << "ERROR RDFSingleFeatureWriter(): can't open file " << outfilename << endl; -// out = cout; // ‽ - } -} - -void RDFSingleFeatureWriter::init(const string& trackid, const Plugin::OutputList& outputList) -{ - cerr << "RDFSingleFeatureWriter init()"<<endl; - - // FIXME namespaces : - *out << "@prefix dc: <http://purl.org/dc/elements/1.1/> .\n" - << "@prefix mo: <http://purl.org/ontology/mo/> .\n" - << "@prefix af: <http://purl.org/ontology/af/>.\n" - << "@prefix event: <http://purl.org/NET/c4dm/event.owl#>.\n" - << "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.\n" - << "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.\n" - << "@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.\n" - << "@prefix timeline: <http://purl.org/NET/c4dm/timeline.owl#>.\n" - << "@prefix time: <http://www.w3.org/2006/time#>.\n" - << "@prefix : <>.\n\n" - << endl; - - /* - * Describe signal we're analysing (AudioFile, Signal, TimeLine, etc.) - */ - *out << "<"<<trackid<<"> a mo:AudioFile .\n\n" - << ":signal a mo:Signal ;\n" - << " mo:available_as <"<<trackid<<"> ;\n" - << " mo:time :sig_int .\n" - << ":sig_int a time:Interval ;\n" - << " timeline:onTimeLine :tl.\n"; - - /* - * Describe feature events and features. - */ - // TODO : The URIs should be specified in a doc accompanying the Vamp plugin. - // For now, we'll make up local names based on plugin identifier - for (int i=0; i < outputList.size(); i++) - { - Plugin::OutputDescriptor od = outputList[i]; - *out << ":fetype_" << od.identifier << " rdfs:subClassOf af:FeatureEvent;\n" - << " dc:title \"" << od.name << "\"; \n" - << " dc:description \"" << od.description << " event\".\n" - << endl; - - *out << ":ftype_" << od.identifier << " rdfs:subClassOf af:Feature;\n" - << " dc:title \"" << od.name << "\"; \n" - << " dc:description \"" << od.description << "\";\n" - << " dc:format \"" << od.unit << "\".\n\n" - << endl; - } - am_initialised = true; -} - -void RDFSingleFeatureWriter::write(const string& trackid, const string& pluginid, const Plugin::OutputList& outputList, const Plugin::FeatureSet& featureSet) -{ - if (!am_initialised) - init(trackid, outputList); - - if (featureSet.size() == 0) - return; - - // iterate through FeatureLists - //cerr << featureSet.size() << " featurelists in set" << endl; - for (map<int, Plugin::FeatureList>::const_iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) - { - Plugin::FeatureList featureList = iter->second; - Plugin::OutputDescriptor od = outputList[iter->first]; - for (unsigned int i = 0; i < featureList.size(); ++i) - { - Plugin::Feature feature = featureList[i]; - *out << ":fe_" << fe_count << " rdf:type :fetype_" << od.identifier << ";\n"; - - /* - * Add timestamp - * In current design this is handled by the rebuffering, s.t. all outputs are VariableSampleRate and have a valid timestamp. - */ - if (od.sampleType == Plugin::OutputDescriptor::VariableSampleRate) - { - *out<< " event:time [ rdf:type time:Instant;\n" //location of the event in time - << " time:onTimeLine " << timelineURI << ";\n" - << " time:atDuration \"PT" << feature.timestamp.toString() << "S\"^^xsd:duration;];\n"; - } - else if (od.sampleType == Plugin::OutputDescriptor::OneSamplePerStep) - { - /* - *out<< " event:time [ rdf:type time:Instant;\n" //location of the event in time - << " time:onTimeLine " << timelineURI << ";\n" - << " time:atDuration \"PT" << timestamp.toString() << "S\"^^xsd:duration;];\n"; - */ - cerr<<"Arg, got a OneSamplePerStep plugin but no timestamp, not sure what to do"<<endl; - } - else if (od.sampleType == Plugin::OutputDescriptor::FixedSampleRate) - { - cerr<<"Arg, got a FixedSampleRate plugin, not sure what to do"<<endl; -/* -16:48 < cannam> FixedSampleRate -> somewhat open to interpretation, but I'd say that the return from the first process call would be timestamped with the stamp passed in to the process call -16:48 < cannam> and subsequent ones would increment by 1 / (the sample rate specified in the output descriptor) -16:49 < cannam> I'm not 100% sure, but I think that no actual plugin uses FixedSampleRate at the moment -*/ - } - *out << " af:hasFeature :f_"<<fe_count<<"."<<endl; - - /* - * Add Feature resource - */ - - *out << ":f_"<<fe_count<<" rdf:type :ftype_"<<od.identifier<<""; - if (feature.label.length() > 0) - *out<< ";\n rdfs:label \"" << feature.label << "\""; - - if (feature.values.size() > 0) - { - *out<<";\n"; - - // TODO : If the plugin names its bins we should do one triple per value - // hopefully we have type URIs for the bins from the plugin's RDF file - - - // If the plugin doesn't name its bins there's probably no point separating them, - // so we'll do a CSV literal : - *out << " af:value \""<< feature.values[0]; - for (unsigned int j = 1; j < feature.values.size(); ++j) - *out << "," << feature.values[j]; - *out << "\"." << endl; - } - else - *out<< ".\n"; - - fe_count++; - } - } -} Deleted: runner/trunk/RDFSingleFeatureWriter.h =================================================================== --- runner/trunk/RDFSingleFeatureWriter.h 2007-12-18 10:35:55 UTC (rev 914) +++ runner/trunk/RDFSingleFeatureWriter.h 2008-01-02 13:02:55 UTC (rev 915) @@ -1,30 +0,0 @@ -/* - * RDFSingleFeatureWriter.h - * vamphost - * - * Created by Chris Sutton on 13/12/2007. - * Copyright 2007 Queen Mary, University of London. All rights reserved. - * - */ - -#ifndef _RDF_SINGLE_FEATURE_WRITER_H_ -#define _RDF_SINGLE_FEATURE_WRITER_H_ - -#include <fstream> -using std::ostream; -#include "FeatureWriter.h" - -class RDFSingleFeatureWriter : public FeatureWriter -{ -public: - RDFSingleFeatureWriter(const string& trackid, const string& outfilename); - virtual ~RDFSingleFeatureWriter() { } - virtual void init(const string& trackid, const Vamp::Plugin::OutputList& outputList); - virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); - bool am_initialised; - int fe_count; - string trackid; - ostream* out; -}; - -#endif Copied: runner/trunk/RDFSinglePluginWriter.cpp (from rev 914, runner/trunk/RDFSingleFeatureWriter.cpp) =================================================================== --- runner/trunk/RDFSinglePluginWriter.cpp (rev 0) +++ runner/trunk/RDFSinglePluginWriter.cpp 2008-01-02 13:02:55 UTC (rev 915) @@ -0,0 +1,301 @@ +/* + * RDFSinglePluginWriter.cpp + * vamphost + * + * Created by Chris Sutton on 13/12/2007. + * Copyright 2007 Queen Mary, University of London. All rights reserved. + * + */ + +#include <iostream> +#include <fstream> +#include <map> +using namespace std; + +#include "RDFSinglePluginWriter.h" +#include "RDFFeatureWriter.h" +using Vamp::Plugin; + +#include <redland.h> + +string timelineURI = ":tl"; //FIXME ? + +RDFSinglePluginWriter::RDFSinglePluginWriter(const string& tid, const string& outfilename) : am_initialised(false), trackid(tid), fe_count(0) +{ + out = new ofstream(outfilename.c_str()); + if (!*out) + { + cerr << "ERROR RDFSinglePluginWriter(): can't open file " << outfilename << endl; +// out = cout; // ‽ + } +} + +void RDFSinglePluginWriter::init(const string& trackid, const string& pluginid, const Plugin::OutputList& outputList) +{ + cerr << "RDFSinglePluginWriter init()"<<endl; + + // FIXME might not need all these namespaces + *out << "@prefix dc: <http://purl.org/dc/elements/1.1/> .\n" + << "@prefix mo: <http://purl.org/ontology/mo/> .\n" + << "@prefix af: <http://purl.org/ontology/af/>.\n" + << "@prefix event: <http://purl.org/NET/c4dm/event.owl#>.\n" + << "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.\n" + << "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.\n" + << "@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.\n" + << "@prefix timeline: <http://purl.org/NET/c4dm/timeline.owl#>.\n" + << "@prefix time: <http://www.w3.org/2006/time#>.\n" + << "@prefix : <>.\n\n" + << endl; + + /* + * Describe signal we're analysing (AudioFile, Signal, TimeLine, etc.) + */ + *out << "<"<<trackid<<"> a mo:AudioFile .\n\n" + << ":signal a mo:Signal ;\n" + << " mo:available_as <"<<trackid<<"> ;\n" + << " mo:time :sig_int .\n" + << ":sig_int a time:Interval ;\n" + << " timeline:onTimeLine :tl.\n"; + + /* + * Describe feature events and features. + */ + + string desc_path = RDFFeatureWriter::getDescriptionFileForPlugin(pluginid); + if (desc_path!="") + { + + cerr<<"Got desc_path : "<<desc_path<<endl<<endl; + desc_path = "file://"+desc_path; + + librdf_world* world = librdf_new_world(); + librdf_world_open(world); + + librdf_uri *uri = librdf_new_uri(world, (const unsigned char*)desc_path.c_str()); + librdf_storage* storage = librdf_new_storage(world, "memory", "test", NULL); + librdf_parser* parser = librdf_new_parser(world, "guess", NULL, NULL); + librdf_model* model = librdf_new_model(world, storage, NULL); + + if(librdf_parser_parse_into_model(parser, uri, uri, model)) + cerr<<"Failed to parse RDF into model"<<endl; + librdf_free_parser(parser); + + // Find our plugin : + + librdf_node* n_rdf_type = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); + librdf_node* n_rdfs_subClassOf = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.w3.org/2000/01/rdf-schema#subClassOf"); + librdf_node* n_vamp_Plugin = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.vamp-plugins.org/ontology/Plugin"); + librdf_node* n_vamp_identifier = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.vamp-plugins.org/ontology/identifier"); + librdf_node* n_vamp_computes = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.vamp-plugins.org/ontology/computes"); + librdf_node* n_vamp_computes_feature_type = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.vamp-plugins.org/ontology/computes_feature_type"); + librdf_node* n_vamp_computes_event_type = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.vamp-plugins.org/ontology/computes_event_type"); + librdf_node* n_af_Feature = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://purl.org/ontology/af/Feature"); + librdf_node* n_af_FeatureEvent = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://purl.org/ontology/af/FeatureEvent"); + + + librdf_iterator* itr = librdf_model_get_sources(model, n_rdf_type, n_vamp_Plugin); + + librdf_node* n_plugin = NULL; + if(!itr || librdf_iterator_end(itr)) + cerr<<"No plugins found in the RDF file !"<<endl; + else + { + while(!librdf_iterator_end(itr)) + { + librdf_node* this_plugin = (librdf_node*)librdf_iterator_get_object(itr); + + // Check identifier : + librdf_node* n_identifier = librdf_model_get_target(model,this_plugin, n_vamp_identifier); + string identifier = (const char*)librdf_node_get_literal_value(n_identifier); + cerr<<"Found plugin w/id : "<<identifier<<endl; + if (identifier == pluginid) + n_plugin = this_plugin; + librdf_iterator_next(itr); + + } + librdf_free_iterator(itr); + } + + if (!n_plugin) + cerr<<"Couldn't find plugin with matching identifier in RDF file !"<<endl; + + + /* + * Describe feature events and features. + */ + + for (unsigned int i=0; i < outputList.size(); i++) + { + Plugin::OutputDescriptor od = outputList[i]; + ODTypes.push_back(ODOT_UNKNOWN); + ODFeatureTypeURIs.push_back("<http://purl.org/ontology/af/Feature>"); + ODEventTypeURIs.push_back("<http://purl.org/ontology/af/FeatureEvent>"); + + // Find the RDF about this output descriptor + + librdf_node* n_od = librdf_model_get_source(model, n_vamp_identifier, librdf_new_node_from_literal(world, (const unsigned char*)od.identifier.c_str(), NULL, 0)); + if (!n_od) + { + cerr<<"Couldn't find RDF description of output descriptor "<<od.identifier<<" !"<<endl; + ODTypes[i] = ODOT_UNKNOWN; + } + else + { + // Does it compute features, events, or both ? + itr = librdf_model_get_targets(model, n_od, n_vamp_computes_feature_type); + if (!itr || librdf_iterator_end(itr)) + ODTypes[i] = ODOT_UNKNOWN; + else + { + while(!librdf_iterator_end(itr)) + { + librdf_node* n_computes_obj = (librdf_node*)librdf_iterator_get_object(itr); + + if (ODTypes[i] == ODOT_BOTH || ODTypes[i] == ODOT_FEATURE) + cerr<<"Too many vamp:computes_feature_type statements for output descriptor "<<od.identifier<<" !"<<endl; + else + { + if (ODTypes[i] == ODOT_UNKNOWN) + ODTypes[i] = ODOT_FEATURE; + else + ODTypes[i] = ODOT_BOTH; + + ODFeatureTypeURIs[i] = "<"+(string)(const char*)librdf_uri_as_string(librdf_node_get_uri(n_computes_obj))+">"; + cerr<<"Setting ODTypes["<<i<<"]="<<ODTypes[i]<<", ODFeatureTypeURIs["<<i<<"]="<<ODFeatureTypeURIs[i]<<"."<<endl; + } + + librdf_iterator_next(itr); + } + + } + librdf_free_iterator(itr); + + itr = librdf_model_get_targets(model, n_od, n_vamp_computes_event_type); + if (itr && !librdf_iterator_end(itr)) + { + while(!librdf_iterator_end(itr)) + { + librdf_node* n_computes_obj = (librdf_node*)librdf_iterator_get_object(itr); + + if (ODTypes[i] == ODOT_BOTH || ODTypes[i] == ODOT_EVENT) + cerr<<"Too many vamp:computes_event_type statements for output descriptor "<<od.identifier<<" !"<<endl; + else + { + if (ODTypes[i] == ODOT_UNKNOWN) + ODTypes[i] = ODOT_EVENT; + else + ODTypes[i] = ODOT_BOTH; + ODEventTypeURIs[i] = "<"+(string)(const char*)librdf_uri_as_string(librdf_node_get_uri(n_computes_obj))+">"; + cerr<<"Setting ODTypes["<<i<<"]="<<ODTypes[i]<<", ODEventTypeURIs["<<i<<"]="<<ODEventTypeURIs[i]<<"."<<endl; + } + librdf_iterator_next(itr); + } + } + librdf_free_iterator(itr); + } + + /* + * Fallback to local names if accompanying RDF doesn't satisfy + */ + if (ODTypes[i] == ODOT_UNKNOWN) + { + cout << ":fetype_" << od.identifier << " rdfs:subClassOf af:FeatureEvent;\n" + << " dc:title \"" << od.name << "\"; \n" + << " dc:description \"" << od.description << " event\".\n" + << endl; + ODEventTypeURIs[i] = ":fetype_" + od.identifier; + + cout << ":ftype_" << od.identifier << " rdfs:subClassOf af:Feature;\n" + << " dc:title \"" << od.name << "\"; \n" + << " dc:description \"" << od.description << "\";\n" + << " dc:format \"" << od.unit << "\".\n\n" + << endl; + ODFeatureTypeURIs[i] = ":ftype_" + od.identifier; + } + } + + /* + * TODO : Add any relevant info about the Transform being used (eg. frame size, hop size) + */ + + + // I'm gonna presume freeing the world frees nodes too - otherwise we're gonna need these and more : + // librdf_free_node(n_rdf_type); + // librdf_free_node(n_vamp_plugin); + + + librdf_free_uri(uri); + librdf_free_model(model); + librdf_free_storage(storage); + librdf_free_world(world); + } + + am_initialised = true; +} + +void RDFSinglePluginWriter::write(const string& trackid, const string& pluginid, const Plugin::OutputList& outputList, const Plugin::FeatureSet& featureSet) +{ + if (!am_initialised) + init(trackid, pluginid, outputList); + + if (featureSet.size() == 0) + return; + + // iterate through FeatureLists + //cerr << featureSet.size() << " featurelists in set" << endl; + for (map<int, Plugin::FeatureList>::const_iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) + { + Plugin::FeatureList featureList = iter->second; + Plugin::OutputDescriptor od = outputList[iter->first]; + for (unsigned int i = 0; i < featureList.size(); ++i) + { + Plugin::Feature feature = featureList[i]; + *out << ":fe_" << fe_count << " rdf:type " << ODEventTypeURIs[iter->first] << ";\n"; + if (feature.label.length() > 0) + *out<< " rdfs:label \"" << feature.label << "\";\n"; // Might want to rethink this + + /* + * Add timestamp + * In current design this is handled by the rebuffering, s.t. all outputs are VariableSampleRate and have a valid timestamp. + */ + if (od.sampleType == Plugin::OutputDescriptor::VariableSampleRate) + { + *out<< " event:time [ rdf:type time:Instant;\n" //location of the event in time + << " time:onTimeLine " << timelineURI << ";\n" + << " time:atDuration \"PT" << feature.timestamp.toString() << "S\"^^xsd:duration;];\n"; + } + else + cerr<<"Arg, got a plugin whose OutputDescriptor SampleType isn't VariableSampleRate ! Not sure what to do..."<<endl; + + *out << " af:hasFeature :f_"<<fe_count<<"."<<endl; + + /* + * Add Feature resource + */ + + *out << ":f_"<<fe_count<<" rdf:type "<< ODFeatureTypeURIs[iter->first]; + if (feature.label.length() > 0) + *out<< ";\n rdfs:label \"" << feature.label << "\""; + + if (feature.values.size() > 0) + { + *out<<";\n"; + + // TODO : If the plugin names its bins we should do one triple per value + // hopefully we have type URIs for the bins from the plugin's RDF file + + + // If the plugin doesn't name its bins there's probably no point separating them, + // so we'll do a CSV literal : + *out << " af:value \""<< feature.values[0]; + for (unsigned int j = 1; j < feature.values.size(); ++j) + *out << "," << feature.values[j]; + *out << "\"." << endl; + } + else + *out<< ".\n"; + + fe_count++; + } + } +} Copied: runner/trunk/RDFSinglePluginWriter.h (from rev 914, runner/trunk/RDFSingleFeatureWriter.h) =================================================================== --- runner/trunk/RDFSinglePluginWriter.h (rev 0) +++ runner/trunk/RDFSinglePluginWriter.h 2008-01-02 13:02:55 UTC (rev 915) @@ -0,0 +1,43 @@ +/* + * RDFSinglePluginWriter.h + * vamphost + * + * Created by Chris Sutton on 13/12/2007. + * Copyright 2007 Queen Mary, University of London. All rights reserved. + * + */ + +#ifndef _RDF_SINGLE_PLUGIN_WRITER_H_ +#define _RDF_SINGLE_PLUGIN_WRITER_H_ + +#include <fstream> +using std::ostream; +#include "FeatureWriter.h" + +enum ODOutputType +{ + ODOT_UNKNOWN, + ODOT_FEATURE, + ODOT_EVENT, + ODOT_BOTH +}; + +class RDFSinglePluginWriter : public FeatureWriter +{ +public: + RDFSinglePluginWriter(const string& trackid, const string& outfilename); + virtual ~RDFSinglePluginWriter() { } + virtual void init(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList); + virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); + bool am_initialised; + string trackid; + int fe_count; + ostream* out; + +private: + vector<int> ODTypes; + vector<string> ODFeatureTypeURIs; + vector<string> ODEventTypeURIs; +}; + +#endif Modified: runner/trunk/runner.pro =================================================================== --- runner/trunk/runner.pro 2007-12-18 10:35:55 UTC (rev 914) +++ runner/trunk/runner.pro 2008-01-02 13:02:55 UTC (rev 915) @@ -15,7 +15,7 @@ contains(DEFINES, BUILD_STATIC):LIBS -= -ljack -LIBS = -lsvaudioio -lsvdata -lsvplugin -lsvbase -lsvsystem $$LIBS +LIBS = -lsvaudioio -lsvdata -lsvplugin -lsvbase -lsvsystem -lrdf $$LIBS PRE_TARGETDEPS += ../sonic-visualiser/audioio/libsvaudioio.a \ ../sonic-visualiser/data/libsvdata.a \ @@ -28,7 +28,7 @@ # Input HEADERS += -SOURCES += main.cpp DefaultFeatureWriter.cpp RDFFeatureWriter.cpp RDFSingleFeatureWriter.cpp FeatureExtractionManager.cpp AudioDBFeatureWriter.cpp +SOURCES += main.cpp DefaultFeatureWriter.cpp RDFFeatureWriter.cpp RDFSinglePluginWriter.cpp FeatureExtractionManager.cpp AudioDBFeatureWriter.cpp This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ca...@us...> - 2008-01-04 10:44:18
|
Revision: 916 http://sv1.svn.sourceforge.net/sv1/?rev=916&view=rev Author: cannam Date: 2008-01-04 02:44:16 -0800 (Fri, 04 Jan 2008) Log Message: ----------- * Untabify. Please, no tab characters in code -- it just causes conflict because different editors (or people) have different ideas about what they should mean. Also add comment to tops of files to cause vi and emacs to select 4-space indentation without tabs automatically. Modified Paths: -------------- runner/trunk/AudioDBFeatureWriter.cpp runner/trunk/AudioDBFeatureWriter.h runner/trunk/DefaultFeatureWriter.cpp runner/trunk/DefaultFeatureWriter.h runner/trunk/FeatureExtractionManager.cpp runner/trunk/FeatureExtractionManager.h runner/trunk/FeatureWriter.h runner/trunk/RDFFeatureWriter.cpp runner/trunk/RDFFeatureWriter.h runner/trunk/RDFSinglePluginWriter.cpp runner/trunk/RDFSinglePluginWriter.h runner/trunk/SimpleRDFFeatureWriter.cpp runner/trunk/SimpleRDFFeatureWriter.h runner/trunk/main.cpp Modified: runner/trunk/AudioDBFeatureWriter.cpp =================================================================== --- runner/trunk/AudioDBFeatureWriter.cpp 2008-01-02 13:02:55 UTC (rev 915) +++ runner/trunk/AudioDBFeatureWriter.cpp 2008-01-04 10:44:16 UTC (rev 916) @@ -1,3 +1,4 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* * DefaultFeatureWriter.cpp * runner @@ -15,123 +16,123 @@ struct AudioDBFeatureWriter::TrackStream { - string trackid; - ofstream* ofs; + string trackid; + ofstream* ofs; }; AudioDBFeatureWriter::AudioDBFeatureWriter(const string& catId, const string& dir) : catalogueId(catId), baseDir(dir) { - + } AudioDBFeatureWriter::~AudioDBFeatureWriter() { - // close all open files - for (map<string, TrackStream>::iterator iter = dbfiles.begin(); iter != dbfiles.end(); ++iter) - { - iter->second.ofs->close(); - delete iter->second.ofs; - } - - // TODO: error handling on close + // close all open files + for (map<string, TrackStream>::iterator iter = dbfiles.begin(); iter != dbfiles.end(); ++iter) + { + iter->second.ofs->close(); + delete iter->second.ofs; + } + + // TODO: error handling on close } void AudioDBFeatureWriter::write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) { - // binary output for FeatureSet - - // feature-dimension feature-1 feature-2 ... - // timestamp-1 timestamp-2 ... - - // audioDB has to write each feature to a different file - // assume a simple naming convention of - // <catalog-id>/<track-id>.<feature-id> - // with timestamps in a corresponding <catalog-id>/<track-id>.<feature-id>.timestamp file - - // the feature writer holds a map of open file descriptors - // the catalog-id is passed in to the feature writer's constructor - - // TODO: - // - write feature end rather than start times, once end time is available in vamp - // - write a power file, probably by wrapping plugin in a PluginPowerAdapter :) - - - // iterate through FeatureLists - for (map<int, Vamp::Plugin::FeatureList>::const_iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) - { - Vamp::Plugin::FeatureList featureList = iter->second; - Vamp::Plugin::OutputDescriptor output = outputList[iter->first]; - - if (output.binCount == 0) // this kind of feature just outputs timestamps and labels, assume of no interest to audioDB - continue; - - for (int i = 0; i < featureList.size(); ++i) - { - // replace output files if necessary - if (replaceDBFile(trackid, output.identifier)) - { - // write the feature length for the next track feature record - // binCount has to be set - // - it can be zero, i.e. if the output is really a set of labels + timestamps - *dbfiles[output.identifier].ofs /*<< ios::binary*/ << output.binCount; - - cerr << "writing bin count " << output.binCount << " for " << output.identifier << endl; - } - - if (replaceDBFile(trackid, output.identifier + ".timestamp")) - { - // write the start time to the timestamp file - // as we want it for the first feature in the file - *dbfiles[output.identifier + ".timestamp"].ofs << featureList[i].timestamp.toString() << endl; - } - - for (int j = 0; j < featureList[i].values.size(); ++j) - *dbfiles[output.identifier].ofs /*<< ios::binary*/ << featureList[i].values[j]; - - // write the *end* time of each feature to the timestamp file - // NOT IMPLEMENTED YET - *dbfiles[output.identifier + ".timestamp"].ofs << featureList[i].timestamp.toString() << endl; - } - } + // binary output for FeatureSet + + // feature-dimension feature-1 feature-2 ... + // timestamp-1 timestamp-2 ... + + // audioDB has to write each feature to a different file + // assume a simple naming convention of + // <catalog-id>/<track-id>.<feature-id> + // with timestamps in a corresponding <catalog-id>/<track-id>.<feature-id>.timestamp file + + // the feature writer holds a map of open file descriptors + // the catalog-id is passed in to the feature writer's constructor + + // TODO: + // - write feature end rather than start times, once end time is available in vamp + // - write a power file, probably by wrapping plugin in a PluginPowerAdapter :) + + + // iterate through FeatureLists + for (map<int, Vamp::Plugin::FeatureList>::const_iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) + { + Vamp::Plugin::FeatureList featureList = iter->second; + Vamp::Plugin::OutputDescriptor output = outputList[iter->first]; + + if (output.binCount == 0) // this kind of feature just outputs timestamps and labels, assume of no interest to audioDB + continue; + + for (int i = 0; i < featureList.size(); ++i) + { + // replace output files if necessary + if (replaceDBFile(trackid, output.identifier)) + { + // write the feature length for the next track feature record + // binCount has to be set + // - it can be zero, i.e. if the output is really a set of labels + timestamps + *dbfiles[output.identifier].ofs /*<< ios::binary*/ << output.binCount; + + cerr << "writing bin count " << output.binCount << " for " << output.identifier << endl; + } + + if (replaceDBFile(trackid, output.identifier + ".timestamp")) + { + // write the start time to the timestamp file + // as we want it for the first feature in the file + *dbfiles[output.identifier + ".timestamp"].ofs << featureList[i].timestamp.toString() << endl; + } + + for (int j = 0; j < featureList[i].values.size(); ++j) + *dbfiles[output.identifier].ofs /*<< ios::binary*/ << featureList[i].values[j]; + + // write the *end* time of each feature to the timestamp file + // NOT IMPLEMENTED YET + *dbfiles[output.identifier + ".timestamp"].ofs << featureList[i].timestamp.toString() << endl; + } + } } bool AudioDBFeatureWriter::openDBFile(const string& trackid, const string& identifier) { - string filepath = baseDir + "/" + catalogueId + "/" + trackid + "." + identifier; - ofstream* ofs = new ofstream(filepath.c_str()); - if (!*ofs) - { - cerr << "ERROR AudioDBFeatureWriter::openDBFile(): can't open file " << filepath << endl; - return false; - } - TrackStream ts; - ts.trackid = trackid; - ts.ofs = ofs; - dbfiles[identifier] = ts; - return true; + string filepath = baseDir + "/" + catalogueId + "/" + trackid + "." + identifier; + ofstream* ofs = new ofstream(filepath.c_str()); + if (!*ofs) + { + cerr << "ERROR AudioDBFeatureWriter::openDBFile(): can't open file " << filepath << endl; + return false; + } + TrackStream ts; + ts.trackid = trackid; + ts.ofs = ofs; + dbfiles[identifier] = ts; + return true; } // replace file if no file open for this track, else return false bool AudioDBFeatureWriter::replaceDBFile(const string& trackid, const string& identifier) { - if (dbfiles.find(identifier) != dbfiles.end() && dbfiles[identifier].trackid == trackid) - return false; // have an open file for this track - - if (dbfiles.find(identifier) != dbfiles.end() && dbfiles[identifier].trackid != trackid) - { - // close the current file - dbfiles[identifier].ofs->close(); - delete dbfiles[identifier].ofs; - } - - // open a new file - openDBFile(trackid, identifier); - - // TODO: - // handle file open failure - - return true; + if (dbfiles.find(identifier) != dbfiles.end() && dbfiles[identifier].trackid == trackid) + return false; // have an open file for this track + + if (dbfiles.find(identifier) != dbfiles.end() && dbfiles[identifier].trackid != trackid) + { + // close the current file + dbfiles[identifier].ofs->close(); + delete dbfiles[identifier].ofs; + } + + // open a new file + openDBFile(trackid, identifier); + + // TODO: + // handle file open failure + + return true; } - - \ No newline at end of file + + Modified: runner/trunk/AudioDBFeatureWriter.h =================================================================== --- runner/trunk/AudioDBFeatureWriter.h 2008-01-02 13:02:55 UTC (rev 915) +++ runner/trunk/AudioDBFeatureWriter.h 2008-01-04 10:44:16 UTC (rev 916) @@ -1,3 +1,4 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* * AudioDBFeatureWriter.h * runner @@ -21,19 +22,19 @@ class AudioDBFeatureWriter : public FeatureWriter { public: - AudioDBFeatureWriter(const string& catId, const string& dir); - virtual ~AudioDBFeatureWriter(); - virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); - + AudioDBFeatureWriter(const string& catId, const string& dir); + virtual ~AudioDBFeatureWriter(); + virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); + private: - string catalogueId; - string baseDir; - - struct TrackStream; - map<string, TrackStream> dbfiles; - - bool openDBFile(const string& trackid, const string& identifier); - bool replaceDBFile(const string& trackid, const string& identifier); + string catalogueId; + string baseDir; + + struct TrackStream; + map<string, TrackStream> dbfiles; + + bool openDBFile(const string& trackid, const string& identifier); + bool replaceDBFile(const string& trackid, const string& identifier); }; #endif Modified: runner/trunk/DefaultFeatureWriter.cpp =================================================================== --- runner/trunk/DefaultFeatureWriter.cpp 2008-01-02 13:02:55 UTC (rev 915) +++ runner/trunk/DefaultFeatureWriter.cpp 2008-01-04 10:44:16 UTC (rev 916) @@ -1,3 +1,4 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* * DefaultFeatureWriter.cpp * vamphost @@ -16,46 +17,46 @@ void DefaultFeatureWriter::write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) { - // generic XML output for FeatureSet - - /* - - <feature> - <name>output.name</name> - <timestamp>feature.timestamp</timestamp> - <values>output.binName[0]:feature.value[0]...</values> - <label>feature.label</label> - </feature> - - */ - - // iterate through FeatureLists - - for (map<int, Vamp::Plugin::FeatureList>::const_iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) - { - Vamp::Plugin::FeatureList featureList = iter->second; - Vamp::Plugin::OutputDescriptor output = outputList[iter->first]; - for (int i = 0; i < featureList.size(); ++i) - { - cerr << "<feature>" << endl; - cerr << "\t<name>" << output.name << "</name>" << endl; - cerr << "\t<timestamp>" << featureList[i].timestamp << "</timestamp>" << endl; - if (featureList[i].values.size() > 0) - { - cerr << "\t<values>"; - for (int j = 0; j < featureList[i].values.size(); ++j) - { - if (j > 0) - cerr << " "; - if (output.binNames.size() > 0) - cerr << output.binNames[j] << ":"; - cerr << featureList[i].values[j]; - } - cerr << "</values>" << endl; - } - if (featureList[i].label.length() > 0) - cerr << "\t<label>" << featureList[i].label << "</label>" << endl; - cerr << "</feature>" << endl; - } - } -} \ No newline at end of file + // generic XML output for FeatureSet + + /* + + <feature> + <name>output.name</name> + <timestamp>feature.timestamp</timestamp> + <values>output.binName[0]:feature.value[0]...</values> + <label>feature.label</label> + </feature> + + */ + + // iterate through FeatureLists + + for (map<int, Vamp::Plugin::FeatureList>::const_iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) + { + Vamp::Plugin::FeatureList featureList = iter->second; + Vamp::Plugin::OutputDescriptor output = outputList[iter->first]; + for (int i = 0; i < featureList.size(); ++i) + { + cerr << "<feature>" << endl; + cerr << "\t<name>" << output.name << "</name>" << endl; + cerr << "\t<timestamp>" << featureList[i].timestamp << "</timestamp>" << endl; + if (featureList[i].values.size() > 0) + { + cerr << "\t<values>"; + for (int j = 0; j < featureList[i].values.size(); ++j) + { + if (j > 0) + cerr << " "; + if (output.binNames.size() > 0) + cerr << output.binNames[j] << ":"; + cerr << featureList[i].values[j]; + } + cerr << "</values>" << endl; + } + if (featureList[i].label.length() > 0) + cerr << "\t<label>" << featureList[i].label << "</label>" << endl; + cerr << "</feature>" << endl; + } + } +} Modified: runner/trunk/DefaultFeatureWriter.h =================================================================== --- runner/trunk/DefaultFeatureWriter.h 2008-01-02 13:02:55 UTC (rev 915) +++ runner/trunk/DefaultFeatureWriter.h 2008-01-04 10:44:16 UTC (rev 916) @@ -1,3 +1,4 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* * DefaultFeatureWriter.h * vamphost @@ -16,8 +17,8 @@ class DefaultFeatureWriter : public FeatureWriter { public: - virtual ~DefaultFeatureWriter() { } - virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); + virtual ~DefaultFeatureWriter() { } + virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); }; #endif Modified: runner/trunk/FeatureExtractionManager.cpp =================================================================== --- runner/trunk/FeatureExtractionManager.cpp 2008-01-02 13:02:55 UTC (rev 915) +++ runner/trunk/FeatureExtractionManager.cpp 2008-01-04 10:44:16 UTC (rev 916) @@ -1,3 +1,4 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* * FeatureExtractionManager.cpp * runner @@ -40,166 +41,166 @@ FeatureExtractionManager::~FeatureExtractionManager() { - for (int i = 0; i < plugins.size(); ++i) - delete plugins[i]; + for (int i = 0; i < plugins.size(); ++i) + delete plugins[i]; } void FeatureExtractionManager::setChannels(int channels) { - m_channels = channels; + m_channels = channels; } void FeatureExtractionManager::setSampleRate(int sampleRate) { - m_sampleRate = sampleRate; + m_sampleRate = sampleRate; } bool FeatureExtractionManager::addFeatureExtractor(string library, string plugname, vector<FeatureWriter*> writers) { - PluginLoader *loader = PluginLoader::getInstance(); - + PluginLoader *loader = PluginLoader::getInstance(); + PluginLoader::PluginKey key = loader->composePluginKey(library, plugname); - - Plugin* plugin = loader->loadPlugin(key, m_sampleRate, PluginLoader::ADAPT_ALL); + + Plugin* plugin = loader->loadPlugin(key, m_sampleRate, PluginLoader::ADAPT_ALL); if (!plugin) { cerr << "ERROR: Failed to load plugin \"" << plugin << "\" from library \"" << library << "\"" << endl; return false; } - - plugins.push_back(plugin); - pluginWriters.push_back(writers); - - // create a Transform recording all the parameter settings etc. - Transform transform; - TransformFactory *tf = TransformFactory::getInstance(); + + plugins.push_back(plugin); + pluginWriters.push_back(writers); + + // create a Transform recording all the parameter settings etc. + Transform transform; + TransformFactory *tf = TransformFactory::getInstance(); - transform = tf->getDefaultTransformFor - (Transform::getIdentifierForPluginOutput(key.c_str(), ""), - m_sampleRate); + transform = tf->getDefaultTransformFor + (Transform::getIdentifierForPluginOutput(key.c_str(), ""), + m_sampleRate); - tf->setParametersFromPlugin(transform, plugin); - transforms.push_back(transform); - - return true; + tf->setParametersFromPlugin(transform, plugin); + transforms.push_back(transform); + + return true; } bool FeatureExtractionManager::addFeatureExtractor(string transformXmlFile, vector<FeatureWriter*> writers) { - FILE* file = fopen(transformXmlFile.c_str(),"r"); - if (!file) { - cerr << "ERROR: Failed to open transform XML file \"" - << transformXmlFile << "\" for reading" << endl; - perror("Failed to open transform file"); - return false; - } - QTextStream qts(file); - QString qs = qts.readAll(); - fclose(file); - Transform transform(qs); - - if (transform.getSampleRate() != m_sampleRate) - { - cerr << "ERROR: transform sample rate " << transform.getSampleRate() << " doesn't match the one you set for audio extraction " << m_sampleRate << endl; - print(transform); - cerr << endl; - return false; - } - - Plugin* plugin = TransformFactory::getInstance()->downcastVampPlugin(TransformFactory::getInstance()->instantiatePluginFor(transform)); + FILE* file = fopen(transformXmlFile.c_str(),"r"); + if (!file) { + cerr << "ERROR: Failed to open transform XML file \"" + << transformXmlFile << "\" for reading" << endl; + perror("Failed to open transform file"); + return false; + } + QTextStream qts(file); + QString qs = qts.readAll(); + fclose(file); + Transform transform(qs); + + if (transform.getSampleRate() != m_sampleRate) + { + cerr << "ERROR: transform sample rate " << transform.getSampleRate() << " doesn't match the one you set for audio extraction " << m_sampleRate << endl; + print(transform); + cerr << endl; + return false; + } + + Plugin* plugin = TransformFactory::getInstance()->downcastVampPlugin(TransformFactory::getInstance()->instantiatePluginFor(transform)); if (!plugin) { cerr << "ERROR: Failed to load plugin from transform " << transformXmlFile << endl; - print(transform); - cerr << endl; + print(transform); + cerr << endl; return false; } - - // adapt the plugin for buffering, channels, etc. - if (plugin->getInputDomain() == Plugin::FrequencyDomain) - plugin = new PluginInputDomainAdapter(plugin); - plugin = new PluginBufferingAdapter(plugin); - plugin = new PluginChannelAdapter(plugin); - - plugins.push_back(plugin); - pluginWriters.push_back(writers); - transforms.push_back(transform); - - return true; + + // adapt the plugin for buffering, channels, etc. + if (plugin->getInputDomain() == Plugin::FrequencyDomain) + plugin = new PluginInputDomainAdapter(plugin); + plugin = new PluginBufferingAdapter(plugin); + plugin = new PluginChannelAdapter(plugin); + + plugins.push_back(plugin); + pluginWriters.push_back(writers); + transforms.push_back(transform); + + return true; } void FeatureExtractionManager::extractFeatures(string audioSource) { - cerr << "Creating FileSource..." << endl; - - FileSource source(audioSource.c_str()); - if (!source.isAvailable()) - { + cerr << "Creating FileSource..." << endl; + + FileSource source(audioSource.c_str()); + if (!source.isAvailable()) + { cerr << "ERROR: File or URL \"" << audioSource << "\" could not be located" << endl; exit(1); } cerr << "Retrieving or locating \"" << audioSource << "\"..." << endl; - + source.waitForData(); - + cerr << "Opening and/or decoding audio file..." << endl; AudioFileReader *reader = AudioFileReaderFactory::createReader(source, m_sampleRate); if (!reader) - { + { cerr << "ERROR: File or URL \"" << audioSource << "\" could not be opened" << endl; exit(1); } - + // read using an arbitrary fixed block size - int blockSize = 2048; - int stepSize = 2048; - + int blockSize = 2048; + int stepSize = 2048; + cerr << "Using block size = " << blockSize << ", step size = " << stepSize << endl; - - size_t channels = reader->getChannelCount(); - - // reject file if it has too few channels, plugin will handle if it has too many - if (channels < m_channels) - { + + size_t channels = reader->getChannelCount(); + + // reject file if it has too few channels, plugin will handle if it has too many + if (channels < m_channels) + { cerr << "ERROR: File or URL \"" << audioSource << "\" has less than " << m_channels << " channels" << endl; exit(1); } - - // allocate audio buffers - float **data = new float *[m_channels]; + + // allocate audio buffers + float **data = new float *[m_channels]; for (size_t c = 0; c < m_channels; ++c) - data[c] = new float[blockSize]; - + data[c] = new float[blockSize]; + for (int i = 0; i < plugins.size(); ++i) - { - int minch = plugins[i]->getMinChannelCount(); - int maxch = plugins[i]->getMaxChannelCount(); - cerr << "Plugin accepts " << minch << " -> " << maxch << " channel(s)" << endl; - cerr << "Sound file has " << m_channels << " (will mix/augment if necessary)" << endl; - - if (!plugins[i]->initialise(m_channels, stepSize, blockSize)) { - cerr << "ERROR: Plugin initialise (channels = " << m_channels << ", stepSize = " << stepSize << ", blockSize = " << blockSize << ") failed." << endl; - - // TODO: - // decide how to handle this error... - } - } - - size_t frameCount = reader->getFrameCount(); - - cerr << "file has " << frameCount << " frames" << endl; - - // we may want to control the start and end times - // for feature extraction - this code just process - // the whole file - + { + int minch = plugins[i]->getMinChannelCount(); + int maxch = plugins[i]->getMaxChannelCount(); + cerr << "Plugin accepts " << minch << " -> " << maxch << " channel(s)" << endl; + cerr << "Sound file has " << m_channels << " (will mix/augment if necessary)" << endl; + + if (!plugins[i]->initialise(m_channels, stepSize, blockSize)) { + cerr << "ERROR: Plugin initialise (channels = " << m_channels << ", stepSize = " << stepSize << ", blockSize = " << blockSize << ") failed." << endl; + + // TODO: + // decide how to handle this error... + } + } + + size_t frameCount = reader->getFrameCount(); + + cerr << "file has " << frameCount << " frames" << endl; + + // we may want to control the start and end times + // for feature extraction - this code just process + // the whole file + for (size_t i = 0; i < frameCount; i += stepSize) { //!!! inefficient, although much of the inefficiency may be // susceptible to optimisation - - SampleBlock frames; + + SampleBlock frames; reader->getInterleavedFrames(i, blockSize, frames); for (size_t j = 0; j < blockSize; ++j) { @@ -211,43 +212,43 @@ data[c][j] = 0.f; } } - } - - Vamp::RealTime timestamp = Vamp::RealTime::frame2RealTime(i, m_sampleRate); - - for (int k = 0; k < plugins.size(); ++k) - { - Vamp::Plugin::FeatureSet featureSet = plugins[k]->process(data, timestamp); - for (int j = 0; j < pluginWriters[k].size(); ++j) - pluginWriters[k][j]->write("track01", plugins[k]->getIdentifier(), plugins[k]->getOutputDescriptors(), featureSet); - } - } - - for (int k = 0; k < plugins.size(); ++k) - { - // we may want to set the start and duration times for extraction - // in the transform record (defaults of zero indicate extraction - // from the whole file) - transforms[k].setStartTime(RealTime()); - transforms[k].setDuration(RealTime::frame2RealTime(reader->getFrameCount(), m_sampleRate)); - - print(transforms[k]); - - // guess we could now pass it to the writers - // in case they wanted to add header information - // or even rename files according to some convention - - for (int j = 0; j < pluginWriters[k].size(); ++j) - pluginWriters[k][j]->write("track01", plugins[k]->getIdentifier(), plugins[k]->getOutputDescriptors(), plugins[k]->getRemainingFeatures()); - } - - TempDirectory::getInstance()->cleanup(); + } + + Vamp::RealTime timestamp = Vamp::RealTime::frame2RealTime(i, m_sampleRate); + + for (int k = 0; k < plugins.size(); ++k) + { + Vamp::Plugin::FeatureSet featureSet = plugins[k]->process(data, timestamp); + for (int j = 0; j < pluginWriters[k].size(); ++j) + pluginWriters[k][j]->write("track01", plugins[k]->getIdentifier(), plugins[k]->getOutputDescriptors(), featureSet); + } + } + + for (int k = 0; k < plugins.size(); ++k) + { + // we may want to set the start and duration times for extraction + // in the transform record (defaults of zero indicate extraction + // from the whole file) + transforms[k].setStartTime(RealTime()); + transforms[k].setDuration(RealTime::frame2RealTime(reader->getFrameCount(), m_sampleRate)); + + print(transforms[k]); + + // guess we could now pass it to the writers + // in case they wanted to add header information + // or even rename files according to some convention + + for (int j = 0; j < pluginWriters[k].size(); ++j) + pluginWriters[k][j]->write("track01", plugins[k]->getIdentifier(), plugins[k]->getOutputDescriptors(), plugins[k]->getRemainingFeatures()); + } + + TempDirectory::getInstance()->cleanup(); } void FeatureExtractionManager::print(Transform transform) const { - QString qs; - QTextStream qts(&qs); - transform.toXml(qts); - cerr << qs.toStdString() << endl; + QString qs; + QTextStream qts(&qs); + transform.toXml(qts); + cerr << qs.toStdString() << endl; } Modified: runner/trunk/FeatureExtractionManager.h =================================================================== --- runner/trunk/FeatureExtractionManager.h 2008-01-02 13:02:55 UTC (rev 915) +++ runner/trunk/FeatureExtractionManager.h 2008-01-04 10:44:16 UTC (rev 916) @@ -1,3 +1,4 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* * FeatureExtractionManager.h * runner @@ -24,21 +25,21 @@ class FeatureExtractionManager { public: - FeatureExtractionManager(); - virtual ~FeatureExtractionManager(); - void setChannels(int channels); - void setSampleRate(int sampleRate); - bool addFeatureExtractor(string transformXmlFile, vector<FeatureWriter*> writers); - bool addFeatureExtractor(string library, string plugname, vector<FeatureWriter*> writers); - void extractFeatures(string audioSource); + FeatureExtractionManager(); + virtual ~FeatureExtractionManager(); + void setChannels(int channels); + void setSampleRate(int sampleRate); + bool addFeatureExtractor(string transformXmlFile, vector<FeatureWriter*> writers); + bool addFeatureExtractor(string library, string plugname, vector<FeatureWriter*> writers); + void extractFeatures(string audioSource); private: - vector<Vamp::Plugin*> plugins; - vector<vector<FeatureWriter*> > pluginWriters; // parallel vector of writers for each plugin - vector<Transform> transforms; // parallel vector of transform records for each plugin - int m_sampleRate; - int m_channels; - - void print(Transform transform) const; + vector<Vamp::Plugin*> plugins; + vector<vector<FeatureWriter*> > pluginWriters; // parallel vector of writers for each plugin + vector<Transform> transforms; // parallel vector of transform records for each plugin + int m_sampleRate; + int m_channels; + + void print(Transform transform) const; }; #endif Modified: runner/trunk/FeatureWriter.h =================================================================== --- runner/trunk/FeatureWriter.h 2008-01-02 13:02:55 UTC (rev 915) +++ runner/trunk/FeatureWriter.h 2008-01-04 10:44:16 UTC (rev 916) @@ -1,3 +1,4 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* * FeatureWriter.h * vamphost @@ -19,8 +20,8 @@ class FeatureWriter { public: - virtual ~FeatureWriter() { } - virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) = 0; + virtual ~FeatureWriter() { } + virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) = 0; }; #endif Modified: runner/trunk/RDFFeatureWriter.cpp =================================================================== --- runner/trunk/RDFFeatureWriter.cpp 2008-01-02 13:02:55 UTC (rev 915) +++ runner/trunk/RDFFeatureWriter.cpp 2008-01-04 10:44:16 UTC (rev 916) @@ -1,3 +1,4 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* * RDFFeatureWriter.cpp * runner @@ -22,116 +23,116 @@ RDFFeatureWriter::RDFFeatureWriter(const string& catId, const string& dir) : catalogueId(catId), baseDir(dir) { - + } RDFFeatureWriter::~RDFFeatureWriter() { - // close all open files - for (map<string, RDFSinglePluginWriter*>::iterator iter = featureWriters.begin(); iter != featureWriters.end(); ++iter) - { - delete iter->second; - } + // close all open files + for (map<string, RDFSinglePluginWriter*>::iterator iter = featureWriters.begin(); iter != featureWriters.end(); ++iter) + { + delete iter->second; + } } void RDFFeatureWriter::write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) { - - // iterate through FeatureLists - for (map<int, Vamp::Plugin::FeatureList>::const_iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) - { - Vamp::Plugin::FeatureList featureList = iter->second; - Vamp::Plugin::OutputDescriptor output = outputList[iter->first]; - - for (unsigned int i = 0; i < featureList.size(); ++i) - { - // replace output files if necessary - replaceFeatureWriter(trackid, pluginid); - featureWriters[pluginid]->write(trackid, pluginid, outputList, featureSet); - } - } + + // iterate through FeatureLists + for (map<int, Vamp::Plugin::FeatureList>::const_iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) + { + Vamp::Plugin::FeatureList featureList = iter->second; + Vamp::Plugin::OutputDescriptor output = outputList[iter->first]; + + for (unsigned int i = 0; i < featureList.size(); ++i) + { + // replace output files if necessary + replaceFeatureWriter(trackid, pluginid); + featureWriters[pluginid]->write(trackid, pluginid, outputList, featureSet); + } + } } bool RDFFeatureWriter::newFeatureWriter(const string& trackid, const string& identifier) { - string filepath = baseDir + "/" + catalogueId + "/" + trackid + "." + identifier + ".rdf"; - featureWriters[identifier] = new RDFSinglePluginWriter(trackid, filepath); - if (!(featureWriters[identifier]->out)) - return false; - return true; + string filepath = baseDir + "/" + catalogueId + "/" + trackid + "." + identifier + ".rdf"; + featureWriters[identifier] = new RDFSinglePluginWriter(trackid, filepath); + if (!(featureWriters[identifier]->out)) + return false; + return true; } // replace writer if no writer open for this track&plugin, else return false bool RDFFeatureWriter::replaceFeatureWriter(const string& trackid, const string& pluginid) { - if (featureWriters.find(pluginid) != featureWriters.end()) - { - if (featureWriters[pluginid]->trackid == trackid) - return false; // have a feature writer for this track & plugin - else // track has changed - { - cerr<<"found feature writer with old track"<<endl; - cerr<<"new : "<<trackid<<", old : "<<featureWriters[pluginid]->trackid<<endl; - delete featureWriters[pluginid]; - } - } - cerr<<"allocating new RDFSinglePluginWriter"<<endl; - newFeatureWriter(trackid, pluginid); - return true; + if (featureWriters.find(pluginid) != featureWriters.end()) + { + if (featureWriters[pluginid]->trackid == trackid) + return false; // have a feature writer for this track & plugin + else // track has changed + { + cerr<<"found feature writer with old track"<<endl; + cerr<<"new : "<<trackid<<", old : "<<featureWriters[pluginid]->trackid<<endl; + delete featureWriters[pluginid]; + } + } + cerr<<"allocating new RDFSinglePluginWriter"<<endl; + newFeatureWriter(trackid, pluginid); + return true; } string RDFFeatureWriter::getDescriptionFileForPlugin(const string& pluginid) { - string path = ""; - vector<string> paths = PluginHostAdapter::getPluginPath(); + string path = ""; + vector<string> paths = PluginHostAdapter::getPluginPath(); - vector<string> rdf_exts; - rdf_exts.push_back("rdf"); rdf_exts.push_back("RDF"); - rdf_exts.push_back("n3"); rdf_exts.push_back("N3"); + vector<string> rdf_exts; + rdf_exts.push_back("rdf"); rdf_exts.push_back("RDF"); + rdf_exts.push_back("n3"); rdf_exts.push_back("N3"); - PluginLoader *loader = PluginLoader::getInstance(); - vector<string> keys = loader->listPlugins(); - string libname = ""; - for (vector<string>::iterator kitr = keys.begin(); kitr != keys.end(); kitr++) - { - string::size_type ci = (*kitr).find(':'); - if (ci != string::npos && (*kitr).substr(ci + 1) == pluginid) - { - libname = (*kitr).substr(0,ci); - cerr<<"Found library name for plugin : "<<libname<<endl; - } - } - if (libname == "") - cerr<<"Couldn't find library name for plugin "<<pluginid<<" !"<<endl; - - // Search each Vamp plugin path for a .rdf file matching the plugin identifier - // (possibly in a library-named directory) - - for (vector<string>::const_iterator pitr = paths.begin(); pitr != paths.end(); pitr++) - { - for (vector<string>::const_iterator eitr = rdf_exts.begin(); eitr != rdf_exts.end(); eitr++) - { - path = *pitr + "/" + pluginid + "." + *eitr; - cerr<<"Looking for "<<path<<endl; - // Check for file - if (fileExists(path)) - return path; + PluginLoader *loader = PluginLoader::getInstance(); + vector<string> keys = loader->listPlugins(); + string libname = ""; + for (vector<string>::iterator kitr = keys.begin(); kitr != keys.end(); kitr++) + { + string::size_type ci = (*kitr).find(':'); + if (ci != string::npos && (*kitr).substr(ci + 1) == pluginid) + { + libname = (*kitr).substr(0,ci); + cerr<<"Found library name for plugin : "<<libname<<endl; + } + } + if (libname == "") + cerr<<"Couldn't find library name for plugin "<<pluginid<<" !"<<endl; + + // Search each Vamp plugin path for a .rdf file matching the plugin identifier + // (possibly in a library-named directory) + + for (vector<string>::const_iterator pitr = paths.begin(); pitr != paths.end(); pitr++) + { + for (vector<string>::const_iterator eitr = rdf_exts.begin(); eitr != rdf_exts.end(); eitr++) + { + path = *pitr + "/" + pluginid + "." + *eitr; + cerr<<"Looking for "<<path<<endl; + // Check for file + if (fileExists(path)) + return path; - path = *pitr + "/" + libname + "/" + pluginid + "." + *eitr; // is dir delimiter "/" portable ? - cerr<<"Looking for "<<path<<endl; - // Check for file - if (fileExists(path)) - return path; - } - } - - cerr<<"Couldn't find description of plugin !"<<endl; - return ""; + path = *pitr + "/" + libname + "/" + pluginid + "." + *eitr; // is dir delimiter "/" portable ? + cerr<<"Looking for "<<path<<endl; + // Check for file + if (fileExists(path)) + return path; + } + } + + cerr<<"Couldn't find description of plugin !"<<endl; + return ""; } bool fileExists(string filepath) { - std::ifstream fin(filepath.c_str()); - return (fin != NULL); + std::ifstream fin(filepath.c_str()); + return (fin != NULL); } Modified: runner/trunk/RDFFeatureWriter.h =================================================================== --- runner/trunk/RDFFeatureWriter.h 2008-01-02 13:02:55 UTC (rev 915) +++ runner/trunk/RDFFeatureWriter.h 2008-01-04 10:44:16 UTC (rev 916) @@ -1,3 +1,4 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* * RDFFeatureWriter.h * runner @@ -22,19 +23,19 @@ class RDFFeatureWriter : public FeatureWriter { public: - RDFFeatureWriter(const string& catId, const string& dir); - virtual ~RDFFeatureWriter(); - virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); - static string getDescriptionFileForPlugin(const string& pluginid); - + RDFFeatureWriter(const string& catId, const string& dir); + virtual ~RDFFeatureWriter(); + virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); + static string getDescriptionFileForPlugin(const string& pluginid); + private: - string catalogueId; - string baseDir; - - map<string, RDFSinglePluginWriter*> featureWriters; - - bool newFeatureWriter(const string& trackid, const string& identifier); - bool replaceFeatureWriter(const string& trackid, const string& identifier); + string catalogueId; + string baseDir; + + map<string, RDFSinglePluginWriter*> featureWriters; + + bool newFeatureWriter(const string& trackid, const string& identifier); + bool replaceFeatureWriter(const string& trackid, const string& identifier); }; bool fileExists(string filepath); Modified: runner/trunk/RDFSinglePluginWriter.cpp =================================================================== --- runner/trunk/RDFSinglePluginWriter.cpp 2008-01-02 13:02:55 UTC (rev 915) +++ runner/trunk/RDFSinglePluginWriter.cpp 2008-01-04 10:44:16 UTC (rev 916) @@ -1,3 +1,4 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* * RDFSinglePluginWriter.cpp * vamphost @@ -22,280 +23,280 @@ RDFSinglePluginWriter::RDFSinglePluginWriter(const string& tid, const string& outfilename) : am_initialised(false), trackid(tid), fe_count(0) { - out = new ofstream(outfilename.c_str()); - if (!*out) - { - cerr << "ERROR RDFSinglePluginWriter(): can't open file " << outfilename << endl; -// out = cout; // ‽ - } + out = new ofstream(outfilename.c_str()); + if (!*out) + { + cerr << "ERROR RDFSinglePluginWriter(): can't open file " << outfilename << endl; +// out = cout; // ‽ + } } void RDFSinglePluginWriter::init(const string& trackid, const string& pluginid, const Plugin::OutputList& outputList) { - cerr << "RDFSinglePluginWriter init()"<<endl; - - // FIXME might not need all these namespaces - *out << "@prefix dc: <http://purl.org/dc/elements/1.1/> .\n" + cerr << "RDFSinglePluginWriter init()"<<endl; + + // FIXME might not need all these namespaces + *out << "@prefix dc: <http://purl.org/dc/elements/1.1/> .\n" << "@prefix mo: <http://purl.org/ontology/mo/> .\n" << "@prefix af: <http://purl.org/ontology/af/>.\n" << "@prefix event: <http://purl.org/NET/c4dm/event.owl#>.\n" << "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.\n" << "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.\n" - << "@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.\n" - << "@prefix timeline: <http://purl.org/NET/c4dm/timeline.owl#>.\n" - << "@prefix time: <http://www.w3.org/2006/time#>.\n" - << "@prefix : <>.\n\n" + << "@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.\n" + << "@prefix timeline: <http://purl.org/NET/c4dm/timeline.owl#>.\n" + << "@prefix time: <http://www.w3.org/2006/time#>.\n" + << "@prefix : <>.\n\n" << endl; - - /* - * Describe signal we're analysing (AudioFile, Signal, TimeLine, etc.) - */ - *out << "<"<<trackid<<"> a mo:AudioFile .\n\n" - << ":signal a mo:Signal ;\n" - << " mo:available_as <"<<trackid<<"> ;\n" - << " mo:time :sig_int .\n" - << ":sig_int a time:Interval ;\n" - << " timeline:onTimeLine :tl.\n"; - - /* - * Describe feature events and features. - */ - - string desc_path = RDFFeatureWriter::getDescriptionFileForPlugin(pluginid); - if (desc_path!="") - { + + /* + * Describe signal we're analysing (AudioFile, Signal, TimeLine, etc.) + */ + *out << "<"<<trackid<<"> a mo:AudioFile .\n\n" + << ":signal a mo:Signal ;\n" + << " mo:available_as <"<<trackid<<"> ;\n" + << " mo:time :sig_int .\n" + << ":sig_int a time:Interval ;\n" + << " timeline:onTimeLine :tl.\n"; + + /* + * Describe feature events and features. + */ + + string desc_path = RDFFeatureWriter::getDescriptionFileForPlugin(pluginid); + if (desc_path!="") + { - cerr<<"Got desc_path : "<<desc_path<<endl<<endl; - desc_path = "file://"+desc_path; - - librdf_world* world = librdf_new_world(); - librdf_world_open(world); + cerr<<"Got desc_path : "<<desc_path<<endl<<endl; + desc_path = "file://"+desc_path; + + librdf_world* world = librdf_new_world(); + librdf_world_open(world); - librdf_uri *uri = librdf_new_uri(world, (const unsigned char*)desc_path.c_str()); - librdf_storage* storage = librdf_new_storage(world, "memory", "test", NULL); - librdf_parser* parser = librdf_new_parser(world, "guess", NULL, NULL); - librdf_model* model = librdf_new_model(world, storage, NULL); + librdf_uri *uri = librdf_new_uri(world, (const unsigned char*)desc_path.c_str()); + librdf_storage* storage = librdf_new_storage(world, "memory", "test", NULL); + librdf_parser* parser = librdf_new_parser(world, "guess", NULL, NULL); + librdf_model* model = librdf_new_model(world, storage, NULL); - if(librdf_parser_parse_into_model(parser, uri, uri, model)) - cerr<<"Failed to parse RDF into model"<<endl; - librdf_free_parser(parser); - - // Find our plugin : + if(librdf_parser_parse_into_model(parser, uri, uri, model)) + cerr<<"Failed to parse RDF into model"<<endl; + librdf_free_parser(parser); + + // Find our plugin : - librdf_node* n_rdf_type = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); - librdf_node* n_rdfs_subClassOf = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.w3.org/2000/01/rdf-schema#subClassOf"); - librdf_node* n_vamp_Plugin = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.vamp-plugins.org/ontology/Plugin"); - librdf_node* n_vamp_identifier = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.vamp-plugins.org/ontology/identifier"); - librdf_node* n_vamp_computes = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.vamp-plugins.org/ontology/computes"); - librdf_node* n_vamp_computes_feature_type = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.vamp-plugins.org/ontology/computes_feature_type"); - librdf_node* n_vamp_computes_event_type = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.vamp-plugins.org/ontology/computes_event_type"); - librdf_node* n_af_Feature = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://purl.org/ontology/af/Feature"); - librdf_node* n_af_FeatureEvent = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://purl.org/ontology/af/FeatureEvent"); - - - librdf_iterator* itr = librdf_model_get_sources(model, n_rdf_type, n_vamp_Plugin); + librdf_node* n_rdf_type = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); + librdf_node* n_rdfs_subClassOf = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.w3.org/2000/01/rdf-schema#subClassOf"); + librdf_node* n_vamp_Plugin = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.vamp-plugins.org/ontology/Plugin"); + librdf_node* n_vamp_identifier = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.vamp-plugins.org/ontology/identifier"); + librdf_node* n_vamp_computes = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.vamp-plugins.org/ontology/computes"); + librdf_node* n_vamp_computes_feature_type = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.vamp-plugins.org/ontology/computes_feature_type"); + librdf_node* n_vamp_computes_event_type = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.vamp-plugins.org/ontology/computes_event_type"); + librdf_node* n_af_Feature = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://purl.org/ontology/af/Feature"); + librdf_node* n_af_FeatureEvent = librdf_new_node_from_uri_string(world, (const unsigned char*)"http://purl.org/ontology/af/FeatureEvent"); + + + librdf_iterator* itr = librdf_model_get_sources(model, n_rdf_type, n_vamp_Plugin); - librdf_node* n_plugin = NULL; - if(!itr || librdf_iterator_end(itr)) - cerr<<"No plugins found in the RDF file !"<<endl; - else - { - while(!librdf_iterator_end(itr)) - { - librdf_node* this_plugin = (librdf_node*)librdf_iterator_get_object(itr); + librdf_node* n_plugin = NULL; + if(!itr || librdf_iterator_end(itr)) + cerr<<"No plugins found in the RDF file !"<<endl; + else + { + while(!librdf_iterator_end(itr)) + { + librdf_node* this_plugin = (librdf_node*)librdf_iterator_get_object(itr); - // Check identifier : - librdf_node* n_identifier = librdf_model_get_target(model,this_plugin, n_vamp_identifier); - string identifier = (const char*)librdf_node_get_literal_value(n_identifier); - cerr<<"Found plugin w/id : "<<identifier<<endl; - if (identifier == pluginid) - n_plugin = this_plugin; - librdf_iterator_next(itr); + // Check identifier : + librdf_node* n_identifier = librdf_model_get_target(model,this_plugin, n_vamp_identifier); + string identifier = (const char*)librdf_node_get_literal_value(n_identifier); + cerr<<"Found plugin w/id : "<<identifier<<endl; + if (identifier == pluginid) + n_plugin = this_plugin; + librdf_iterator_next(itr); - } - librdf_free_iterator(itr); - } + } + librdf_free_iterator(itr); + } - if (!n_plugin) - cerr<<"Couldn't find plugin with matching identifier in RDF file !"<<endl; - - - /* - * Describe feature events and features. - */ + if (!n_plugin) + cerr<<"Couldn't find plugin with matching identifier in RDF file !"<<endl; + + + /* + * Describe feature events and features. + */ - for (unsigned int i=0; i < outputList.size(); i++) - { - Plugin::OutputDescriptor od = outputList[i]; - ODTypes.push_back(ODOT_UNKNOWN); - ODFeatureTypeURIs.push_back("<http://purl.org/ontology/af/Feature>"); - ODEventTypeURIs.push_back("<http://purl.org/ontology/af/FeatureEvent>"); + for (unsigned int i=0; i < outputList.size(); i++) + { + Plugin::OutputDescriptor od = outputList[i]; + ODTypes.push_back(ODOT_UNKNOWN); + ODFeatureTypeURIs.push_back("<http://purl.org/ontology/af/Feature>"); + ODEventTypeURIs.push_back("<http://purl.org/ontology/af/FeatureEvent>"); - // Find the RDF about this output descriptor + // Find the RDF about this output descriptor - librdf_node* n_od = librdf_model_get_source(model, n_vamp_identifier, librdf_new_node_from_literal(world, (const unsigned char*)od.identifier.c_str(), NULL, 0)); - if (!n_od) - { - cerr<<"Couldn't find RDF description of output descriptor "<<od.identifier<<" !"<<endl; - ODTypes[i] = ODOT_UNKNOWN; - } - else - { - // Does it compute features, events, or both ? - itr = librdf_model_get_targets(model, n_od, n_vamp_computes_feature_type); - if (!itr || librdf_iterator_end(itr)) - ODTypes[i] = ODOT_UNKNOWN; - else - { - while(!librdf_iterator_end(itr)) - { - librdf_node* n_computes_obj = (librdf_node*)librdf_iterator_get_object(itr); + librdf_node* n_od = librdf_model_get_source(model, n_vamp_identifier, librdf_new_node_from_literal(world, (const unsigned char*)od.identifier.c_str(), NULL, 0)); + if (!n_od) + { + cerr<<"Couldn't find RDF description of output descriptor "<<od.identifier<<" !"<<endl; + ODTypes[i] = ODOT_UNKNOWN; + } + else + { + // Does it compute features, events, or both ? + itr = librdf_model_get_targets(model, n_od, n_vamp_computes_feature_type); + if (!itr || librdf_iterator_end(itr)) + ODTypes[i] = ODOT_UNKNOWN; + else + { + while(!librdf_iterator_end(itr)) + { + librdf_node* n_computes_obj = (librdf_node*)librdf_iterator_get_object(itr); - if (ODTypes[i] == ODOT_BOTH || ODTypes[i] == ODOT_FEATURE) - cerr<<"Too many vamp:computes_feature_type statements for output descriptor "<<od.identifier<<" !"<<endl; - else - { - if (ODTypes[i] == ODOT_UNKNOWN) - ODTypes[i] = ODOT_FEATURE; - else - ODTypes[i] = ODOT_BOTH; + if (ODTypes[i] == ODOT_BOTH || ODTypes[i] == ODOT_FEATURE) + cerr<<"Too many vamp:computes_feature_type statements for output descriptor "<<od.identifier<<" !"<<endl; + else + { + if (ODTypes[i] == ODOT_UNKNOWN) + ODTypes[i] = ODOT_FEATURE; + else + ODTypes[i] = ODOT_BOTH; - ODFeatureTypeURIs[i] = "<"+(string)(const char*)librdf_uri_as_string(librdf_node_get_uri(n_computes_obj))+">"; - cerr<<"Setting ODTypes["<<i<<"]="<<ODTypes[i]<<", ODFeatureTypeURIs["<<i<<"]="<<ODFeatureTypeURIs[i]<<"."<<endl; - } + ODFeatureTypeURIs[i] = "<"+(string)(const char*)librdf_uri_as_string(librdf_node_get_uri(n_computes_obj))+">"; + cerr<<"Setting ODTypes["<<i<<"]="<<ODTypes[i]<<", ODFeatureTypeURIs["<<i<<"]="<<ODFeatureTypeURIs[i]<<"."<<endl; + } - librdf_iterator_next(itr); - } + librdf_iterator_next(itr); + } - } - librdf_free_iterator(itr); + } + librdf_free_iterator(itr); - itr = librdf_model_get_targets(model, n_od, n_vamp_computes_event_type); - if (itr && !librdf_iterator_end(itr)) - { - while(!librdf_iterator_end(itr)) - { - librdf_node* n_computes_obj = (librdf_node*)librdf_iterator_get_object(itr); + itr = librdf_model_get_targets(model, n_od, n_vamp_computes_event_type); + if (itr && !librdf_iterator_end(itr)) + { + while(!librdf_iterator_end(itr)) + { + librdf_node* n_computes_obj = (librdf_node*)librdf_iterator_get_object(itr); - if (ODTypes[i] == ODOT_BOTH || ODTypes[i] == ODOT_EVENT) - cerr<<"Too many vamp:computes_event_type statements for output descriptor "<<od.identifier<<" !"<<endl; - else - { - if (ODTypes[i] == ODOT_UNKNOWN) - ODTypes[i] = ODOT_EVENT; - else - ODTypes[i] = ODOT_BOTH; - ODEventTypeURIs[i] = "<"+(string)(const char*)librdf_uri_as_string(librdf_node_get_uri(n_computes_obj))+">"; - cerr<<"Setting ODTypes["<<i<<"]="<<ODTypes[i]<<", ODEventTypeURIs["<<i<<"]="<<ODEventTypeURIs[i]<<"."<<endl; - } - librdf_iterator_next(itr); - } - } - librdf_free_iterator(itr); - } + if (ODTypes[i] == ODOT_BOTH || ODTypes[i] == ODOT_EVENT) + cerr<<"Too many vamp:computes_event_type statements for output descriptor "<<od.identifier<<" !"<<endl; + else + { + if (ODTypes[i] == ODOT_UNKNOWN) + ODTypes[i] = ODOT_EVENT; + else + ODTypes[i] = ODOT_BOTH; + ODEventTypeURIs[i] = "<"+(string)(const char*)librdf_uri_as_string(librdf_node_get_uri(n_computes_obj))+">"; + cerr<<"Setting ODTypes["<<i<<"]="<<ODTypes[i]<<", ODEventTypeURIs["<<i<<"]="<<ODEventTypeURIs[i]<<"."<<endl; + } + librdf_iterator_next(itr); + } + } + librdf_free_iterator(itr); + } - /* - * Fallback to local names if accompanying RDF doesn't satisfy - */ - if (ODTypes[i] == ODOT_UNKNOWN) - { - cout << ":fetype_" << od.identifier << " rdfs:subClassOf af:FeatureEvent;\n" - << " dc:title \"" << od.name << "\"; \n" - << " dc:description \"" << od.description << " event\".\n" - << endl; - ODEventTypeURIs[i] = ":fetype_" + od.identifier; + /* + * Fallback to local names if accompanying RDF doesn't satisfy + */ + if (ODTypes[i] == ODOT_UNKNOWN) + { + cout << ":fetype_" << od.identifier << " rdfs:subClassOf af:FeatureEvent;\n" + << " dc:title \"" << od.name << "\"; \n" + << " dc:description \"" << od.description << " event\".\n" + << endl; + ODEventTypeURIs[i] = ":fetype_" + od.identifier; - cout << ":ftype_" << od.identifier << " rdfs:subClassOf af:Feature;\n" - << " dc:title \"" << od.name << "\"; \n" - << " dc:description \"" << od.description << "\";\n" - << " dc:format \"" << od.unit << "\".\n\n" - << endl; - ODFeatureTypeURIs[i] = ":ftype_" + od.identifier; - } - } - - /* - * TODO : Add any relevant info about the Transform being used (eg. frame size, hop size) - */ + cout << ":ftype_" << od.identifier << " rdfs:subClassOf af:Feature;\n" + << " dc:title \"" << od.name << "\"; \n" + << " dc:description \"" << od.description << "\";\n" + << " dc:format \"" << od.unit << "\".\n\n" + << endl; + ODFeatureTypeURIs[i] = ":ftype_" + od.identifier; + } + } + + /* + * TODO : Add any relevant info about the Transform being used (eg. frame size, hop size) + */ - // I'm gonna presume freeing the world frees nodes too - otherwise we're gonna need these and more : - // librdf_free_node(n_rdf_type); - // librdf_free_node(n_vamp_plugin); + // I'm gonna presume freeing the world frees nodes too - otherwise we're gonna need these and more : + // librdf_free_node(n_rdf_type); + // librdf_free_node(n_vamp_plugin); - librdf_free_uri(uri); - librdf_free_model(model); - librdf_free_storage(storage); - librdf_free_world(world); - } - - am_initialised = true; + librdf_free_uri(uri); + librdf_free_model(model); + librdf_free_storage(storage); + librdf_free_world(world); + } + + am_initialised = true; } void RDFSinglePluginWriter::write(const string& trackid, const string& pluginid, const Plugin::OutputList& outputList, const Plugin::FeatureSet& featureSet) { - if (!am_initialised) - init(trackid, pluginid, outputList); + if (!am_initialised) + init(trackid, pluginid, outputList); - if (featureSet.size() == 0) - return; - - // iterate through FeatureLists - //cerr << featureSet.size() << " featurelists in set" << endl; - for (map<int, Plugin::FeatureList>::const_iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) - { - Plugin::FeatureList featureList = iter->second; - Plugin::OutputDescriptor od = outputList[iter->first]; - for (unsigned int i = 0; i < featureList.size(); ++i) - { - Plugin::Feature feature = featureList[i]; - *out << ":fe_" << fe_count << " rdf:type " << ODEventTypeURIs[iter->first] << ";\n"; - if (feature.label.length() > 0) - *out<< " rdfs:label \"" << feature.label << "\";\n"; // Might want to rethink this - - /* - * Add timestamp - * In current design this is handled by the rebuffering, s.t. all outputs are VariableSampleRate and have a valid timestamp. - */ - if (od.sampleType == Plugin::OutputDescriptor::VariableSampleRate) - { + if (featureSet.size() == 0) + return; + + // iterate through FeatureLists + //cerr << featureSet.size() << " featurelists in set" << endl; + for (map<int, Plugin::FeatureList>::const_iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) + { + Plugin::FeatureList featureList = iter->second; + Plugin::OutputDescriptor od = outputList[iter->first]; + for (unsigned int i = 0; i < featureList.size(); ++i) + { + Plugin::Feature feature = featureList[i]; + *out << ":fe_" << fe_count << " rdf:type " << ODEventTypeURIs[iter->first] << ";\n"; + if (feature.label.length() > 0) + *out<< " rdfs:label \"" << feature.label << "\";\n"; // Might want to rethink this + + /* + * Add timestamp + * In current design this is handled by the rebuffering, s.t. all outputs are VariableSampleRate and have a valid timestamp. + */ + if (od.sampleType == Plugin::OutputDescriptor::VariableSampleRate) + { *out<< " event:time [ rdf:type time:Instant;\n" //location of the event in time << " time:onTimeLine " << timelineURI << ";\n" << " time:atDuration \"PT" << fea... [truncated message content] |
From: <ca...@us...> - 2008-03-13 14:28:00
|
Revision: 1009 http://sv1.svn.sourceforge.net/sv1/?rev=1009&view=rev Author: cannam Date: 2008-03-13 07:27:58 -0700 (Thu, 13 Mar 2008) Log Message: ----------- * Update to build with current SV code. The aim is to make runner able to build without a QtGui dependency, but the progress reporting logic for file import is currently impeding that one. Modified Paths: -------------- runner/trunk/FeatureExtractionManager.cpp runner/trunk/FeatureExtractionManager.h runner/trunk/RDFFeatureWriter.cpp runner/trunk/main.cpp runner/trunk/runner.pro Modified: runner/trunk/FeatureExtractionManager.cpp =================================================================== --- runner/trunk/FeatureExtractionManager.cpp 2008-03-13 14:06:03 UTC (rev 1008) +++ runner/trunk/FeatureExtractionManager.cpp 2008-03-13 14:27:58 UTC (rev 1009) @@ -27,7 +27,7 @@ #include "data/fileio/AudioFileReader.h" #include "data/fileio/AudioFileReaderFactory.h" #include "base/TempDirectory.h" -#include "plugin/transform/TransformFactory.h" +#include "transform/TransformFactory.h" #include "FeatureWriter.h" #include "FeatureExtractionManager.h" Modified: runner/trunk/FeatureExtractionManager.h =================================================================== --- runner/trunk/FeatureExtractionManager.h 2008-03-13 14:06:03 UTC (rev 1008) +++ runner/trunk/FeatureExtractionManager.h 2008-03-13 14:27:58 UTC (rev 1009) @@ -18,7 +18,7 @@ using std::string; #include <vamp-sdk/Plugin.h> -#include <plugin/transform/Transform.h> +#include <transform/Transform.h> class FeatureWriter; Modified: runner/trunk/RDFFeatureWriter.cpp =================================================================== --- runner/trunk/RDFFeatureWriter.cpp 2008-03-13 14:06:03 UTC (rev 1008) +++ runner/trunk/RDFFeatureWriter.cpp 2008-03-13 14:27:58 UTC (rev 1009) @@ -87,6 +87,8 @@ string path = ""; vector<string> paths = PluginHostAdapter::getPluginPath(); + paths.push_back("."); //!!! + vector<string> rdf_exts; rdf_exts.push_back("rdf"); rdf_exts.push_back("RDF"); rdf_exts.push_back("n3"); rdf_exts.push_back("N3"); Modified: runner/trunk/main.cpp =================================================================== --- runner/trunk/main.cpp 2008-03-13 14:06:03 UTC (rev 1008) +++ runner/trunk/main.cpp 2008-03-13 14:27:58 UTC (rev 1009) @@ -14,6 +14,7 @@ #include <QCoreApplication> +#include <QStringList> using std::cout; using std::endl; using std::vector; Modified: runner/trunk/runner.pro =================================================================== --- runner/trunk/runner.pro 2008-03-13 14:06:03 UTC (rev 1008) +++ runner/trunk/runner.pro 2008-03-13 14:27:58 UTC (rev 1009) @@ -6,19 +6,21 @@ CONFIG += sv qt thread warn_on stl rtti exceptions QT += xml network +#QT -= gui TARGET = runner DEPENDPATH += . ../sonic-visualiser i18n main INCLUDEPATH += . ../sonic-visualiser main -LIBPATH = ../sonic-visualiser/audioio ../sonic-visualiser/data ../sonic-visualiser/plugin ../sonic-visualiser/base ../sonic-visualiser/system $$LIBPATH +LIBPATH = ../sonic-visualiser/audioio ../sonic-visualiser/data ../sonic-visualiser/plugin ../sonic-visualiser/transform ../sonic-visualiser/base ../sonic-visualiser/system $$LIBPATH contains(DEFINES, BUILD_STATIC):LIBS -= -ljack -LIBS = -lsvaudioio -lsvdata -lsvplugin -lsvbase -lsvsystem -lrdf $$LIBS +LIBS = -lsvaudioio -lsvdata -lsvtransform -lsvplugin -lsvbase -lsvsystem -lrdf $$LIBS PRE_TARGETDEPS += ../sonic-visualiser/audioio/libsvaudioio.a \ ../sonic-visualiser/data/libsvdata.a \ + ../sonic-visualiser/transform/libsvtransform.a \ ../sonic-visualiser/plugin/libsvplugin.a \ ../sonic-visualiser/base/libsvbase.a \ ../sonic-visualiser/system/libsvsystem.a This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ca...@us...> - 2008-04-03 15:46:50
|
Revision: 1040 http://sv1.svn.sourceforge.net/sv1/?rev=1040&view=rev Author: cannam Date: 2008-04-03 08:46:46 -0700 (Thu, 03 Apr 2008) Log Message: ----------- * Add CSV output, fix various bugs, add support for playlists and basedir Modified Paths: -------------- runner/trunk/FeatureExtractionManager.cpp runner/trunk/FeatureExtractionManager.h runner/trunk/FeatureWriter.h runner/trunk/FeatureWriterFactory.cpp runner/trunk/RDFFeatureWriter.cpp runner/trunk/RDFFeatureWriter.h runner/trunk/main.cpp runner/trunk/runner.pro Added Paths: ----------- runner/trunk/CSVFeatureWriter.cpp runner/trunk/CSVFeatureWriter.h runner/trunk/FileFeatureWriter.cpp runner/trunk/FileFeatureWriter.h Added: runner/trunk/CSVFeatureWriter.cpp =================================================================== --- runner/trunk/CSVFeatureWriter.cpp (rev 0) +++ runner/trunk/CSVFeatureWriter.cpp 2008-04-03 15:46:46 UTC (rev 1040) @@ -0,0 +1,95 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "CSVFeatureWriter.h" + +#include <iostream> + +#include <QRegExp> +#include <QTextStream> + +using namespace std; +using namespace Vamp; + +CSVFeatureWriter::CSVFeatureWriter() : + FileFeatureWriter(SupportOneFilePerTrackTransform, + "csv"), + m_separator(",") +{ +} + +CSVFeatureWriter::~CSVFeatureWriter() +{ +} + +CSVFeatureWriter::ParameterList +CSVFeatureWriter::getSupportedParameters() const +{ + ParameterList pl = FileFeatureWriter::getSupportedParameters(); + Parameter p; + + p.name = "separator"; + p.description = "Column separator for output. Default is \",\" (comma)."; + p.hasArg = true; + pl.push_back(p); + + return pl; +} + +void +CSVFeatureWriter::setParameters(map<string, string> ¶ms) +{ + FileFeatureWriter::setParameters(params); + + cerr << "CSVFeatureWriter::setParameters" << endl; + for (map<string, string>::iterator i = params.begin(); + i != params.end(); ++i) { + cerr << i->first << " -> " << i->second << endl; + if (i->first == "separator") { + m_separator = i->second.c_str(); + } + } +} + +void +CSVFeatureWriter::write(QString trackId, + TransformId transformId, + const Plugin::OutputDescriptor& output, + const Plugin::FeatureList& features) +{ + // Select appropriate output file for our track/transform + // combination + + QTextStream *sptr = getOutputStream(trackId, transformId); + if (!sptr) return; //!!! this is probably better handled with an exception + + QTextStream &stream = *sptr; + + for (unsigned int i = 0; i < features.size(); ++i) { + + QString timestamp = features[i].timestamp.toString().c_str(); + timestamp.replace(QRegExp("^ +"), ""); + + stream << timestamp; + + for (unsigned int j = 0; j < features[i].values.size(); ++j) { + stream << m_separator << features[i].values[j]; + } + + stream << "\n"; + } +} + + Added: runner/trunk/CSVFeatureWriter.h =================================================================== --- runner/trunk/CSVFeatureWriter.h (rev 0) +++ runner/trunk/CSVFeatureWriter.h 2008-04-03 15:46:46 UTC (rev 1040) @@ -0,0 +1,51 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _CSV_FEATURE_WRITER_H_ +#define _CSV_FEATURE_WRITER_H_ + +#include <string> +#include <map> +#include <set> + +#include <QString> + +#include "FileFeatureWriter.h" + +using std::string; +using std::map; + +class QTextStream; +class QFile; + +class CSVFeatureWriter : public FileFeatureWriter +{ +public: + CSVFeatureWriter(); + virtual ~CSVFeatureWriter(); + + virtual ParameterList getSupportedParameters() const; + virtual void setParameters(map<string, string> ¶ms); + + virtual void write(QString trackid, + TransformId transformId, + const Vamp::Plugin::OutputDescriptor &output, + const Vamp::Plugin::FeatureList &features); + +private: + QString m_separator; +}; + +#endif Modified: runner/trunk/FeatureExtractionManager.cpp =================================================================== --- runner/trunk/FeatureExtractionManager.cpp 2008-04-03 08:30:25 UTC (rev 1039) +++ runner/trunk/FeatureExtractionManager.cpp 2008-04-03 15:46:46 UTC (rev 1040) @@ -32,6 +32,7 @@ #include "data/fileio/FileSource.h" #include "data/fileio/AudioFileReader.h" #include "data/fileio/AudioFileReaderFactory.h" +#include "data/fileio/PlaylistFileReader.h" #include "base/TempDirectory.h" #include "base/ProgressPrinter.h" #include "transform/TransformFactory.h" @@ -41,8 +42,13 @@ #include <QTextStream> #include <QFile> +#include <QFileInfo> -FeatureExtractionManager::FeatureExtractionManager() +FeatureExtractionManager::FeatureExtractionManager() : + // We can read using an arbitrary fixed block size -- + // PluginBufferingAdapter handles this for us. It's likely to be + // quicker to use larger sizes than smallish ones like 1024 + m_blockSize(16384) { } @@ -119,7 +125,32 @@ plugin = new PluginBufferingAdapter(plugin); plugin = new PluginChannelAdapter(plugin); - cerr << "NOTE: Loaded plugin for transform \"" + if (!plugin->initialise(m_channels, m_blockSize, m_blockSize)) { + + cerr << "ERROR: Plugin initialise (channels = " << m_channels << ", stepSize = " << m_blockSize << ", blockSize = " << m_blockSize << ") failed." << endl; + + //!!! TODO: + // decide how to handle this error... + } + + Plugin::OutputList outputs = plugin->getOutputDescriptors(); + for (int i = 0; i < outputs.size(); ++i) { + + m_pluginOutputs[plugin][outputs[i].identifier] = outputs[i]; + m_pluginOutputIndices[outputs[i].identifier] = i; + + // As a special case, the empty string refers to the first + // (default) output -- this is so we can specify + // transforms with just soname:plugin and leave the output + // hanging + + if (i == 0) { + m_pluginOutputs[plugin][""] = outputs[i]; + m_pluginOutputIndices[""] = i; + } + } + + cerr << "NOTE: Loaded and initialised plugin for transform \"" << transform.getIdentifier().toStdString() << "\"" << endl; } @@ -178,6 +209,21 @@ source.waitForData(); + if (QFileInfo(audioSource).suffix().toLower() == "m3u") { + PlaylistFileReader reader(source); + if (reader.isOK()) { + vector<QString> files = reader.load(); + for (int i = 0; i < files.size(); ++i) { + extractFeatures(files[i]); + } + return; + } else { + cerr << "ERROR: Playlist \"" << audioSource.toStdString() + << "\" could not be opened" << endl; + exit(1); + } + } + AudioFileReader *reader = AudioFileReaderFactory::createReader(source, m_sampleRate, &printer); @@ -187,14 +233,6 @@ exit(1); } - //!!! handle plugin reset when more than one file is processed - - // We can read using an arbitrary fixed block size -- - // PluginBufferingAdapter handles this for us. It's likely to be - // quicker to use larger sizes than smallish ones like 1024 - int blockSize = 16384; - int stepSize = blockSize; - size_t channels = reader->getChannelCount(); // reject file if it has too few channels, plugin will handle if it has too many @@ -207,44 +245,10 @@ // allocate audio buffers float **data = new float *[m_channels]; - for (size_t c = 0; c < m_channels; ++c) - data[c] = new float[blockSize]; + for (size_t c = 0; c < m_channels; ++c) { + data[c] = new float[m_blockSize]; + } - for (PluginMap::iterator pi = m_plugins.begin(); - pi != m_plugins.end(); ++pi) { - - Plugin *plugin = pi->first; - - int minch = plugin->getMinChannelCount(); - int maxch = plugin->getMaxChannelCount(); - cerr << "Plugin accepts " << minch << " -> " << maxch << " channel(s)" << endl; - cerr << "Sound file has " << m_channels << " (will mix/augment if necessary)" << endl; - - if (!plugin->initialise(m_channels, stepSize, blockSize)) { - cerr << "ERROR: Plugin initialise (channels = " << m_channels << ", stepSize = " << stepSize << ", blockSize = " << blockSize << ") failed." << endl; - - //!!! TODO: - // decide how to handle this error... - } - - Plugin::OutputList outputs = plugin->getOutputDescriptors(); - for (int i = 0; i < outputs.size(); ++i) { - - m_pluginOutputs[plugin][outputs[i].identifier] = outputs[i]; - m_pluginOutputIndices[outputs[i].identifier] = i; - - // As a special case, the empty string refers to the first - // (default) output -- this is so we can specify - // transforms with just soname:plugin and leave the output - // hanging - - if (i == 0) { - m_pluginOutputs[plugin][""] = outputs[i]; - m_pluginOutputIndices[""] = i; - } - } - } - size_t frameCount = reader->getFrameCount(); cerr << "file has " << frameCount << " frames" << endl; @@ -254,6 +258,8 @@ Plugin *plugin = pi->first; + plugin->reset(); + for (TransformWriterMap::iterator ti = pi->second.begin(); ti != pi->second.end(); ++ti) { @@ -281,15 +287,15 @@ // for feature extraction - this code just process // the whole file - for (size_t i = 0; i < frameCount; i += stepSize) { + for (size_t i = 0; i < frameCount; i += m_blockSize) { //!!! inefficient, although much of the inefficiency may be // susceptible to optimisation SampleBlock frames; - reader->getInterleavedFrames(i, blockSize, frames); + reader->getInterleavedFrames(i, m_blockSize, frames); - for (size_t j = 0; j < blockSize; ++j) { + for (size_t j = 0; j < m_blockSize; ++j) { for (size_t c = 0; c < m_channels; ++c) { size_t index = j * m_channels + c; if (index < frames.size()) { Modified: runner/trunk/FeatureExtractionManager.h =================================================================== --- runner/trunk/FeatureExtractionManager.h 2008-04-03 08:30:25 UTC (rev 1039) +++ runner/trunk/FeatureExtractionManager.h 2008-04-03 15:46:46 UTC (rev 1040) @@ -82,6 +82,7 @@ Vamp::Plugin *, const Vamp::Plugin::FeatureSet &); + int m_blockSize; int m_sampleRate; int m_channels; Modified: runner/trunk/FeatureWriter.h =================================================================== --- runner/trunk/FeatureWriter.h 2008-04-03 08:30:25 UTC (rev 1039) +++ runner/trunk/FeatureWriter.h 2008-04-03 15:46:46 UTC (rev 1040) @@ -49,6 +49,8 @@ return; } + // may throw FailedToOpenFile or other exceptions + virtual void write(QString trackid, TransformId transformId, const Vamp::Plugin::OutputDescriptor &output, Modified: runner/trunk/FeatureWriterFactory.cpp =================================================================== --- runner/trunk/FeatureWriterFactory.cpp 2008-04-03 08:30:25 UTC (rev 1039) +++ runner/trunk/FeatureWriterFactory.cpp 2008-04-03 15:46:46 UTC (rev 1040) @@ -19,6 +19,7 @@ #include "DefaultFeatureWriter.h" #include "RDFFeatureWriter.h" #include "AudioDBFeatureWriter.h" +#include "CSVFeatureWriter.h" set<string> FeatureWriterFactory::getWriterTags() @@ -27,7 +28,7 @@ tags.insert("default"); tags.insert("rdf"); tags.insert("audiodb"); -// tags.insert("csv"); + tags.insert("csv"); return tags; } @@ -40,6 +41,8 @@ return new RDFFeatureWriter(); } else if (tag == "audiodb") { return new AudioDBFeatureWriter(); + } else if (tag == "csv") { + return new CSVFeatureWriter(); } return 0; Added: runner/trunk/FileFeatureWriter.cpp =================================================================== --- runner/trunk/FileFeatureWriter.cpp (rev 0) +++ runner/trunk/FileFeatureWriter.cpp 2008-04-03 15:46:46 UTC (rev 1040) @@ -0,0 +1,231 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "FileFeatureWriter.h" + +#include "base/Exceptions.h" + +#include <QTextStream> +#include <QFile> +#include <QFileInfo> +#include <QUrl> +#include <QDir> + +using namespace std; +using namespace Vamp; + +FileFeatureWriter::FileFeatureWriter(int support, + QString extension) : + m_support(support), + m_extension(extension), + m_manyFiles(false), + m_append(false), + m_force(false) +{ + if (!(m_support & SupportOneFilePerTrack)) { + if (m_support & SupportOneFilePerTrackTransform) { + m_manyFiles = true; + } else if (m_support & SupportOneFileTotal) { + m_singleFileName = QString("output.%1").arg(m_extension); + } else { + cerr << "FileFeatureWriter::FileFeatureWriter: ERROR: Invalid support specification " << support << endl; + } + } +} + +FileFeatureWriter::~FileFeatureWriter() +{ + while (!m_streams.empty()) { + m_streams.begin()->second->flush(); + delete m_streams.begin()->second; + m_streams.erase(m_streams.begin()); + } + while (!m_files.empty()) { + delete m_files.begin()->second; + m_files.erase(m_files.begin()); + } +} + +FileFeatureWriter::ParameterList +FileFeatureWriter::getSupportedParameters() const +{ + ParameterList pl; + Parameter p; + + p.name = "basedir"; + p.description = "Base output directory path. (The default is the same directory as the input file.)"; + p.hasArg = true; + pl.push_back(p); + + if (m_support & SupportOneFilePerTrackTransform && + m_support & SupportOneFilePerTrack) { + p.name = "many-files"; + p.description = "Create a separate output file for every combination of input file and transform. The output file names will be based on the input file names. (The default is to create one output file per input audio file, and write all transform results for that input into it.)"; + p.hasArg = false; + pl.push_back(p); + } + + if (m_support & SupportOneFileTotal) { + if (m_support & ~SupportOneFileTotal) { // not only option + p.name = "one-file"; + p.description = "Write all transform results for all input files into the single named output file."; + p.hasArg = true; + pl.push_back(p); + } + } + + p.name = "force"; + p.description = "If an output file already exists, overwrite it."; + p.hasArg = false; + pl.push_back(p); + + p.name = "append"; + p.description = "If an output file already exists, append data to it."; + p.hasArg = false; + pl.push_back(p); + + return pl; +} + +void +FileFeatureWriter::setParameters(map<string, string> ¶ms) +{ + cerr << "FileFeatureWriter::setParameters" << endl; + for (map<string, string>::iterator i = params.begin(); + i != params.end(); ++i) { + cerr << i->first << " -> " << i->second << endl; + if (i->first == "basedir") { + m_baseDir = i->second.c_str(); + } else if (i->first == "many-files") { + if (m_support & SupportOneFilePerTrackTransform && + m_support & SupportOneFilePerTrack) { + if (m_singleFileName != "") { + cerr << "FileFeatureWriter::setParameters: WARNING: Both one-file and many-files parameters provided, ignoring many-files" << endl; + } else { + m_manyFiles = true; + } + } + } else if (i->first == "one-file") { + if (m_support & SupportOneFileTotal) { + if (m_support & ~SupportOneFileTotal) { // not only option + if (m_manyFiles) { + cerr << "FileFeatureWriter::setParameters: WARNING: Both many-files and one-file parameters provided, ignoring one-file" << endl; + } else { + m_singleFileName = i->second.c_str(); + } + } + } + } else if (i->first == "append") { + m_append = true; + } else if (i->first == "force") { + m_force = true; + } + } +} + +QString FileFeatureWriter::getOutputFilename(QString trackId, + TransformId transformId) +{ + if (m_singleFileName != "") { + if (QFileInfo(m_singleFileName).exists() && !(m_force || m_append)) { + cerr << "FileFeatureWriter: ERROR: Specified output file \"" << m_singleFileName.toStdString() << "\" exists and neither force nor append flag is specified -- not overwriting" << endl; + return ""; + } + return m_singleFileName; + } + + QUrl url(trackId); + QString scheme = url.scheme().toLower(); + bool local = (scheme == "" || scheme == "file" || scheme.length() == 1); + + QString dirname, basename; + QString infilename = url.toLocalFile(); + basename = QFileInfo(infilename).baseName(); + + if (m_baseDir != "") dirname = QFileInfo(m_baseDir).absoluteFilePath(); + else if (local) dirname = QFileInfo(infilename).absolutePath(); + else dirname = QDir::currentPath(); + + QString filename; + + if (m_manyFiles && transformId != "") { + filename = QString("%1:%2.%3").arg(basename).arg(transformId).arg(m_extension); + } else { + filename = QString("%1.%2").arg(basename).arg(m_extension); + } + + filename = QDir(dirname).filePath(filename); + + if (QFileInfo(filename).exists() && !(m_force || m_append)) { + cerr << "FileFeatureWriter: ERROR: Output file \"" << filename.toStdString() << "\" exists (for input file or URL \"" << trackId.toStdString() << "\" and transform \"" << transformId.toStdString() << "\") and neither force nor append is specified -- not overwriting" << endl; + return ""; + } + + return filename; +} + + +QFile *FileFeatureWriter::getOutputFile(QString trackId, + TransformId transformId) +{ + pair<QString, TransformId> key; + + if (m_singleFileName != "") { + key = pair<QString, TransformId>("", ""); + } else if (m_manyFiles) { + key = pair<QString, TransformId>(trackId, transformId); + } else { + key = pair<QString, TransformId>(trackId, ""); + } + + if (m_files.find(key) == m_files.end()) { + + QString filename = getOutputFilename(trackId, transformId); + + cerr << "FileFeatureWriter: NOTE: Using output filename \"" + << filename.toStdString() << "\"" << endl; + + QFile *file = new QFile(filename); + QIODevice::OpenMode mode = (QIODevice::WriteOnly); + if (m_append) mode |= QIODevice::Append; + + if (!file->open(mode)) { + cerr << "FileFeatureWriter: ERROR: Failed to open output file \"" << filename.toStdString() + << "\" for writing" << endl; + delete file; + m_files[key] = 0; + throw FailedToOpenFile(filename); + } + + m_files[key] = file; + } + + return m_files[key]; +} + + +QTextStream *FileFeatureWriter::getOutputStream(QString trackId, + TransformId transformId) +{ + QFile *file = getOutputFile(trackId, transformId); + if (!file) return 0; + + if (m_streams.find(file) == m_streams.end()) { + m_streams[file] = new QTextStream(file); + } + + return m_streams[file]; +} + Added: runner/trunk/FileFeatureWriter.h =================================================================== --- runner/trunk/FileFeatureWriter.h (rev 0) +++ runner/trunk/FileFeatureWriter.h 2008-04-03 15:46:46 UTC (rev 1040) @@ -0,0 +1,69 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _FILE_FEATURE_WRITER_H_ +#define _FILE_FEATURE_WRITER_H_ + +#include <string> +#include <map> +#include <set> + +#include "FeatureWriter.h" + +using std::string; +using std::map; +using std::set; +using std::pair; + +class QTextStream; +class QFile; + +class FileFeatureWriter : public FeatureWriter +{ +public: + virtual ~FileFeatureWriter(); + + virtual ParameterList getSupportedParameters() const; + virtual void setParameters(map<string, string> ¶ms); + +protected: + enum FileWriteSupport { + SupportOneFilePerTrackTransform = 1, + SupportOneFilePerTrack = 2, + SupportOneFileTotal = 4 + }; + + FileFeatureWriter(int support, QString extension); + + typedef pair<QString, TransformId> TrackTransformPair; + typedef map<TrackTransformPair, QFile *> FileMap; + typedef map<QFile *, QTextStream *> FileStreamMap; + FileMap m_files; + FileStreamMap m_streams; + + QString getOutputFilename(QString, TransformId); + QFile *getOutputFile(QString, TransformId); + QTextStream *getOutputStream(QString, TransformId); + + int m_support; + QString m_extension; + QString m_baseDir; + bool m_manyFiles; + QString m_singleFileName; + bool m_append; + bool m_force; +}; + +#endif Modified: runner/trunk/RDFFeatureWriter.cpp =================================================================== --- runner/trunk/RDFFeatureWriter.cpp 2008-04-03 08:30:25 UTC (rev 1039) +++ runner/trunk/RDFFeatureWriter.cpp 2008-04-03 15:46:46 UTC (rev 1040) @@ -21,18 +21,17 @@ #include "RDFFeatureWriter.h" #include <QTextStream> -#include <QFile> -#include <QFileInfo> #include <QUrl> -#include <QDir> +#include <QRegExp> using namespace std; using namespace Vamp; RDFFeatureWriter::RDFFeatureWriter() : - m_manyFiles(false), - m_append(false), - m_force(false), + FileFeatureWriter(SupportOneFilePerTrackTransform | + SupportOneFilePerTrack | + SupportOneFileTotal, + "n3"), m_plain(false), m_count(0) { @@ -40,48 +39,14 @@ RDFFeatureWriter::~RDFFeatureWriter() { - while (!m_streams.empty()) { - m_streams.begin()->second->flush(); - delete m_streams.begin()->second; - m_streams.erase(m_streams.begin()); - } - while (!m_files.empty()) { - delete m_files.begin()->second; - m_files.erase(m_files.begin()); - } } RDFFeatureWriter::ParameterList RDFFeatureWriter::getSupportedParameters() const { - ParameterList pl; + ParameterList pl = FileFeatureWriter::getSupportedParameters(); Parameter p; - p.name = "basedir"; - p.description = "Base output directory path. (The default is the same directory as the input file.)"; - p.hasArg = true; - pl.push_back(p); - - p.name = "many-files"; - p.description = "Create a separate output file for every combination of input file and transform. The output file names will be based on the input file names. (The default is to create one output file per input audio file, and write all transform results for that input into it.)"; - p.hasArg = false; - pl.push_back(p); - - p.name = "one-file"; - p.description = "Write all transform results for all input files into the single named output file."; - p.hasArg = true; - pl.push_back(p); - - p.name = "force"; - p.description = "If an output file already exists, overwrite it."; - p.hasArg = false; - pl.push_back(p); - - p.name = "append"; - p.description = "If an output file already exists, append data to it."; - p.hasArg = false; - pl.push_back(p); - p.name = "plain"; p.description = "Use \"plain\" RDF even if transform metadata is available."; p.hasArg = false; @@ -93,127 +58,18 @@ void RDFFeatureWriter::setParameters(map<string, string> ¶ms) { + FileFeatureWriter::setParameters(params); + cerr << "RDFFeatureWriter::setParameters" << endl; for (map<string, string>::iterator i = params.begin(); i != params.end(); ++i) { cerr << i->first << " -> " << i->second << endl; - if (i->first == "basedir") { - m_baseDir = i->second.c_str(); - } else if (i->first == "many-files") { - if (m_singleFileName != "") { - cerr << "RDFFeatureWriter::setParameters: WARNING: Both one-file and many-files parameters provided, ignoring many-files" << endl; - } else { - m_manyFiles = true; - } - } else if (i->first == "one-file") { - if (m_manyFiles) { - cerr << "RDFFeatureWriter::setParameters: WARNING: Both many-files and one-file parameters provided, ignoring one-file" << endl; - } else { - m_singleFileName = i->second.c_str(); - } - } else if (i->first == "plain") { + if (i->first == "plain") { m_plain = true; - } else if (i->first == "append") { - m_append = true; - } else if (i->first == "force") { - m_force = true; } } } -QString RDFFeatureWriter::getOutputFilename(QString trackId, - TransformId transformId) -{ - if (m_singleFileName != "") { - if (QFileInfo(m_singleFileName).exists() && !(m_force || m_append)) { - cerr << "RDFFeatureWriter: ERROR: Specified output file \"" << m_singleFileName.toStdString() << "\" exists and neither force nor append flag is specified -- not overwriting" << endl; - return ""; - } - return m_singleFileName; - } - - QUrl url(trackId); - QString scheme = url.scheme().toLower(); - bool local = (scheme == "" || scheme == "file" || scheme.length() == 1); - - QString dirname, basename; - QString infilename = url.toLocalFile(); - basename = QFileInfo(infilename).baseName(); - if (local) dirname = QFileInfo(infilename).absolutePath(); - else dirname = QDir::currentPath(); - - QString filename; - - if (m_manyFiles && transformId != "") { - filename = QString("%1:%2.rdf").arg(basename).arg(transformId); - } else { - filename = QString("%1.rdf").arg(basename); - } - - filename = QDir(dirname).filePath(filename); - - if (QFileInfo(filename).exists() && !(m_force || m_append)) { - cerr << "RDFFeatureWriter: ERROR: Output file \"" << filename.toStdString() << "\" exists (for input file or URL \"" << trackId.toStdString() << "\" and transform \"" << transformId.toStdString() << "\") and neither force nor append is specified -- not overwriting" << endl; - return ""; - } - - return filename; -} - - -QFile *RDFFeatureWriter::getOutputFile(QString trackId, - TransformId transformId) -{ - pair<QString, TransformId> key; - - if (m_singleFileName != "") { - key = pair<QString, TransformId>("", ""); - } else if (m_manyFiles) { - key = pair<QString, TransformId>(trackId, transformId); - } else { - key = pair<QString, TransformId>(trackId, ""); - } - - if (m_files.find(key) == m_files.end()) { - - QString filename = getOutputFilename(trackId, transformId); - - cerr << "RDFFeatureWriter: NOTE: Using output filename \"" - << filename.toStdString() << "\"" << endl; - - QFile *file = new QFile(filename); - QIODevice::OpenMode mode = (QIODevice::WriteOnly); - if (m_append) mode |= QIODevice::Append; - - if (!file->open(mode)) { - cerr << "RDFFeatureWriter: ERROR: Failed to open output file \"" << filename.toStdString() - << "\" for writing" << endl; - delete file; - m_files[key] = 0; - return 0; - } - - m_files[key] = file; - } - - return m_files[key]; -} - - -QTextStream *RDFFeatureWriter::getOutputStream(QString trackId, - TransformId transformId) -{ - QFile *file = getOutputFile(trackId, transformId); - if (!file) return 0; - - if (m_streams.find(file) == m_streams.end()) { - m_streams[file] = new QTextStream(file); - } - - return m_streams[file]; -} - - void RDFFeatureWriter::write(QString trackId, TransformId transformId, const Plugin::OutputDescriptor& output, @@ -294,6 +150,19 @@ * Describe signal we're analysing (AudioFile, Signal, TimeLine, etc.) */ + QUrl url(trackId); + QString scheme = url.scheme().toLower(); + bool local = (scheme == "" || scheme == "file" || scheme.length() == 1); + + if (local) { + if (scheme == "") { + url.setScheme("file"); + } else if (scheme.length() == 1) { // DOS drive letter! + url.setScheme("file"); + url.setPath(scheme + ":" + url.path()); + } + } + if (m_trackTimelineURIs.find(trackId) == m_trackTimelineURIs.end()) { m_trackTimelineURIs[trackId] = QString(":tl_%1").arg(m_count++); } @@ -301,7 +170,8 @@ stream << "\n<" << trackId << "> a mo:AudioFile .\n\n" << ":signal a mo:Signal ;\n" - << " mo:available_as <" << trackId << "> ;\n" + << " mo:available_as <" << url.toString() + << "> ;\n" << " mo:time :sig_int .\n" << ":sig_int a time:Interval ;\n" << " time:onTimeLine " @@ -334,9 +204,12 @@ stream << desc.getOutputEventTypeURI(od.identifier).c_str() << ";\n"; } + QString timestamp = feature.timestamp.toString().c_str(); + timestamp.replace(QRegExp("^ +"), ""); + stream << " event:time [ rdf:type time:Instant;\n" //location of the event in time << " time:onTimeLine " << timelineURI << ";\n" - << " time:at \"PT" << feature.timestamp.toString().c_str() + << " time:at \"PT" << timestamp << "S\"^^xsd:duration; ];\n"; stream << " af:hasFeature :f_" << m_count << "."<<endl; Modified: runner/trunk/RDFFeatureWriter.h =================================================================== --- runner/trunk/RDFFeatureWriter.h 2008-04-03 08:30:25 UTC (rev 1039) +++ runner/trunk/RDFFeatureWriter.h 2008-04-03 15:46:46 UTC (rev 1040) @@ -22,7 +22,7 @@ #include <QString> -#include "FeatureWriter.h" +#include "FileFeatureWriter.h" #include "PluginRDFDescription.h" using std::string; @@ -33,7 +33,7 @@ class QTextStream; class QFile; -class RDFFeatureWriter : public FeatureWriter +class RDFFeatureWriter : public FileFeatureWriter { public: RDFFeatureWriter(); @@ -50,17 +50,7 @@ private: typedef map<QString, PluginRDFDescription> RDFDescriptionMap; RDFDescriptionMap m_rdfDescriptions; - - typedef pair<QString, TransformId> TrackTransformPair; - typedef map<TrackTransformPair, QFile *> FileMap; - typedef map<QFile *, QTextStream *> FileStreamMap; - FileMap m_files; - FileStreamMap m_streams; - QString getOutputFilename(QString, TransformId); - QFile *getOutputFile(QString, TransformId); - QTextStream *getOutputStream(QString, TransformId); - void writePrefixes(QTextStream *); void writeSignalDescription(QTextStream *, QString); @@ -75,13 +65,8 @@ map<QString, QString> m_trackTimelineURIs; - QString m_baseDir; - bool m_manyFiles; - QString m_singleFileName; - bool m_append; - bool m_force; bool m_plain; - + uint64_t m_count; }; Modified: runner/trunk/main.cpp =================================================================== --- runner/trunk/main.cpp 2008-04-03 08:30:25 UTC (rev 1039) +++ runner/trunk/main.cpp 2008-04-03 15:46:46 UTC (rev 1040) @@ -29,6 +29,8 @@ using std::vector; using std::string; +#include "base/Exceptions.h" + #include "data/fileio/AudioFileReaderFactory.h" #include "data/fileio/PlaylistFileReader.h" @@ -557,7 +559,13 @@ for (QStringList::const_iterator i = sources.begin(); i != sources.end(); ++i) { std::cerr << "Extracting features for: \"" << i->toStdString() << "\"" << std::endl; - manager.extractFeatures(*i); + try { + manager.extractFeatures(*i); + } catch (FailedToOpenFile f) { + cerr << "ERROR: Failed to open output file for feature writer: " + << f.what() << endl; + break; + } } for (int i = 0; i < writers.size(); ++i) delete writers[i]; Modified: runner/trunk/runner.pro =================================================================== --- runner/trunk/runner.pro 2008-04-03 08:30:25 UTC (rev 1039) +++ runner/trunk/runner.pro 2008-04-03 15:46:46 UTC (rev 1040) @@ -31,8 +31,8 @@ MOC_DIR = tmp_moc # Input -HEADERS += AudioDBFeatureWriter.h FeatureWriterFactory.h DefaultFeatureWriter.h FeatureWriter.h FeatureExtractionManager.h RDFFeatureWriter.h PluginRDFDescription.h -SOURCES += main.cpp DefaultFeatureWriter.cpp RDFFeatureWriter.cpp FeatureExtractionManager.cpp AudioDBFeatureWriter.cpp FeatureWriterFactory.cpp PluginRDFDescription.cpp +HEADERS += AudioDBFeatureWriter.h FeatureWriterFactory.h FileFeatureWriter.h DefaultFeatureWriter.h FeatureWriter.h FeatureExtractionManager.h RDFFeatureWriter.h PluginRDFDescription.h CSVFeatureWriter.h +SOURCES += main.cpp DefaultFeatureWriter.cpp RDFFeatureWriter.cpp FileFeatureWriter.cpp FeatureExtractionManager.cpp AudioDBFeatureWriter.cpp FeatureWriterFactory.cpp PluginRDFDescription.cpp CSVFeatureWriter.cpp This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ca...@us...> - 2008-04-24 12:10:08
|
Revision: 1058 http://sv1.svn.sourceforge.net/sv1/?rev=1058&view=rev Author: cannam Date: 2008-04-24 05:10:01 -0700 (Thu, 24 Apr 2008) Log Message: ----------- * Fix channel handling Modified Paths: -------------- runner/trunk/FeatureExtractionManager.cpp runner/trunk/main.cpp Modified: runner/trunk/FeatureExtractionManager.cpp =================================================================== --- runner/trunk/FeatureExtractionManager.cpp 2008-04-24 10:31:25 UTC (rev 1057) +++ runner/trunk/FeatureExtractionManager.cpp 2008-04-24 12:10:01 UTC (rev 1058) @@ -297,14 +297,26 @@ SampleBlock frames; reader->getInterleavedFrames(i, m_blockSize, frames); + // We have to do our own channel handling here; we can't just + // leave it to the plugin adapter because the same plugin + // adapter may have to serve for input files with various + // numbers of channels (so the adapter is simply configured + // with a fixed channel count, generally 1). + + size_t rc = reader->getChannelCount(); + for (size_t j = 0; j < m_blockSize; ++j) { for (size_t c = 0; c < m_channels; ++c) { - size_t index = j * m_channels + c; - if (index < frames.size()) { - data[c][j] = frames[index]; + size_t index; + if (c < rc) { + index = j * rc + c; + data[c][j] = 0.f; } else { - data[c][j] = 0.f; + index = j * rc + (c % rc); } + if (index < frames.size()) { + data[c][j] += frames[index]; + } } } Modified: runner/trunk/main.cpp =================================================================== --- runner/trunk/main.cpp 2008-04-24 10:31:25 UTC (rev 1057) +++ runner/trunk/main.cpp 2008-04-24 12:10:01 UTC (rev 1058) @@ -448,6 +448,7 @@ // specified in the Transform file. manager.setSampleRate(22050); // always work at this rate +// manager.setSampleRate(44100); // always work at this rate manager.setChannels(1); vector<FeatureWriter *> writers; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mh...@us...> - 2007-12-13 12:26:11
|
Revision: 908 http://sv1.svn.sourceforge.net/sv1/?rev=908&view=rev Author: mhlevy Date: 2007-12-13 04:25:30 -0800 (Thu, 13 Dec 2007) Log Message: ----------- AudioDBFeatureWriter now writes to separate files for each track Modified Paths: -------------- runner/trunk/AudioDBFeatureWriter.cpp runner/trunk/AudioDBFeatureWriter.h Modified: runner/trunk/AudioDBFeatureWriter.cpp =================================================================== --- runner/trunk/AudioDBFeatureWriter.cpp 2007-12-12 17:42:23 UTC (rev 907) +++ runner/trunk/AudioDBFeatureWriter.cpp 2007-12-13 12:25:30 UTC (rev 908) @@ -1,6 +1,6 @@ /* * DefaultFeatureWriter.cpp - * vamphost + * runner * * Created by Mark Levy on 01/11/2007. * Copyright 2007 Queen Mary, Univesity of London. All rights reserved. @@ -13,6 +13,12 @@ #include "AudioDBFeatureWriter.h" +struct AudioDBFeatureWriter::TrackStream +{ + string trackid; + ofstream* ofs; +}; + AudioDBFeatureWriter::AudioDBFeatureWriter(const string& catId, const string& dir) : catalogueId(catId), baseDir(dir) { @@ -21,9 +27,12 @@ AudioDBFeatureWriter::~AudioDBFeatureWriter() { - // close all the files - for (map<string, ofstream*>::iterator iter = dbfiles.begin(); iter != dbfiles.end(); ++iter) - iter->second->close(); + // close all open files + for (map<string, TrackStream>::iterator iter = dbfiles.begin(); iter != dbfiles.end(); ++iter) + { + iter->second.ofs->close(); + delete iter->second.ofs; + } // TODO: error handling on close } @@ -35,78 +44,94 @@ // feature-dimension feature-1 feature-2 ... // timestamp-1 timestamp-2 ... - // iterate through FeatureLists + // audioDB has to write each feature to a different file + // assume a simple naming convention of + // <catalog-id>/<track-id>.<feature-id> + // with timestamps in a corresponding <catalog-id>/<track-id>.<feature-id>.timestamp file + // the feature writer holds a map of open file descriptors + // the catalog-id is passed in to the feature writer's constructor + + // TODO: + // - write feature end rather than start times, once end time is available in vamp + // - write a power file, probably by wrapping plugin in a PluginPowerAdapter :) + + + // iterate through FeatureLists for (map<int, Vamp::Plugin::FeatureList>::const_iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) { Vamp::Plugin::FeatureList featureList = iter->second; Vamp::Plugin::OutputDescriptor output = outputList[iter->first]; + + if (output.binCount == 0) // this kind of feature just outputs timestamps and labels, assume of no interest to audioDB + continue; + for (int i = 0; i < featureList.size(); ++i) { - if (output.binCount == 0) // this kind of feature just outputs timestamps and labels, assume of no interest to audioDB - continue; - - // audioDB has to write each feature to a different file - // assume a simple naming convention of - // <catalog-id>.<feature-id> - // with timestamps in a corresponding <catalog-id>.<feature-id>.timestamp file - - // the feature writer should hold a map of open file descriptors - // the catalog-id can get passed in to the feature writer's constructor - - // we open them lazily - - // for the feature-id we use the vamp identifier, which is guaranteed short - // and free of white space and punctuation - if (dbfiles.find(output.identifier) == dbfiles.end()) - if (!openDBFile(output.identifier)) - continue; - - // assume for now that we always want a timestamp file and - // that we always have timestamps in the features (which should be the case - // using the buffering adapter) - if (dbfiles.find(output.identifier + ".timestamp") == dbfiles.end()) - if (!openDBFile(output.identifier + ".timestamp")) - continue; - - // TODO: more robust handling of failed file open - // this solution is DANGEROUS if we manage to open it - // but only on a subsequent try!! - - if (trackid != m_trackid) - { - // end the rows in each file if we've finished with a track - if (m_trackid.length() > 0) - { - for (map<string, ofstream*>::iterator iter = dbfiles.begin(); iter != dbfiles.end(); ++iter) - *(iter->second) << endl; - } - - m_trackid = trackid; - + // replace output files if necessary + if (replaceDBFile(trackid, output.identifier)) + { // write the feature length for the next track feature record // binCount has to be set // - it can be zero, i.e. if the output is really a set of labels + timestamps - *dbfiles[output.identifier] /*<< ios::binary*/ << output.binCount; + *dbfiles[output.identifier].ofs /*<< ios::binary*/ << output.binCount; + + cerr << "writing bin count " << output.binCount << " for " << output.identifier << endl; } + if (replaceDBFile(trackid, output.identifier + ".timestamp")) + { + // write the start time to the timestamp file + // as we want it for the first feature in the file + *dbfiles[output.identifier + ".timestamp"].ofs << featureList[i].timestamp.toString() << endl; + } + for (int j = 0; j < featureList[i].values.size(); ++j) - *dbfiles[output.identifier] /*<< ios::binary*/ << featureList[i].values[j]; + *dbfiles[output.identifier].ofs /*<< ios::binary*/ << featureList[i].values[j]; - *dbfiles[output.identifier + ".timestamp"] /*<< ios::binary*/ << featureList[i].timestamp; + // write the *end* time of each feature to the timestamp file + // NOT IMPLEMENTED YET + *dbfiles[output.identifier + ".timestamp"].ofs << featureList[i].timestamp.toString() << endl; } } } -bool AudioDBFeatureWriter::openDBFile(const string& identifier) +bool AudioDBFeatureWriter::openDBFile(const string& trackid, const string& identifier) { - string filepath = baseDir + "/" + catalogueId + "." + identifier; + string filepath = baseDir + "/" + catalogueId + "/" + trackid + "." + identifier; ofstream* ofs = new ofstream(filepath.c_str()); if (!*ofs) { cerr << "ERROR AudioDBFeatureWriter::openDBFile(): can't open file " << filepath << endl; return false; } - dbfiles.insert(pair<string, ofstream*>(identifier, ofs)); + TrackStream ts; + ts.trackid = trackid; + ts.ofs = ofs; + dbfiles[identifier] = ts; return true; -} \ No newline at end of file +} + +// replace file if no file open for this track, else return false +bool AudioDBFeatureWriter::replaceDBFile(const string& trackid, const string& identifier) +{ + if (dbfiles.find(identifier) != dbfiles.end() && dbfiles[identifier].trackid == trackid) + return false; // have an open file for this track + + if (dbfiles.find(identifier) != dbfiles.end() && dbfiles[identifier].trackid != trackid) + { + // close the current file + dbfiles[identifier].ofs->close(); + delete dbfiles[identifier].ofs; + } + + // open a new file + openDBFile(trackid, identifier); + + // TODO: + // handle file open failure + + return true; +} + + \ No newline at end of file Modified: runner/trunk/AudioDBFeatureWriter.h =================================================================== --- runner/trunk/AudioDBFeatureWriter.h 2007-12-12 17:42:23 UTC (rev 907) +++ runner/trunk/AudioDBFeatureWriter.h 2007-12-13 12:25:30 UTC (rev 908) @@ -1,6 +1,6 @@ /* * AudioDBFeatureWriter.h - * + * runner * * Created by Mark Levy on 14/11/2007. * Copyright 2007 Queen Mary, University of London. All rights reserved. @@ -11,11 +11,9 @@ #define _AUDIO_DB_FEATURE_WRITER_H_ #include <string> -#include <fstream> #include <map> using std::string; -using std::ofstream; using std::map; #include "FeatureWriter.h" @@ -30,10 +28,12 @@ private: string catalogueId; string baseDir; - string m_trackid; - map<string, ofstream*> dbfiles; - bool openDBFile(const string& identifier); + struct TrackStream; + map<string, TrackStream> dbfiles; + + bool openDBFile(const string& trackid, const string& identifier); + bool replaceDBFile(const string& trackid, const string& identifier); }; #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ca...@us...> - 2008-01-04 17:10:51
|
Revision: 919 http://sv1.svn.sourceforge.net/sv1/?rev=919&view=rev Author: cannam Date: 2008-01-04 09:10:49 -0800 (Fri, 04 Jan 2008) Log Message: ----------- * update for progress-to-console in FileSource (needs latest SV1 SVN) * need a QApplication on the go, or else HTTP retrieval will hang I'm getting a double-free-or-corruption error from glibc and abort after decoding completes for some input files, need to investigate this Modified Paths: -------------- runner/trunk/FeatureExtractionManager.cpp runner/trunk/main.cpp Modified: runner/trunk/FeatureExtractionManager.cpp =================================================================== --- runner/trunk/FeatureExtractionManager.cpp 2008-01-04 17:08:10 UTC (rev 918) +++ runner/trunk/FeatureExtractionManager.cpp 2008-01-04 17:10:49 UTC (rev 919) @@ -134,7 +134,7 @@ { cerr << "Creating FileSource..." << endl; - FileSource source(audioSource.c_str()); + FileSource source(audioSource.c_str(), FileSource::ProgressToConsole); if (!source.isAvailable()) { cerr << "ERROR: File or URL \"" << audioSource << "\" could not be located" << endl; Modified: runner/trunk/main.cpp =================================================================== --- runner/trunk/main.cpp 2008-01-04 17:08:10 UTC (rev 918) +++ runner/trunk/main.cpp 2008-01-04 17:10:49 UTC (rev 919) @@ -11,6 +11,8 @@ #include <vector> #include <string> +#include <QCoreApplication> + using std::vector; using std::string; @@ -21,6 +23,14 @@ int main(int argc, char **argv) { + QCoreApplication application(argc, argv); + + QCoreApplication::setOrganizationName("QMUL"); + QCoreApplication::setOrganizationDomain("qmul.ac.uk"); + QCoreApplication::setApplicationName("runner"); + + QStringList args = application.arguments(); + FeatureExtractionManager manager; // the manager dictates the sample rate and number of channels @@ -33,8 +43,8 @@ writers.push_back(new DefaultFeatureWriter()); // for debug string writerType = ""; - if (argc > 1) - writerType = argv[1]; + if (args.size() > 1) + writerType = args[1].toStdString(); if (writerType == "rdf") writers.push_back(new RDFFeatureWriter(".", "."));// For now, dump RDF adjacent to audio if (writerType == "adb") @@ -87,8 +97,9 @@ // } //string trackUri = "./test.mp3"; - //string trackUri = "http://dsp-cluster/music/yvesr/2%20MANY%20DJs/Soulwax%20Radio%20Session%20Part%201%20CD%202/00.%20As%20Heard%20On%20Radio%20Soulwax%20pt.%203.mp3"; - string trackUri = "/users/mark/documents/tags/audio/999.mp3"; +// string trackUri = "/home/studio/sunset_overseas.mp3"; + string trackUri = "http://dsp-cluster/music/yvesr/2%20MANY%20DJs/Soulwax%20Radio%20Session%20Part%201%20CD%202/00.%20As%20Heard%20On%20Radio%20Soulwax%20pt.%203.mp3"; + //string trackUri = "/users/mark/documents/tags/audio/999.mp3"; if (argc > 2) trackUri = argv[2]; manager.extractFeatures(trackUri); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <je...@us...> - 2008-02-02 14:40:51
|
Revision: 942 http://sv1.svn.sourceforge.net/sv1/?rev=942&view=rev Author: jerrell Date: 2008-02-02 06:40:44 -0800 (Sat, 02 Feb 2008) Log Message: ----------- some very basic command line parameters for runner Modified Paths: -------------- runner/trunk/FeatureExtractionManager.cpp runner/trunk/main.cpp Modified: runner/trunk/FeatureExtractionManager.cpp =================================================================== --- runner/trunk/FeatureExtractionManager.cpp 2008-01-31 15:07:38 UTC (rev 941) +++ runner/trunk/FeatureExtractionManager.cpp 2008-02-02 14:40:44 UTC (rev 942) @@ -223,7 +223,7 @@ { Vamp::Plugin::FeatureSet featureSet = plugins[k]->process(data, timestamp); for (int j = 0; j < pluginWriters[k].size(); ++j) - pluginWriters[k][j]->write("track01", plugins[k]->getIdentifier(), plugins[k]->getOutputDescriptors(), featureSet); + pluginWriters[k][j]->write(audioSource.c_str(), plugins[k]->getIdentifier(), plugins[k]->getOutputDescriptors(), featureSet); } } @@ -242,7 +242,7 @@ // or even rename files according to some convention for (int j = 0; j < pluginWriters[k].size(); ++j) - pluginWriters[k][j]->write("track01", plugins[k]->getIdentifier(), plugins[k]->getOutputDescriptors(), plugins[k]->getRemainingFeatures()); + pluginWriters[k][j]->write(audioSource.c_str(), plugins[k]->getIdentifier(), plugins[k]->getOutputDescriptors(), plugins[k]->getRemainingFeatures()); } TempDirectory::getInstance()->cleanup(); Modified: runner/trunk/main.cpp =================================================================== --- runner/trunk/main.cpp 2008-01-31 15:07:38 UTC (rev 941) +++ runner/trunk/main.cpp 2008-02-02 14:40:44 UTC (rev 942) @@ -10,9 +10,12 @@ #include <vector> #include <string> +#include <iostream> + #include <QCoreApplication> +using std::cout; using std::endl; using std::vector; using std::string; @@ -40,8 +43,16 @@ manager.setChannels(1); vector<FeatureWriter*> writers; - writers.push_back(new DefaultFeatureWriter()); // for debug + // writers.push_back(new DefaultFeatureWriter()); // for debug + if (argc <= 1) // no args supplied + { + cout<<" Usage : runner writertype audiofile transformfile"<<endl; + cout<<" eg. runner rdf test.mp3 transforms/tempotracker.xml"<<endl; + exit(-1); + } + + string writerType = ""; if (args.size() > 1) writerType = args[1].toStdString(); @@ -64,9 +75,14 @@ // we may want to work from saved transforms here if we // already know what features we want // - this is the audioDB scenario - manager.addFeatureExtractor("transforms/percussiononsets.xml", writers); - manager.addFeatureExtractor("transforms/chromagram.xml", writers); - manager.addFeatureExtractor("transforms/spectralcentroid.xml", writers); + if (argc>3) + manager.addFeatureExtractor(argv[3], writers); + else + { + manager.addFeatureExtractor("transforms/percussiononsets.xml", writers); + manager.addFeatureExtractor("transforms/chromagram.xml", writers); + manager.addFeatureExtractor("transforms/spectralcentroid.xml", writers); + } // note that the default writer dumps everything to cerr // but real writers can write to feature-specific and/or track-specific files This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ca...@us...> - 2008-03-14 17:16:59
|
Revision: 1012 http://sv1.svn.sourceforge.net/sv1/?rev=1012&view=rev Author: cannam Date: 2008-03-14 10:16:56 -0700 (Fri, 14 Mar 2008) Log Message: ----------- * Update to build with latest SV code; now it no longer depends on QtGui (only one billion library dependencies remaining!) Modified Paths: -------------- runner/trunk/FeatureExtractionManager.cpp runner/trunk/runner.pro Modified: runner/trunk/FeatureExtractionManager.cpp =================================================================== --- runner/trunk/FeatureExtractionManager.cpp 2008-03-14 17:14:21 UTC (rev 1011) +++ runner/trunk/FeatureExtractionManager.cpp 2008-03-14 17:16:56 UTC (rev 1012) @@ -27,6 +27,7 @@ #include "data/fileio/AudioFileReader.h" #include "data/fileio/AudioFileReaderFactory.h" #include "base/TempDirectory.h" +#include "base/ProgressPrinter.h" #include "transform/TransformFactory.h" #include "FeatureWriter.h" @@ -134,7 +135,8 @@ { cerr << "Creating FileSource..." << endl; - FileSource source(audioSource.c_str(), FileSource::ProgressToConsole); + ProgressPrinter printer("Retrieving data..."); + FileSource source(audioSource.c_str(), &printer); if (!source.isAvailable()) { cerr << "ERROR: File or URL \"" << audioSource << "\" could not be located" << endl; Modified: runner/trunk/runner.pro =================================================================== --- runner/trunk/runner.pro 2008-03-14 17:14:21 UTC (rev 1011) +++ runner/trunk/runner.pro 2008-03-14 17:16:56 UTC (rev 1012) @@ -6,7 +6,7 @@ CONFIG += sv qt thread warn_on stl rtti exceptions QT += xml network -#QT -= gui +QT -= gui TARGET = runner This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ca...@us...> - 2008-03-19 13:36:18
|
Revision: 1019 http://sv1.svn.sourceforge.net/sv1/?rev=1019&view=rev Author: cannam Date: 2008-03-19 06:36:13 -0700 (Wed, 19 Mar 2008) Log Message: ----------- * tinkering (does not currently build) Modified Paths: -------------- runner/trunk/AudioDBFeatureWriter.cpp runner/trunk/AudioDBFeatureWriter.h runner/trunk/RDFFeatureWriter.cpp runner/trunk/RDFFeatureWriter.h runner/trunk/RDFSinglePluginWriter.h runner/trunk/main.cpp runner/trunk/runner.pro Modified: runner/trunk/AudioDBFeatureWriter.cpp =================================================================== --- runner/trunk/AudioDBFeatureWriter.cpp 2008-03-19 11:20:18 UTC (rev 1018) +++ runner/trunk/AudioDBFeatureWriter.cpp 2008-03-19 13:36:13 UTC (rev 1019) @@ -10,18 +10,19 @@ #include <fstream> +#include "AudioDBFeatureWriter.h" + using namespace std; +using namespace Vamp; -#include "AudioDBFeatureWriter.h" - struct AudioDBFeatureWriter::TrackStream { string trackid; ofstream* ofs; }; -AudioDBFeatureWriter::AudioDBFeatureWriter(const string& catId, const string& dir) : -catalogueId(catId), baseDir(dir) +AudioDBFeatureWriter::AudioDBFeatureWriter() : + catalogueId("catalog"), baseDir("audiodb") { } @@ -38,8 +39,23 @@ // TODO: error handling on close } -void AudioDBFeatureWriter::write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) +void +AudioDBFeatureWriter::setCatalogueId(const string &catid) { + catalogueId = catid; +} + +void +AudioDBFeatureWriter::setBaseDirectory(const string &base) +{ + baseDir = base; +} + +void AudioDBFeatureWriter::write(const string& trackid, + const string& pluginid, + const Plugin::OutputList& outputList, + const Plugin::FeatureSet& featureSet) +{ // binary output for FeatureSet // feature-dimension feature-1 feature-2 ... @@ -59,10 +75,11 @@ // iterate through FeatureLists - for (map<int, Vamp::Plugin::FeatureList>::const_iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) + for (Plugin::FeatureSet::const_iterator iter = featureSet.begin(); + iter != featureSet.end(); ++iter) { - Vamp::Plugin::FeatureList featureList = iter->second; - Vamp::Plugin::OutputDescriptor output = outputList[iter->first]; + const Plugin::FeatureList &featureList = iter->second; + const Plugin::OutputDescriptor &output = outputList[iter->first]; if (output.binCount == 0) // this kind of feature just outputs timestamps and labels, assume of no interest to audioDB continue; @@ -114,7 +131,8 @@ } // replace file if no file open for this track, else return false -bool AudioDBFeatureWriter::replaceDBFile(const string& trackid, const string& identifier) +bool AudioDBFeatureWriter::replaceDBFile(const string& trackid, + const string& identifier) { if (dbfiles.find(identifier) != dbfiles.end() && dbfiles[identifier].trackid == trackid) return false; // have an open file for this track Modified: runner/trunk/AudioDBFeatureWriter.h =================================================================== --- runner/trunk/AudioDBFeatureWriter.h 2008-03-19 11:20:18 UTC (rev 1018) +++ runner/trunk/AudioDBFeatureWriter.h 2008-03-19 13:36:13 UTC (rev 1019) @@ -22,9 +22,18 @@ class AudioDBFeatureWriter : public FeatureWriter { public: - AudioDBFeatureWriter(const string& catId, const string& dir); + AudioDBFeatureWriter(); virtual ~AudioDBFeatureWriter(); - virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); + + virtual void setParameters(const map<string, string> ¶ms); + + virtual void setCatalogueId(const string &); + virtual void setBaseDirectory(const string &); + + virtual void write(const string& trackid, + const string& pluginid, + const Vamp::Plugin::OutputList& outputList, + const Vamp::Plugin::FeatureSet& featureSet); private: string catalogueId; Modified: runner/trunk/RDFFeatureWriter.cpp =================================================================== --- runner/trunk/RDFFeatureWriter.cpp 2008-03-19 11:20:18 UTC (rev 1018) +++ runner/trunk/RDFFeatureWriter.cpp 2008-03-19 13:36:13 UTC (rev 1019) @@ -10,18 +10,16 @@ #include <fstream> -using namespace std; - #include "vamp-sdk/PluginHostAdapter.h" #include "vamp-sdk/hostext/PluginLoader.h" -using Vamp::HostExt::PluginLoader; -using Vamp::PluginHostAdapter; - #include "RDFFeatureWriter.h" -RDFFeatureWriter::RDFFeatureWriter(const string& catId, const string& dir) : -catalogueId(catId), baseDir(dir) +using namespace std; +using namespace Vamp; + +RDFFeatureWriter::RDFFeatureWriter() : + catalogueId("."), baseDir(".") //!!! { } @@ -29,21 +27,24 @@ RDFFeatureWriter::~RDFFeatureWriter() { // close all open files - for (map<string, RDFSinglePluginWriter*>::iterator iter = featureWriters.begin(); iter != featureWriters.end(); ++iter) + for (WriterMap::iterator iter = featureWriters.begin(); + iter != featureWriters.end(); ++iter) { delete iter->second; } } -void RDFFeatureWriter::write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) +void RDFFeatureWriter::write(const string& trackid, + const string& pluginid, + const Plugin::OutputList& outputList, + const Plugin::FeatureSet& featureSet) { - - // iterate through FeatureLists - for (map<int, Vamp::Plugin::FeatureList>::const_iterator iter = featureSet.begin(); iter != featureSet.end(); ++iter) + for (Plugin::FeatureSet::const_iterator iter = featureSet.begin(); + iter != featureSet.end(); ++iter) { - Vamp::Plugin::FeatureList featureList = iter->second; - Vamp::Plugin::OutputDescriptor output = outputList[iter->first]; + const Plugin::FeatureList &featureList = iter->second; + const Plugin::OutputDescriptor &output = outputList[iter->first]; for (unsigned int i = 0; i < featureList.size(); ++i) { @@ -75,6 +76,7 @@ cerr<<"found feature writer with old track"<<endl; cerr<<"new : "<<trackid<<", old : "<<featureWriters[pluginid]->trackid<<endl; delete featureWriters[pluginid]; + featureWriters.erase(pluginid); } } cerr<<"allocating new RDFSinglePluginWriter"<<endl; @@ -82,6 +84,12 @@ return true; } +static bool fileExists(string filepath) +{ + std::ifstream fin(filepath.c_str()); + return (fin != NULL); +} + string RDFFeatureWriter::getDescriptionFileForPlugin(const string& pluginid) { string path = ""; @@ -93,7 +101,7 @@ rdf_exts.push_back("rdf"); rdf_exts.push_back("RDF"); rdf_exts.push_back("n3"); rdf_exts.push_back("N3"); - PluginLoader *loader = PluginLoader::getInstance(); + HostExt::PluginLoader *loader = HostExt::PluginLoader::getInstance(); vector<string> keys = loader->listPlugins(); string libname = ""; for (vector<string>::iterator kitr = keys.begin(); kitr != keys.end(); kitr++) @@ -132,9 +140,3 @@ cerr<<"Couldn't find description of plugin !"<<endl; return ""; } - -bool fileExists(string filepath) -{ - std::ifstream fin(filepath.c_str()); - return (fin != NULL); -} Modified: runner/trunk/RDFFeatureWriter.h =================================================================== --- runner/trunk/RDFFeatureWriter.h 2008-03-19 11:20:18 UTC (rev 1018) +++ runner/trunk/RDFFeatureWriter.h 2008-03-19 13:36:13 UTC (rev 1019) @@ -23,21 +23,27 @@ class RDFFeatureWriter : public FeatureWriter { public: - RDFFeatureWriter(const string& catId, const string& dir); + RDFFeatureWriter(); virtual ~RDFFeatureWriter(); - virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); + + virtual void setParameters(const map<string, string> ¶ms); + + virtual void write(const string& trackid, + const string& pluginid, + const Vamp::Plugin::OutputList& outputList, + const Vamp::Plugin::FeatureSet& featureSet); + static string getDescriptionFileForPlugin(const string& pluginid); private: string catalogueId; string baseDir; + + typedef map<string, RDFSinglePluginWriter*> WriterMap; + WriterMap featureWriters; - map<string, RDFSinglePluginWriter*> featureWriters; - bool newFeatureWriter(const string& trackid, const string& identifier); bool replaceFeatureWriter(const string& trackid, const string& identifier); }; -bool fileExists(string filepath); - #endif Modified: runner/trunk/RDFSinglePluginWriter.h =================================================================== --- runner/trunk/RDFSinglePluginWriter.h 2008-03-19 11:20:18 UTC (rev 1018) +++ runner/trunk/RDFSinglePluginWriter.h 2008-03-19 13:36:13 UTC (rev 1019) @@ -12,9 +12,12 @@ #define _RDF_SINGLE_PLUGIN_WRITER_H_ #include <fstream> -using std::ostream; + #include "FeatureWriter.h" +using std::ostream; +using std::vector; + enum ODOutputType { ODOT_UNKNOWN, Modified: runner/trunk/main.cpp =================================================================== --- runner/trunk/main.cpp 2008-03-19 11:20:18 UTC (rev 1018) +++ runner/trunk/main.cpp 2008-03-19 13:36:13 UTC (rev 1019) @@ -21,11 +21,11 @@ using std::string; #include "FeatureExtractionManager.h" -#include "DefaultFeatureWriter.h" -#include "RDFFeatureWriter.h" -#include "AudioDBFeatureWriter.h" +//#include "DefaultFeatureWriter.h" +//#include "RDFFeatureWriter.h" +//#include "AudioDBFeatureWriter.h" +#include "FeatureWriterFactory.h" - // Desired options: // // * output preference: @@ -42,7 +42,7 @@ // - based on input (obvious choice for one file per input file modes) // - specified on command line (obvious choice for all in one file mode) // -// * output format: +// * output format: one or more of // - RDF // - AudioDB // - Vamp Simple Host format @@ -78,7 +78,7 @@ // // MAYBE: // * input files to transform: -// - supple file names or URIs on command line +// - supply file names or URIs on command line // - use all files in a given directory or tree @@ -119,10 +119,9 @@ string writerType = ""; if (args.size() > 1) writerType = args[1].toStdString(); - if (writerType == "rdf") - writers.push_back(new RDFFeatureWriter(".", "."));// For now, dump RDF adjacent to audio - if (writerType == "adb") - writers.push_back(new AudioDBFeatureWriter("catalog01", "audiodb")); + + FeatureWriter *writer = FeatureWriterFactory::createWriter(writerType); + if (writer) writers.push_back(writer); /* // list all the available plugins as transforms Modified: runner/trunk/runner.pro =================================================================== --- runner/trunk/runner.pro 2008-03-19 11:20:18 UTC (rev 1018) +++ runner/trunk/runner.pro 2008-03-19 13:36:13 UTC (rev 1019) @@ -29,8 +29,8 @@ MOC_DIR = tmp_moc # Input -HEADERS += -SOURCES += main.cpp DefaultFeatureWriter.cpp RDFFeatureWriter.cpp RDFSinglePluginWriter.cpp FeatureExtractionManager.cpp AudioDBFeatureWriter.cpp +HEADERS += AudioDBFeatureWriter.h FeatureWriterFactory.h RDFSinglePluginWriter.h DefaultFeatureWriter.h FeatureWriter.h SimpleRDFFeatureWriter.h FeatureExtractionManager.h RDFFeatureWriter.h +SOURCES += main.cpp DefaultFeatureWriter.cpp RDFFeatureWriter.cpp RDFSinglePluginWriter.cpp FeatureExtractionManager.cpp AudioDBFeatureWriter.cpp FeatureWriterFactory.cpp This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ca...@us...> - 2008-03-19 13:54:39
|
Revision: 1020 http://sv1.svn.sourceforge.net/sv1/?rev=1020&view=rev Author: cannam Date: 2008-03-19 06:54:37 -0700 (Wed, 19 Mar 2008) Log Message: ----------- * basic factory class Added Paths: ----------- runner/trunk/FeatureWriterFactory.cpp runner/trunk/FeatureWriterFactory.h Added: runner/trunk/FeatureWriterFactory.cpp =================================================================== --- runner/trunk/FeatureWriterFactory.cpp (rev 0) +++ runner/trunk/FeatureWriterFactory.cpp 2008-03-19 13:54:37 UTC (rev 1020) @@ -0,0 +1,28 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +#include "FeatureWriterFactory.h" + +#include "RDFFeatureWriter.h" +#include "AudioDBFeatureWriter.h" + +set<string> +FeatureWriterFactory::getWriterTags() +{ + set<string> tags; + tags.insert("rdf"); + tags.insert("audiodb"); +// tags.insert("csv"); + return tags; +} + +FeatureWriter * +FeatureWriterFactory::createWriter(string tag) +{ + if (tag == "rdf") { + return new RDFFeatureWriter(); + } else if (tag == "audiodb") { + return new AudioDBFeatureWriter(); + } + + return 0; +} Added: runner/trunk/FeatureWriterFactory.h =================================================================== --- runner/trunk/FeatureWriterFactory.h (rev 0) +++ runner/trunk/FeatureWriterFactory.h 2008-03-19 13:54:37 UTC (rev 1020) @@ -0,0 +1,22 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +#ifndef _FEATURE_WRITER_FACTORY_H_ +#define _FEATURE_WRITER_FACTORY_H_ + +#include <set> +#include <string> + +using std::set; +using std::string; + +class FeatureWriter; + +class FeatureWriterFactory +{ +public: + static set<string> getWriterTags(); + static FeatureWriter *createWriter(string tag); +}; + + +#endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ca...@us...> - 2008-03-19 16:23:50
|
Revision: 1021 http://sv1.svn.sourceforge.net/sv1/?rev=1021&view=rev Author: cannam Date: 2008-03-19 09:23:47 -0700 (Wed, 19 Mar 2008) Log Message: ----------- * Print out usage notes (not actually implemented yet, but hey! the spec is half the work!) * A few other tweaks Modified Paths: -------------- runner/trunk/AudioDBFeatureWriter.cpp runner/trunk/AudioDBFeatureWriter.h runner/trunk/DefaultFeatureWriter.cpp runner/trunk/DefaultFeatureWriter.h runner/trunk/FeatureExtractionManager.cpp runner/trunk/FeatureExtractionManager.h runner/trunk/FeatureWriter.h runner/trunk/FeatureWriterFactory.cpp runner/trunk/FeatureWriterFactory.h runner/trunk/RDFFeatureWriter.cpp runner/trunk/RDFFeatureWriter.h runner/trunk/RDFSinglePluginWriter.cpp runner/trunk/RDFSinglePluginWriter.h runner/trunk/SimpleRDFFeatureWriter.cpp runner/trunk/SimpleRDFFeatureWriter.h runner/trunk/main.cpp Modified: runner/trunk/AudioDBFeatureWriter.cpp =================================================================== --- runner/trunk/AudioDBFeatureWriter.cpp 2008-03-19 13:54:37 UTC (rev 1020) +++ runner/trunk/AudioDBFeatureWriter.cpp 2008-03-19 16:23:47 UTC (rev 1021) @@ -1,13 +1,18 @@ /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + /* - * DefaultFeatureWriter.cpp - * runner - * - * Created by Mark Levy on 01/11/2007. - * Copyright 2007 Queen Mary, Univesity of London. All rights reserved. - * - */ + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + #include <fstream> #include "AudioDBFeatureWriter.h" @@ -15,6 +20,12 @@ using namespace std; using namespace Vamp; +string +AudioDBFeatureWriter::catalogueIdParam = "catid"; + +string +AudioDBFeatureWriter::baseDirParam = "basedir"; + struct AudioDBFeatureWriter::TrackStream { string trackid; @@ -39,7 +50,29 @@ // TODO: error handling on close } +map<string, string> +AudioDBFeatureWriter::getSupportedParameters() const +{ + map<string, string> params; + params[catalogueIdParam] = "Catalogue ID"; + params[baseDirParam] = "Base output directory path"; + return params; +} + void +AudioDBFeatureWriter::setParameters(map<string, string> ¶ms) +{ + if (params.find("catalogue") != params.end()) { + setCatalogueId(params["catalogue"]); + params.erase("catalogue"); + } + if (params.find("basedir") != params.end()) { + setCatalogueId(params["basedir"]); + params.erase("basedir"); + } +} + +void AudioDBFeatureWriter::setCatalogueId(const string &catid) { catalogueId = catid; Modified: runner/trunk/AudioDBFeatureWriter.h =================================================================== --- runner/trunk/AudioDBFeatureWriter.h 2008-03-19 13:54:37 UTC (rev 1020) +++ runner/trunk/AudioDBFeatureWriter.h 2008-03-19 16:23:47 UTC (rev 1021) @@ -1,13 +1,18 @@ /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + /* - * AudioDBFeatureWriter.h - * runner - * - * Created by Mark Levy on 14/11/2007. - * Copyright 2007 Queen Mary, University of London. All rights reserved. - * - */ + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + #ifndef _AUDIO_DB_FEATURE_WRITER_H_ #define _AUDIO_DB_FEATURE_WRITER_H_ @@ -25,7 +30,8 @@ AudioDBFeatureWriter(); virtual ~AudioDBFeatureWriter(); - virtual void setParameters(const map<string, string> ¶ms); + virtual map<string, string> getSupportedParameters() const; + virtual void setParameters(map<string, string> ¶ms); virtual void setCatalogueId(const string &); virtual void setBaseDirectory(const string &); @@ -38,6 +44,9 @@ private: string catalogueId; string baseDir; + + static string catalogueIdParam; + static string baseDirParam; struct TrackStream; map<string, TrackStream> dbfiles; Modified: runner/trunk/DefaultFeatureWriter.cpp =================================================================== --- runner/trunk/DefaultFeatureWriter.cpp 2008-03-19 13:54:37 UTC (rev 1020) +++ runner/trunk/DefaultFeatureWriter.cpp 2008-03-19 16:23:47 UTC (rev 1021) @@ -1,13 +1,18 @@ /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + /* - * DefaultFeatureWriter.cpp - * vamphost - * - * Created by Mark Levy on 01/11/2007. - * Copyright 2007 Queen Mary, Univesity of London. All rights reserved. - * - */ + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + #include <iostream> #include <map> Modified: runner/trunk/DefaultFeatureWriter.h =================================================================== --- runner/trunk/DefaultFeatureWriter.h 2008-03-19 13:54:37 UTC (rev 1020) +++ runner/trunk/DefaultFeatureWriter.h 2008-03-19 16:23:47 UTC (rev 1021) @@ -1,13 +1,18 @@ /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + /* - * DefaultFeatureWriter.h - * vamphost - * - * Created by Mark Levy on 01/11/2007. - * Copyright 2007 Queen Mary, Univesity of London. All rights reserved. - * - */ + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + #ifndef _DEFAULT_FEATURE_WRITER_H_ #define _DEFAULT_FEATURE_WRITER_H_ Modified: runner/trunk/FeatureExtractionManager.cpp =================================================================== --- runner/trunk/FeatureExtractionManager.cpp 2008-03-19 13:54:37 UTC (rev 1020) +++ runner/trunk/FeatureExtractionManager.cpp 2008-03-19 16:23:47 UTC (rev 1021) @@ -1,13 +1,18 @@ /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + /* - * FeatureExtractionManager.cpp - * runner - * - * Created by Mark Levy on 31/10/2007. - * Copyright 2007 Queen Mary, University of London. All rights reserved. - * - */ + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + #include <iostream> using namespace std; Modified: runner/trunk/FeatureExtractionManager.h =================================================================== --- runner/trunk/FeatureExtractionManager.h 2008-03-19 13:54:37 UTC (rev 1020) +++ runner/trunk/FeatureExtractionManager.h 2008-03-19 16:23:47 UTC (rev 1021) @@ -1,13 +1,18 @@ /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + /* - * FeatureExtractionManager.h - * runner - * - * Created by Mark Levy on 31/10/2007. - * Copyright 2007 Queen Mary, University of London. All rights reserved. - * - */ + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + #ifndef _FEATURE_EXTRACTION_MANAGER_H_ #define _FEATURE_EXTRACTION_MANAGER_H_ Modified: runner/trunk/FeatureWriter.h =================================================================== --- runner/trunk/FeatureWriter.h 2008-03-19 13:54:37 UTC (rev 1020) +++ runner/trunk/FeatureWriter.h 2008-03-19 16:23:47 UTC (rev 1021) @@ -1,27 +1,46 @@ /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + /* - * FeatureWriter.h - * vamphost - * - * Created by Mark Levy on 01/11/2007. - * Copyright 2007 Queen Mary, Univesity of London. All rights reserved. - * - */ + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + #ifndef _FEATURE_WRITER_H_ #define _FEATURE_WRITER_H_ #include <string> +#include <map> +#include <vamp-sdk/Plugin.h> + using std::string; +using std::map; -#include <vamp-sdk/Plugin.h> - class FeatureWriter { public: virtual ~FeatureWriter() { } - virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) = 0; + + virtual map<string, string> getSupportedParameters() const { + return map<string, string>(); + } + + virtual void setParameters(map<string, string> ¶ms) { + return; + } + + virtual void write(const string& trackid, + const string& pluginid, + const Vamp::Plugin::OutputList& outputList, + const Vamp::Plugin::FeatureSet& featureSet) = 0; }; #endif Modified: runner/trunk/FeatureWriterFactory.cpp =================================================================== --- runner/trunk/FeatureWriterFactory.cpp 2008-03-19 13:54:37 UTC (rev 1020) +++ runner/trunk/FeatureWriterFactory.cpp 2008-03-19 16:23:47 UTC (rev 1021) @@ -1,5 +1,19 @@ /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ +/* + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + #include "FeatureWriterFactory.h" #include "RDFFeatureWriter.h" Modified: runner/trunk/FeatureWriterFactory.h =================================================================== --- runner/trunk/FeatureWriterFactory.h 2008-03-19 13:54:37 UTC (rev 1020) +++ runner/trunk/FeatureWriterFactory.h 2008-03-19 16:23:47 UTC (rev 1021) @@ -1,5 +1,19 @@ /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ +/* + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + #ifndef _FEATURE_WRITER_FACTORY_H_ #define _FEATURE_WRITER_FACTORY_H_ Modified: runner/trunk/RDFFeatureWriter.cpp =================================================================== --- runner/trunk/RDFFeatureWriter.cpp 2008-03-19 13:54:37 UTC (rev 1020) +++ runner/trunk/RDFFeatureWriter.cpp 2008-03-19 16:23:47 UTC (rev 1021) @@ -1,13 +1,18 @@ /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + /* - * RDFFeatureWriter.cpp - * runner - * - * Created by Chris Sutton 13/12/2007. - * Copyright 2007 Queen Mary, Univesity of London. All rights reserved. - * - */ + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + #include <fstream> #include "vamp-sdk/PluginHostAdapter.h" @@ -34,6 +39,24 @@ } } +map<string, string> +RDFFeatureWriter::getSupportedParameters() const +{ + map<string, string> params; + params["one-file"] = "Create one output file only:\nall transforms for all inputs written to the same file"; + params["per-input"] = "Create one output file for each input file:\nall transforms for that input written to the same file"; + params["per-transform"] = "Create output file for each transform on each input"; + params["plain"] = "Use \"plain\" RDF even if transform metadata is available"; + params["basedir"] = "Base output directory path (default same as input file)"; + return params; +} + +void +RDFFeatureWriter::setParameters(map<string, string> ¶ms) +{ + //!!! implement +} + void RDFFeatureWriter::write(const string& trackid, const string& pluginid, const Plugin::OutputList& outputList, Modified: runner/trunk/RDFFeatureWriter.h =================================================================== --- runner/trunk/RDFFeatureWriter.h 2008-03-19 13:54:37 UTC (rev 1020) +++ runner/trunk/RDFFeatureWriter.h 2008-03-19 16:23:47 UTC (rev 1021) @@ -1,13 +1,18 @@ /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + /* - * RDFFeatureWriter.h - * runner - * - * Created by Chris Sutton on 13/12/2007. - * Copyright 2007 Queen Mary, University of London. All rights reserved. - * - */ + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + #ifndef _RDF_FEATURE_WRITER_H_ #define _RDF_FEATURE_WRITER_H_ @@ -26,7 +31,8 @@ RDFFeatureWriter(); virtual ~RDFFeatureWriter(); - virtual void setParameters(const map<string, string> ¶ms); + virtual map<string, string> getSupportedParameters() const; + virtual void setParameters(map<string, string> ¶ms); virtual void write(const string& trackid, const string& pluginid, Modified: runner/trunk/RDFSinglePluginWriter.cpp =================================================================== --- runner/trunk/RDFSinglePluginWriter.cpp 2008-03-19 13:54:37 UTC (rev 1020) +++ runner/trunk/RDFSinglePluginWriter.cpp 2008-03-19 16:23:47 UTC (rev 1021) @@ -1,13 +1,18 @@ /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + /* - * RDFSinglePluginWriter.cpp - * vamphost - * - * Created by Chris Sutton on 13/12/2007. - * Copyright 2007 Queen Mary, University of London. All rights reserved. - * - */ + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + #include <iostream> #include <fstream> #include <map> Modified: runner/trunk/RDFSinglePluginWriter.h =================================================================== --- runner/trunk/RDFSinglePluginWriter.h 2008-03-19 13:54:37 UTC (rev 1020) +++ runner/trunk/RDFSinglePluginWriter.h 2008-03-19 16:23:47 UTC (rev 1021) @@ -1,13 +1,18 @@ /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + /* - * RDFSinglePluginWriter.h - * vamphost - * - * Created by Chris Sutton on 13/12/2007. - * Copyright 2007 Queen Mary, University of London. All rights reserved. - * - */ + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + #ifndef _RDF_SINGLE_PLUGIN_WRITER_H_ #define _RDF_SINGLE_PLUGIN_WRITER_H_ Modified: runner/trunk/SimpleRDFFeatureWriter.cpp =================================================================== --- runner/trunk/SimpleRDFFeatureWriter.cpp 2008-03-19 13:54:37 UTC (rev 1020) +++ runner/trunk/SimpleRDFFeatureWriter.cpp 2008-03-19 16:23:47 UTC (rev 1021) @@ -1,14 +1,18 @@ /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + /* - * SimpleRDFFeatureWriter.cpp - * vamphost - * - * Created by Chris Sutton on 01/11/2007. - * Using code from Yves Raimond as a basis. - * Copyright 2007 Queen Mary, University of London. All rights reserved. - * - */ + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + #include <iostream> #include <map> using namespace std; Modified: runner/trunk/SimpleRDFFeatureWriter.h =================================================================== --- runner/trunk/SimpleRDFFeatureWriter.h 2008-03-19 13:54:37 UTC (rev 1020) +++ runner/trunk/SimpleRDFFeatureWriter.h 2008-03-19 16:23:47 UTC (rev 1021) @@ -1,13 +1,18 @@ /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + /* - * SimpleRDFFeatureWriter.h - * vamphost - * - * Created by Chris Sutton on 01/11/2007. - * Copyright 2007 Queen Mary, University of London. All rights reserved. - * - */ + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + #ifndef _SIMPLE_RDF_FEATURE_WRITER_H_ #define _SIMPLE_RDF_FEATURE_WRITER_H_ Modified: runner/trunk/main.cpp =================================================================== --- runner/trunk/main.cpp 2008-03-19 13:54:37 UTC (rev 1020) +++ runner/trunk/main.cpp 2008-03-19 16:23:47 UTC (rev 1021) @@ -1,13 +1,18 @@ /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + /* - * main.cpp - * vamphost - * - * Created by Mark Levy on 02/11/2007. - * Copyright 2007 Queen Mary, University of London. All rights reserved. - * - */ + Sonic Annotator + A utility for batch feature extraction from audio files. + Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London. + Copyright 2007-2008 QMUL. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + #include <vector> #include <string> #include <iostream> @@ -15,15 +20,21 @@ #include <QCoreApplication> #include <QStringList> +#include <QString> -using std::cout; using std::endl; +using std::cout; +using std::cerr; +using std::endl; using std::vector; using std::string; +#include "data/fileio/AudioFileReaderFactory.h" + +#include "transform/Transform.h" +#include "transform/TransformFactory.h" + #include "FeatureExtractionManager.h" -//#include "DefaultFeatureWriter.h" -//#include "RDFFeatureWriter.h" -//#include "AudioDBFeatureWriter.h" +#include "FeatureWriter.h" #include "FeatureWriterFactory.h" // Desired options: @@ -81,7 +92,128 @@ // - supply file names or URIs on command line // - use all files in a given directory or tree +void usage() +{ + set<string> writers = FeatureWriterFactory::getWriterTags(); + + cerr << endl; + cerr << "Sonic Annotator" << endl; + cerr << "A utility for batch feature extraction from audio files." << endl; + cerr << "Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London." << endl; + cerr << "Copyright 2007-2008 QMUL. Distributed under the GNU General Public License." << endl; + cerr << endl; + cerr << " Usage: runner [options] <audiofile ...> <transformfile ...>" << endl; + cerr << endl; + cerr << "Where <audiofile> is an audio file to use as input, and <transformfile> is a " << endl; + cerr << "file containing an XML description of a transform to be applied. Either of" << endl; + cerr << "these may alternatively be an M3U-format playlist file containing a list of" << endl; + cerr << "audio and/or transform files. Files may be given using either local file" << endl; + cerr << "paths, local \"file://\" URLs, or remote \"http://\" or \"ftp://\" URLs." << endl; + cerr << endl; + cerr << "Any number of audio and transform files may be provided in any order. All" << endl; + cerr << "transforms will be applied to all input files regardless of the given order." << endl; + cerr << endl; + QString extensions = AudioFileReaderFactory::getKnownExtensions(); + QStringList extlist = extensions.split(" ", QString::SkipEmptyParts); + if (!extlist.empty()) { + cerr << "The following audio file types are supported:" << endl; + cerr << " * "; + int c = 4; + for (int i = 0; i < extlist.size(); ++i) { + QString ext = extlist[i]; + if (ext.startsWith("*.")) ext = ext.right(ext.length()-2); + c += ext.length() + 2; + if (c >= 80) { + cerr << "\n "; + c -= 76; + } + cerr << ext.toStdString(); + if (i + 1 == extlist.size()) cerr << "."; + else cerr << ", "; + } + cerr << endl; + } + + cerr << endl; + cerr << "General options:" << endl; + cerr << endl; + cerr << " -w, --writer <W> Write output using writer type <W>." << endl; + cerr << " Supported writer types are: "; + for (set<string>::const_iterator i = writers.begin(); + i != writers.end(); ) { + cerr << *i; + if (++i != writers.end()) cerr << ", "; + else cerr << "."; + } + cerr << endl; + cerr << " You may supply this option multiple times." << endl; + cerr << endl; + cerr << " -m, --multiplex If multiple input audio files are given, use mono" << endl; + cerr << " mixdowns of all files as the input channels for a single" << endl; + cerr << " invocation of each transform, instead of running the" << endl; + cerr << " transform against all files separately." << endl; + cerr << endl; + cerr << " -L, --list List all known transform ids to standard output." << endl; + cerr << endl; + cerr << " -S, --skeleton <T> Generate a skeleton transform file for transform id <T>" << endl; + cerr << " and write it to standard output." << endl; + + cerr << endl; + cerr << "If no -w or --writer options are supplied, exactly one of the -L or -S options" << endl; + cerr << "must be given instead." << endl; + + for (set<string>::const_iterator i = writers.begin(); + i != writers.end(); ++i) { + FeatureWriter *w = FeatureWriterFactory::createWriter(*i); + if (!w) { + cerr << " (Internal error: failed to create writer of this type)" << endl; + continue; + } + map<string, string> params = w->getSupportedParameters(); + delete w; + if (params.empty()) { + continue; + } + cerr << endl; + cerr << "Additional options for writer type \"" << *i << "\":" << endl; + cerr << endl; + for (map<string, string>::const_iterator j = params.begin(); + j != params.end(); ++j) { + cerr << " --" << *i << "-" << j->first << " "; + for (int k = 0; k < 16 - int(i->length()) - int(j->first.length()); ++k) cerr << " "; + QString s(j->second.c_str()); + s.replace("\n", "\n "); + cerr << s.toStdString() << endl; + } + } + + cerr << endl; + exit(2); +} + +void +listTransforms() +{ + TransformList transforms = + TransformFactory::getInstance()->getAllTransformDescriptions(); + + for (TransformList::const_iterator iter = transforms.begin(); + iter != transforms.end(); ++iter) { + const TransformDescription &transform = *iter; + cout << transform.identifier.toStdString() << endl; + } +} + +void +printSkeleton(QString id) +{ + Transform transform = + TransformFactory::getInstance()->getDefaultTransformFor(id); + QString xml = transform.toXmlString(); + cout << xml.toStdString(); +} + int main(int argc, char **argv) { QCoreApplication application(argc, argv); @@ -92,6 +224,15 @@ QStringList args = application.arguments(); + //!!! + listTransforms(); + + //!!! + printSkeleton("vamp:qm-vamp-plugins:qm-mfcc:coefficients"); + + //!!! + usage(); + FeatureExtractionManager manager; // the manager dictates the sample rate and number of channels @@ -124,14 +265,6 @@ if (writer) writers.push_back(writer); /* - // list all the available plugins as transforms - TransformList transforms = TransformFactory::getInstance()->getAllTransformDescriptions(); - for (TransformList::iterator iter = transforms.begin(); iter != transforms.end(); ++iter) - { - TransformDescription transform = *iter; - - cerr << transform.identifier.toStdString() << endl << endl; - } */ // we may want to work from saved transforms here if we This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ca...@us...> - 2008-03-19 17:19:37
|
Revision: 1022 http://sv1.svn.sourceforge.net/sv1/?rev=1022&view=rev Author: cannam Date: 2008-03-19 10:19:35 -0700 (Wed, 19 Mar 2008) Log Message: ----------- * More options stuff Modified Paths: -------------- runner/trunk/FeatureWriterFactory.cpp runner/trunk/main.cpp Modified: runner/trunk/FeatureWriterFactory.cpp =================================================================== --- runner/trunk/FeatureWriterFactory.cpp 2008-03-19 16:23:47 UTC (rev 1021) +++ runner/trunk/FeatureWriterFactory.cpp 2008-03-19 17:19:35 UTC (rev 1022) @@ -16,6 +16,7 @@ #include "FeatureWriterFactory.h" +#include "DefaultFeatureWriter.h" #include "RDFFeatureWriter.h" #include "AudioDBFeatureWriter.h" @@ -23,6 +24,7 @@ FeatureWriterFactory::getWriterTags() { set<string> tags; + tags.insert("default"); tags.insert("rdf"); tags.insert("audiodb"); // tags.insert("csv"); @@ -32,7 +34,9 @@ FeatureWriter * FeatureWriterFactory::createWriter(string tag) { - if (tag == "rdf") { + if (tag == "default") { + return new DefaultFeatureWriter(); + } else if (tag == "rdf") { return new RDFFeatureWriter(); } else if (tag == "audiodb") { return new AudioDBFeatureWriter(); Modified: runner/trunk/main.cpp =================================================================== --- runner/trunk/main.cpp 2008-03-19 16:23:47 UTC (rev 1021) +++ runner/trunk/main.cpp 2008-03-19 17:19:35 UTC (rev 1022) @@ -17,10 +17,10 @@ #include <string> #include <iostream> - #include <QCoreApplication> #include <QStringList> #include <QString> +#include <QFileInfo> using std::cout; using std::cerr; @@ -92,7 +92,7 @@ // - supply file names or URIs on command line // - use all files in a given directory or tree -void usage() +void usage(QString myname) { set<string> writers = FeatureWriterFactory::getWriterTags(); @@ -100,18 +100,23 @@ cerr << "Sonic Annotator" << endl; cerr << "A utility for batch feature extraction from audio files." << endl; cerr << "Mark Levy, Chris Sutton and Chris Cannam, Queen Mary, University of London." << endl; - cerr << "Copyright 2007-2008 QMUL. Distributed under the GNU General Public License." << endl; + cerr << "Copyright 2007-2008 Queen Mary, University of London." << endl; cerr << endl; - cerr << " Usage: runner [options] <audiofile ...> <transformfile ...>" << endl; + cerr << "This program is free software. You may redistribute copies of it under the" << endl; + cerr << "terms of the GNU General Public License <http://www.gnu.org/licenses/gpl.html>." << endl; + cerr << "This program is supplied with NO WARRANTY, to the extent permitted by law." << endl; cerr << endl; - cerr << "Where <audiofile> is an audio file to use as input, and <transformfile> is a " << endl; + cerr << " Usage: " << myname.toStdString() + << " [options] <audiofile ...> <transformfile ...>" << endl; + cerr << endl; + cerr << "Where <audiofile> is an audio file to use as input and <transformfile> is a " << endl; cerr << "file containing an XML description of a transform to be applied. Either of" << endl; cerr << "these may alternatively be an M3U-format playlist file containing a list of" << endl; cerr << "audio and/or transform files. Files may be given using either local file" << endl; cerr << "paths, local \"file://\" URLs, or remote \"http://\" or \"ftp://\" URLs." << endl; cerr << endl; - cerr << "Any number of audio and transform files may be provided in any order. All" << endl; - cerr << "transforms will be applied to all input files regardless of the given order." << endl; + cerr << "Any number of audio and transform files may be provided in any order: all" << endl; + cerr << "of the transforms will be applied to all of the input files." << endl; cerr << endl; QString extensions = AudioFileReaderFactory::getKnownExtensions(); @@ -136,7 +141,7 @@ } cerr << endl; - cerr << "General options:" << endl; + cerr << "Transformation options:" << endl; cerr << endl; cerr << " -w, --writer <W> Write output using writer type <W>." << endl; cerr << " Supported writer types are: "; @@ -154,15 +159,24 @@ cerr << " invocation of each transform, instead of running the" << endl; cerr << " transform against all files separately." << endl; cerr << endl; - cerr << " -L, --list List all known transform ids to standard output." << endl; + cerr << " -r, --recursive If any of the <audiofile> arguments is found to be a" << endl; + cerr << " directory, search the tree starting at that directory" << endl; + cerr << " for all supported audio files and take all of those as" << endl; + cerr << " input instead." << endl; cerr << endl; - cerr << " -S, --skeleton <T> Generate a skeleton transform file for transform id <T>" << endl; + cerr << "Housekeeping options:" << endl; + cerr << endl; + cerr << " -l, --list List all known transform ids to standard output." << endl; + cerr << endl; + cerr << " -s, --skeleton <T> Generate a skeleton transform file for transform id <T>" << endl; cerr << " and write it to standard output." << endl; - cerr << endl; - cerr << "If no -w or --writer options are supplied, exactly one of the -L or -S options" << endl; - cerr << "must be given instead." << endl; + cerr << " -h, --help Show this help." << endl; + cerr << endl; + cerr << "If no -w (or --writer) options are supplied, either the -l or -s option (or" << endl; + cerr << "long equivalent) must be given instead." << endl; + for (set<string>::const_iterator i = writers.begin(); i != writers.end(); ++i) { FeatureWriter *w = FeatureWriterFactory::createWriter(*i); @@ -220,19 +234,94 @@ QCoreApplication::setOrganizationName("QMUL"); QCoreApplication::setOrganizationDomain("qmul.ac.uk"); - QCoreApplication::setApplicationName("runner"); + QCoreApplication::setApplicationName("Sonic Annotator"); QStringList args = application.arguments(); + vector<string> requestedWriterTags; + bool multiplex = false; + bool recursive = false; + bool list = false; + QString skeletonFor; + QString myname = args[0]; + myname = QFileInfo(myname).baseName(); - //!!! - listTransforms(); - - //!!! - printSkeleton("vamp:qm-vamp-plugins:qm-mfcc:coefficients"); + QString helpStr = myname + ": use --help option for help"; - //!!! - usage(); + for (int i = 1; i < args.size(); ++i) { + QString arg = args[i]; + bool last = ((i + 1) == args.size()); + + if (arg == "-h" || arg == "--help" || arg == "-?") { + usage(myname); + } + + if (arg == "-w" || arg == "--writer") { + if (last || args[i+1].startsWith("-")) { + cerr << myname.toStdString() << ": Usage: " + << myname.toStdString() << " [" << arg.toStdString() + << " <writer>] <audiofile> <transformfile>" << endl; + cerr << helpStr.toStdString() << endl; + exit(2); + } else { + requestedWriterTags.push_back(args[++i].toStdString()); + continue; + } + } else if (arg == "-m" || arg == "--multiplex") { + multiplex = true; + cerr << myname.toStdString() + << ": WARNING: Multiplex argument not yet implemented" << endl; //!!! + continue; + } else if (arg == "-r" || arg == "--recursive") { + recursive = true; + cerr << myname.toStdString() + << ": WARNING: Recursive argument not yet implemented" << endl; //!!! + continue; + } else if (arg == "-l" || arg == "--list") { + list = true; + continue; + } else if (arg == "-s" || arg == "--skeleton") { + if (last || args[i+1].startsWith("-")) { + cerr << myname.toStdString() << ": Usage: " + << myname.toStdString() << " " << arg.toStdString() + << " <transform>" << endl; + cerr << helpStr.toStdString() << endl; + exit(2); + } else { + skeletonFor = args[++i]; + continue; + } + } else { + //... + } + } + + if (list) { + if (!requestedWriterTags.empty() || skeletonFor != "") { + cerr << helpStr.toStdString() << endl; + exit(2); + } + listTransforms(); + exit(0); + } + if (skeletonFor != "") { + if (!requestedWriterTags.empty()) { + cerr << helpStr.toStdString() << endl; + exit(2); + } + printSkeleton(skeletonFor); + exit(0); + } + + if (requestedWriterTags.empty()) { + cerr << myname.toStdString() + << ": No writer(s) specified" << endl; + cerr << helpStr.toStdString() << endl; + exit(2); + } + + exit(-1); + FeatureExtractionManager manager; // the manager dictates the sample rate and number of channels This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ca...@us...> - 2008-03-19 20:37:26
|
Revision: 1024 http://sv1.svn.sourceforge.net/sv1/?rev=1024&view=rev Author: cannam Date: 2008-03-19 13:37:24 -0700 (Wed, 19 Mar 2008) Log Message: ----------- ... Modified Paths: -------------- runner/trunk/RDFFeatureWriter.cpp runner/trunk/main.cpp Modified: runner/trunk/RDFFeatureWriter.cpp =================================================================== --- runner/trunk/RDFFeatureWriter.cpp 2008-03-19 20:23:26 UTC (rev 1023) +++ runner/trunk/RDFFeatureWriter.cpp 2008-03-19 20:37:24 UTC (rev 1024) @@ -43,11 +43,10 @@ RDFFeatureWriter::getSupportedParameters() const { map<string, string> params; - params["one-file"] = "Create one output file only:\nall transforms for all inputs written to the same file"; - params["per-input"] = "Create one output file for each input file:\nall transforms for that input written to the same file"; - params["per-transform"] = "Create output file for each transform on each input"; - params["plain"] = "Use \"plain\" RDF even if transform metadata is available"; - params["basedir"] = "Base output directory path (default same as input file)"; + params["one-file"] = "Create one output file only, and write all transform\nresults for all input files into it."; + params["many-files"] = "Create a separate output file for every combination of\ninput file and transform.\n(The default is to create one output file per input\naudio file, and write all transform results for that\ninput file into it.)"; + params["plain"] = "Use \"plain\" RDF even if transform metadata is available."; + params["basedir"] = "Base output directory path.\n(The default is the same directory as the input file.)"; return params; } Modified: runner/trunk/main.cpp =================================================================== --- runner/trunk/main.cpp 2008-03-19 20:23:26 UTC (rev 1023) +++ runner/trunk/main.cpp 2008-03-19 20:37:24 UTC (rev 1024) @@ -122,16 +122,16 @@ QString extensions = AudioFileReaderFactory::getKnownExtensions(); QStringList extlist = extensions.split(" ", QString::SkipEmptyParts); if (!extlist.empty()) { - cerr << "The following audio file types are supported:" << endl; - cerr << " * "; - int c = 4; + cerr << "The following audio file extensions are recognised:" << endl; + cerr << " "; + int c = 2; for (int i = 0; i < extlist.size(); ++i) { QString ext = extlist[i]; if (ext.startsWith("*.")) ext = ext.right(ext.length()-2); c += ext.length() + 2; if (c >= 80) { - cerr << "\n "; - c -= 76; + cerr << "\n "; + c -= 78; } cerr << ext.toStdString(); if (i + 1 == extlist.size()) cerr << "."; @@ -245,7 +245,7 @@ QString myname = args[0]; myname = QFileInfo(myname).baseName(); - QString helpStr = myname + ": use --help option for help"; + QString helpStr = myname + ": use -h or --help option for help"; for (int i = 1; i < args.size(); ++i) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ca...@us...> - 2008-03-20 15:59:04
|
Revision: 1025 http://sv1.svn.sourceforge.net/sv1/?rev=1025&view=rev Author: cannam Date: 2008-03-20 08:59:00 -0700 (Thu, 20 Mar 2008) Log Message: ----------- * overhaul options again a bit: have explicit -t for transforms * flesh out implementation a bit more Modified Paths: -------------- runner/trunk/AudioDBFeatureWriter.cpp runner/trunk/AudioDBFeatureWriter.h runner/trunk/FeatureWriter.h runner/trunk/RDFFeatureWriter.cpp runner/trunk/RDFFeatureWriter.h runner/trunk/main.cpp Modified: runner/trunk/AudioDBFeatureWriter.cpp =================================================================== --- runner/trunk/AudioDBFeatureWriter.cpp 2008-03-19 20:37:24 UTC (rev 1024) +++ runner/trunk/AudioDBFeatureWriter.cpp 2008-03-20 15:59:00 UTC (rev 1025) @@ -50,25 +50,35 @@ // TODO: error handling on close } -map<string, string> +AudioDBFeatureWriter::ParameterList AudioDBFeatureWriter::getSupportedParameters() const { - map<string, string> params; - params[catalogueIdParam] = "Catalogue ID"; - params[baseDirParam] = "Base output directory path"; - return params; + ParameterList pl; + Parameter p; + + p.name = catalogueIdParam; + p.description = "Catalogue ID"; + p.hasArg = true; + pl.push_back(p); + + p.name = baseDirParam; + p.description = "Base output directory path"; + p.hasArg = true; + pl.push_back(p); + + return pl; } void AudioDBFeatureWriter::setParameters(map<string, string> ¶ms) { - if (params.find("catalogue") != params.end()) { - setCatalogueId(params["catalogue"]); - params.erase("catalogue"); + if (params.find(catalogueIdParam) != params.end()) { + setCatalogueId(params[catalogueIdParam]); + params.erase(catalogueIdParam); } - if (params.find("basedir") != params.end()) { - setCatalogueId(params["basedir"]); - params.erase("basedir"); + if (params.find(baseDirParam) != params.end()) { + setCatalogueId(params[baseDirParam]); + params.erase(baseDirParam); } } Modified: runner/trunk/AudioDBFeatureWriter.h =================================================================== --- runner/trunk/AudioDBFeatureWriter.h 2008-03-19 20:37:24 UTC (rev 1024) +++ runner/trunk/AudioDBFeatureWriter.h 2008-03-20 15:59:00 UTC (rev 1025) @@ -30,7 +30,7 @@ AudioDBFeatureWriter(); virtual ~AudioDBFeatureWriter(); - virtual map<string, string> getSupportedParameters() const; + virtual ParameterList getSupportedParameters() const; virtual void setParameters(map<string, string> ¶ms); virtual void setCatalogueId(const string &); Modified: runner/trunk/FeatureWriter.h =================================================================== --- runner/trunk/FeatureWriter.h 2008-03-19 20:37:24 UTC (rev 1024) +++ runner/trunk/FeatureWriter.h 2008-03-20 15:59:00 UTC (rev 1025) @@ -18,19 +18,27 @@ #include <string> #include <map> +#include <vector> #include <vamp-sdk/Plugin.h> using std::string; using std::map; +using std::vector; class FeatureWriter { public: virtual ~FeatureWriter() { } - virtual map<string, string> getSupportedParameters() const { - return map<string, string>(); + struct Parameter { + string name; + string description; + bool hasArg; + }; + typedef vector<Parameter> ParameterList; + virtual ParameterList getSupportedParameters() const { + return ParameterList(); } virtual void setParameters(map<string, string> ¶ms) { Modified: runner/trunk/RDFFeatureWriter.cpp =================================================================== --- runner/trunk/RDFFeatureWriter.cpp 2008-03-19 20:37:24 UTC (rev 1024) +++ runner/trunk/RDFFeatureWriter.cpp 2008-03-20 15:59:00 UTC (rev 1025) @@ -39,21 +39,43 @@ } } -map<string, string> +RDFFeatureWriter::ParameterList RDFFeatureWriter::getSupportedParameters() const { - map<string, string> params; - params["one-file"] = "Create one output file only, and write all transform\nresults for all input files into it."; - params["many-files"] = "Create a separate output file for every combination of\ninput file and transform.\n(The default is to create one output file per input\naudio file, and write all transform results for that\ninput file into it.)"; - params["plain"] = "Use \"plain\" RDF even if transform metadata is available."; - params["basedir"] = "Base output directory path.\n(The default is the same directory as the input file.)"; - return params; + ParameterList pl; + Parameter p; + + p.name = "basedir"; + p.description = "Base output directory path.\n(The default is the same directory as the input file.)"; + p.hasArg = true; + pl.push_back(p); + + p.name = "many-files"; + p.description = "Create a separate output file for every combination of\ninput file and transform.\n(The default is to create one output file per input\naudio file, and write all transform results for that\ninput file into it.)"; + p.hasArg = false; + pl.push_back(p); + + p.name = "one-file"; + p.description = "Create one output file only, and write all transform\nresults for all input files into it."; + p.hasArg = false; + pl.push_back(p); + + p.name = "plain"; + p.description = "Use \"plain\" RDF even if transform metadata is available."; + p.hasArg = false; + pl.push_back(p); + + return pl; } void RDFFeatureWriter::setParameters(map<string, string> ¶ms) { - //!!! implement + cerr << "RDFFeatureWriter::setParameters" << endl; + for (map<string, string>::iterator i = params.begin(); + i != params.end(); ++i) { + cerr << i->first << " -> " << i->second << endl; + } } void RDFFeatureWriter::write(const string& trackid, Modified: runner/trunk/RDFFeatureWriter.h =================================================================== --- runner/trunk/RDFFeatureWriter.h 2008-03-19 20:37:24 UTC (rev 1024) +++ runner/trunk/RDFFeatureWriter.h 2008-03-20 15:59:00 UTC (rev 1025) @@ -31,7 +31,7 @@ RDFFeatureWriter(); virtual ~RDFFeatureWriter(); - virtual map<string, string> getSupportedParameters() const; + virtual ParameterList getSupportedParameters() const; virtual void setParameters(map<string, string> ¶ms); virtual void write(const string& trackid, Modified: runner/trunk/main.cpp =================================================================== --- runner/trunk/main.cpp 2008-03-19 20:37:24 UTC (rev 1024) +++ runner/trunk/main.cpp 2008-03-20 15:59:00 UTC (rev 1025) @@ -29,6 +29,7 @@ using std::string; #include "data/fileio/AudioFileReaderFactory.h" +#include "data/fileio/PlaylistFileReader.h" #include "transform/Transform.h" #include "transform/TransformFactory.h" @@ -107,17 +108,17 @@ cerr << "This program is supplied with NO WARRANTY, to the extent permitted by law." << endl; cerr << endl; cerr << " Usage: " << myname.toStdString() - << " [options] <audiofile ...> <transformfile ...>" << endl; + << " [-mr] -t trans.xml [...] -w <writer> [...] <audio> [...]" << endl; + cerr << " " << myname.toStdString() + << " [-mr] -T trans.txt [...] -w <writer> [...] <audio> [...]" << endl; + cerr << " " << myname.toStdString() + << " -s <transform>" << endl; + cerr << " " << myname.toStdString() + << " [-lh]" << endl; cerr << endl; - cerr << "Where <audiofile> is an audio file to use as input and <transformfile> is a " << endl; - cerr << "file containing an XML description of a transform to be applied. Either of" << endl; - cerr << "these may alternatively be an M3U-format playlist file containing a list of" << endl; - cerr << "audio and/or transform files. Files may be given using either local file" << endl; - cerr << "paths, local \"file://\" URLs, or remote \"http://\" or \"ftp://\" URLs." << endl; + cerr << "Where <audio> is an audio file or URL to use as input: either a local file" << endl; + cerr << "path, local \"file://\" URL, or remote \"http://\" or \"ftp://\" URL." << endl; cerr << endl; - cerr << "Any number of audio and transform files may be provided in any order: all" << endl; - cerr << "of the transforms will be applied to all of the input files." << endl; - cerr << endl; QString extensions = AudioFileReaderFactory::getKnownExtensions(); QStringList extlist = extensions.split(" ", QString::SkipEmptyParts); @@ -140,9 +141,19 @@ cerr << endl; } + cerr << "Playlist files in M3U format are also supported." << endl; cerr << endl; cerr << "Transformation options:" << endl; cerr << endl; + cerr << " -t, --transform <T> Apply transform described in transform XML file <T> to" << endl; + cerr << " all input audio files. You may supply this option" << endl; + cerr << " multiple times. You must supply this option or -T at" << endl; + cerr << " least once for any work to be done." << endl; + cerr << endl; + cerr << " -T, --transforms <T> Apply all transforms described in transform XML files" << endl; + cerr << " whose names are listed in text file <T>. You may supply" << endl; + cerr << " this option multiple times." << endl; + cerr << endl; cerr << " -w, --writer <W> Write output using writer type <W>." << endl; cerr << " Supported writer types are: "; for (set<string>::const_iterator i = writers.begin(); @@ -152,14 +163,15 @@ else cerr << "."; } cerr << endl; - cerr << " You may supply this option multiple times." << endl; + cerr << " You may supply this option multiple times. You must" << endl; + cerr << " supply this option at least once for any work to be done." << endl; cerr << endl; cerr << " -m, --multiplex If multiple input audio files are given, use mono" << endl; cerr << " mixdowns of all files as the input channels for a single" << endl; cerr << " invocation of each transform, instead of running the" << endl; cerr << " transform against all files separately." << endl; cerr << endl; - cerr << " -r, --recursive If any of the <audiofile> arguments is found to be a" << endl; + cerr << " -r, --recursive If any of the <audio> arguments is found to be a local" << endl; cerr << " directory, search the tree starting at that directory" << endl; cerr << " for all supported audio files and take all of those as" << endl; cerr << " input instead." << endl; @@ -184,7 +196,7 @@ cerr << " (Internal error: failed to create writer of this type)" << endl; continue; } - map<string, string> params = w->getSupportedParameters(); + FeatureWriter::ParameterList params = w->getSupportedParameters(); delete w; if (params.empty()) { continue; @@ -192,11 +204,13 @@ cerr << endl; cerr << "Additional options for writer type \"" << *i << "\":" << endl; cerr << endl; - for (map<string, string>::const_iterator j = params.begin(); + for (FeatureWriter::ParameterList::const_iterator j = params.begin(); j != params.end(); ++j) { - cerr << " --" << *i << "-" << j->first << " "; - for (int k = 0; k < 16 - int(i->length()) - int(j->first.length()); ++k) cerr << " "; - QString s(j->second.c_str()); + cerr << " --" << *i << "-" << j->name << " "; + int spaceage = 16 - int(i->length()) - int(j->name.length()); + if (j->hasArg) { cerr << "<X> "; spaceage -= 4; } + for (int k = 0; k < spaceage; ++k) cerr << " "; + QString s(j->description.c_str()); s.replace("\n", "\n "); cerr << s.toStdString() << endl; } @@ -237,13 +251,16 @@ QCoreApplication::setApplicationName("Sonic Annotator"); QStringList args = application.arguments(); - vector<string> requestedWriterTags; + set<string> requestedWriterTags; + set<string> requestedTransformFiles; + set<string> requestedTransformListFiles; bool multiplex = false; bool recursive = false; bool list = false; QString skeletonFor; QString myname = args[0]; myname = QFileInfo(myname).baseName(); + QStringList otherArgs; QString helpStr = myname + ": use -h or --help option for help"; @@ -258,15 +275,51 @@ if (arg == "-w" || arg == "--writer") { if (last || args[i+1].startsWith("-")) { - cerr << myname.toStdString() << ": Usage: " - << myname.toStdString() << " [" << arg.toStdString() - << " <writer>] <audiofile> <transformfile>" << endl; + cerr << myname.toStdString() << ": argument expected for \"" + << arg.toStdString() << "\" option" << endl; cerr << helpStr.toStdString() << endl; exit(2); } else { - requestedWriterTags.push_back(args[++i].toStdString()); + string tag = args[++i].toStdString(); + if (requestedWriterTags.find(tag) != requestedWriterTags.end()) { + cerr << myname.toStdString() << ": NOTE: duplicate specification of writer type \"" << tag << "\" ignored" << endl; + } else { + requestedWriterTags.insert(tag); + } continue; } + } else if (arg == "-t" || arg == "--transform") { + if (last || args[i+1].startsWith("-")) { + cerr << myname.toStdString() << ": argument expected for \"" + << arg.toStdString() << "\" option" << endl; + cerr << helpStr.toStdString() << endl; + exit(2); + } else { + string transform = args[++i].toStdString(); + if (requestedTransformFiles.find(transform) != + requestedTransformFiles.end()) { + cerr << myname.toStdString() << ": NOTE: duplicate specification of transform file \"" << transform << "\" ignored" << endl; + } else { + requestedTransformFiles.insert(transform); + } + continue; + } + } else if (arg == "-T" || arg == "--transforms") { + if (last || args[i+1].startsWith("-")) { + cerr << myname.toStdString() << ": argument expected for \"" + << arg.toStdString() << "\" option" << endl; + cerr << helpStr.toStdString() << endl; + exit(2); + } else { + string transform = args[++i].toStdString(); + if (requestedTransformListFiles.find(transform) != + requestedTransformListFiles.end()) { + cerr << myname.toStdString() << ": NOTE: duplicate specification of transform list file \"" << transform << "\" ignored" << endl; + } else { + requestedTransformListFiles.insert(transform); + } + continue; + } } else if (arg == "-m" || arg == "--multiplex") { multiplex = true; cerr << myname.toStdString() @@ -282,7 +335,7 @@ continue; } else if (arg == "-s" || arg == "--skeleton") { if (last || args[i+1].startsWith("-")) { - cerr << myname.toStdString() << ": Usage: " + cerr << myname.toStdString() << ": usage: " << myname.toStdString() << " " << arg.toStdString() << " <transform>" << endl; cerr << helpStr.toStdString() << endl; @@ -292,7 +345,7 @@ continue; } } else { - //... + otherArgs.push_back(args[i]); } } @@ -313,15 +366,21 @@ exit(0); } + if (requestedTransformFiles.empty() && + requestedTransformListFiles.empty()) { + cerr << myname.toStdString() + << ": no transform(s) specified" << endl; + cerr << helpStr.toStdString() << endl; + exit(2); + } + if (requestedWriterTags.empty()) { cerr << myname.toStdString() - << ": No writer(s) specified" << endl; + << ": no writer(s) specified" << endl; cerr << helpStr.toStdString() << endl; exit(2); } - exit(-1); - FeatureExtractionManager manager; // the manager dictates the sample rate and number of channels @@ -335,26 +394,93 @@ manager.setSampleRate(22050); // always work at this rate manager.setChannels(1); - vector<FeatureWriter*> writers; - // writers.push_back(new DefaultFeatureWriter()); // for debug - - if (argc <= 1) // no args supplied - { - cout<<" Usage : runner writertype audiofile transformfile"<<endl; - cout<<" eg. runner rdf test.mp3 transforms/tempotracker.xml"<<endl; - exit(-1); + vector<FeatureWriter *> writers; + + for (set<string>::const_iterator i = requestedWriterTags.begin(); + i != requestedWriterTags.end(); ++i) { + + FeatureWriter *writer = FeatureWriterFactory::createWriter(*i); + + if (!writer) { + cerr << myname.toStdString() << ": unknown feature writer \"" + << *i << "\"" << endl; + cerr << helpStr.toStdString() << endl; + exit(2); + } + + map<string, string> writerArgs; + FeatureWriter::ParameterList pl(writer->getSupportedParameters()); + + for (int k = 0; k < pl.size(); ++k) { + + string argbase = pl[k].name; + QString literal = QString("--%1-%2") + .arg(i->c_str()).arg(argbase.c_str()); + + for (int j = 0; j < otherArgs.size(); ) { + + if (otherArgs[j] != literal) { + ++j; + continue; + } + + otherArgs.removeAt(j); + + if (pl[k].hasArg) { + if (j < otherArgs.size()) { + writerArgs[argbase] = otherArgs[j].toStdString(); + otherArgs.removeAt(j); + } else { + cerr << myname.toStdString() << ": " + << "argument required for \"" + << literal.toStdString() << "\" option" + << endl; + cerr << helpStr.toStdString() << endl; + exit(2); + } + } else { + writerArgs[argbase] = ""; + } + } + } + + writer->setParameters(writerArgs); + + writers.push_back(writer); } - - string writerType = ""; - if (args.size() > 1) - writerType = args[1].toStdString(); + for (int i = 0; i < otherArgs.size(); ++i) { + if (otherArgs[i].startsWith("-")) { + cerr << myname.toStdString() << ": unknown option \"" + << otherArgs[i].toStdString() << "\"" << endl; + cerr << helpStr.toStdString() << endl; + exit(2); + } + } - FeatureWriter *writer = FeatureWriterFactory::createWriter(writerType); - if (writer) writers.push_back(writer); + if (otherArgs.empty()) { + cerr << myname.toStdString() << ": no input(s) specified" << endl; + cerr << helpStr.toStdString() << endl; + exit(2); + } + + for (set<string>::const_iterator i = requestedTransformListFiles.begin(); + i != requestedTransformListFiles.end(); ++i) { + PlaylistFileReader reader(i->c_str()); + if (reader.isOK()) { + vector<QString> files = reader.load(); + for (int j = 0; j < files.size(); ++j) { + requestedTransformFiles.insert(files[j].toStdString()); + } + } else { + cerr << myname.toStdString() << ": failed to read template list file \"" << *i << "\"" << endl; + exit(2); + } + } - /* - */ + + //!!! + exit (-1); // we may want to work from saved transforms here if we // already know what features we want This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ca...@us...> - 2008-03-26 14:38:41
|
Revision: 1030 http://sv1.svn.sourceforge.net/sv1/?rev=1030&view=rev Author: cannam Date: 2008-03-26 07:38:38 -0700 (Wed, 26 Mar 2008) Log Message: ----------- * implement --recursive Modified Paths: -------------- runner/trunk/FeatureExtractionManager.cpp runner/trunk/main.cpp Modified: runner/trunk/FeatureExtractionManager.cpp =================================================================== --- runner/trunk/FeatureExtractionManager.cpp 2008-03-26 14:35:03 UTC (rev 1029) +++ runner/trunk/FeatureExtractionManager.cpp 2008-03-26 14:38:38 UTC (rev 1030) @@ -154,7 +154,8 @@ cerr << "Opening and/or decoding audio file..." << endl; - AudioFileReader *reader = AudioFileReaderFactory::createReader(source, m_sampleRate); + AudioFileReader *reader = + AudioFileReaderFactory::createReader(source, m_sampleRate, &printer); if (!reader) { Modified: runner/trunk/main.cpp =================================================================== --- runner/trunk/main.cpp 2008-03-26 14:35:03 UTC (rev 1029) +++ runner/trunk/main.cpp 2008-03-26 14:38:38 UTC (rev 1030) @@ -21,6 +21,7 @@ #include <QStringList> #include <QString> #include <QFileInfo> +#include <QDir> using std::cout; using std::cerr; @@ -242,6 +243,34 @@ cout << xml.toStdString(); } +void +findSourcesRecursive(QString dirname, QStringList &addTo, int &found) +{ + QDir dir(dirname); + + QString printable = dir.dirName().left(20); + cerr << "\rScanning \"" << printable.toStdString() << "\"..." + << QString(" ").left(20 - printable.length()).toStdString() + << " [" << found << " audio file(s)]"; + + QString extensions = AudioFileReaderFactory::getKnownExtensions(); + QStringList extlist = extensions.split(" ", QString::SkipEmptyParts); + + QStringList files = dir.entryList + (extlist, QDir::Files | QDir::Readable); + for (int i = 0; i < files.size(); ++i) { + addTo.push_back(dir.filePath(files[i])); + ++found; + } + + QStringList subdirs = dir.entryList + (QStringList(), QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot); + for (int i = 0; i < subdirs.size(); ++i) { + findSourcesRecursive(dir.filePath(subdirs[i]), addTo, found); + } +} + + int main(int argc, char **argv) { QCoreApplication application(argc, argv); @@ -327,8 +356,6 @@ continue; } else if (arg == "-r" || arg == "--recursive") { recursive = true; - cerr << myname.toStdString() - << ": WARNING: Recursive argument not yet implemented" << endl; //!!! continue; } else if (arg == "-l" || arg == "--list") { list = true; @@ -483,8 +510,26 @@ manager.addFeatureExtractor(*i, writers); } - for (QStringList::const_iterator i = otherArgs.begin(); - i != otherArgs.end(); ++i) { + QStringList sources; + if (!recursive) { + sources = otherArgs; + } else { + for (QStringList::const_iterator i = otherArgs.begin(); + i != otherArgs.end(); ++i) { + if (QDir(*i).exists()) { + cerr << "Directory found and recursive flag set, scanning for audio files..." << endl; + int found = 0; + findSourcesRecursive(*i, sources, found); + cerr << "\rDone, found " << found << " supported audio file(s) " << endl; + } else { + sources.push_back(*i); + } + } + } + + for (QStringList::const_iterator i = sources.begin(); + i != sources.end(); ++i) { + std::cerr << "Extracting features for: \"" << i->toStdString() << "\"" << std::endl; manager.extractFeatures(i->toStdString()); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ca...@us...> - 2008-03-27 10:22:44
|
Revision: 1031 http://sv1.svn.sourceforge.net/sv1/?rev=1031&view=rev Author: cannam Date: 2008-03-27 03:15:26 -0700 (Thu, 27 Mar 2008) Log Message: ----------- * some work on overhauling writer API -- incomplete and does not build Modified Paths: -------------- runner/trunk/AudioDBFeatureWriter.cpp runner/trunk/AudioDBFeatureWriter.h runner/trunk/DefaultFeatureWriter.cpp runner/trunk/DefaultFeatureWriter.h runner/trunk/FeatureExtractionManager.cpp runner/trunk/FeatureExtractionManager.h runner/trunk/FeatureWriter.h runner/trunk/RDFFeatureWriter.cpp runner/trunk/RDFFeatureWriter.h runner/trunk/RDFSinglePluginWriter.h runner/trunk/SimpleRDFFeatureWriter.h runner/trunk/main.cpp Modified: runner/trunk/AudioDBFeatureWriter.cpp =================================================================== --- runner/trunk/AudioDBFeatureWriter.cpp 2008-03-26 14:38:38 UTC (rev 1030) +++ runner/trunk/AudioDBFeatureWriter.cpp 2008-03-27 10:15:26 UTC (rev 1031) @@ -28,7 +28,7 @@ struct AudioDBFeatureWriter::TrackStream { - string trackid; + QString trackid; ofstream* ofs; }; @@ -94,10 +94,10 @@ baseDir = base; } -void AudioDBFeatureWriter::write(const string& trackid, - const string& pluginid, - const Plugin::OutputList& outputList, - const Plugin::FeatureSet& featureSet) +void AudioDBFeatureWriter::write(QString trackid, + TransformId transformId, + const Vamp::Plugin::OutputList& outputList, + const Vamp::Plugin::FeatureSet& featureSet) { // binary output for FeatureSet @@ -157,9 +157,10 @@ } } -bool AudioDBFeatureWriter::openDBFile(const string& trackid, const string& identifier) +bool AudioDBFeatureWriter::openDBFile(QString trackid, const string& identifier) { - string filepath = baseDir + "/" + catalogueId + "/" + trackid + "." + identifier; + string filepath = baseDir + "/" + catalogueId + "/" + + trackid.toString() + "." + identifier; ofstream* ofs = new ofstream(filepath.c_str()); if (!*ofs) { @@ -174,7 +175,7 @@ } // replace file if no file open for this track, else return false -bool AudioDBFeatureWriter::replaceDBFile(const string& trackid, +bool AudioDBFeatureWriter::replaceDBFile(QString trackid, const string& identifier) { if (dbfiles.find(identifier) != dbfiles.end() && dbfiles[identifier].trackid == trackid) Modified: runner/trunk/AudioDBFeatureWriter.h =================================================================== --- runner/trunk/AudioDBFeatureWriter.h 2008-03-26 14:38:38 UTC (rev 1030) +++ runner/trunk/AudioDBFeatureWriter.h 2008-03-27 10:15:26 UTC (rev 1031) @@ -36,8 +36,8 @@ virtual void setCatalogueId(const string &); virtual void setBaseDirectory(const string &); - virtual void write(const string& trackid, - const string& pluginid, + virtual void write(QString trackid, + TransformId transformId, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); @@ -51,8 +51,8 @@ struct TrackStream; map<string, TrackStream> dbfiles; - bool openDBFile(const string& trackid, const string& identifier); - bool replaceDBFile(const string& trackid, const string& identifier); + bool openDBFile(QString trackid, const string& identifier); + bool replaceDBFile(QString trackid, const string& identifier); }; #endif Modified: runner/trunk/DefaultFeatureWriter.cpp =================================================================== --- runner/trunk/DefaultFeatureWriter.cpp 2008-03-26 14:38:38 UTC (rev 1030) +++ runner/trunk/DefaultFeatureWriter.cpp 2008-03-27 10:15:26 UTC (rev 1031) @@ -20,7 +20,10 @@ #include "DefaultFeatureWriter.h" -void DefaultFeatureWriter::write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) +void DefaultFeatureWriter::write(QString trackid, + TransformId transformId, + const Vamp::Plugin::OutputList& outputList, + const Vamp::Plugin::FeatureSet& featureSet) { // generic XML output for FeatureSet Modified: runner/trunk/DefaultFeatureWriter.h =================================================================== --- runner/trunk/DefaultFeatureWriter.h 2008-03-26 14:38:38 UTC (rev 1030) +++ runner/trunk/DefaultFeatureWriter.h 2008-03-27 10:15:26 UTC (rev 1031) @@ -23,7 +23,10 @@ { public: virtual ~DefaultFeatureWriter() { } - virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); + virtual void write(QString trackid, + TransformId transformId, + const Vamp::Plugin::OutputList& outputList, + const Vamp::Plugin::FeatureSet& featureSet); }; #endif Modified: runner/trunk/FeatureExtractionManager.cpp =================================================================== --- runner/trunk/FeatureExtractionManager.cpp 2008-03-26 14:38:38 UTC (rev 1030) +++ runner/trunk/FeatureExtractionManager.cpp 2008-03-27 10:15:26 UTC (rev 1031) @@ -23,6 +23,7 @@ #include <vamp-sdk/hostext/PluginLoader.h> using Vamp::Plugin; +using Vamp::PluginBase; using Vamp::HostExt::PluginLoader; using Vamp::HostExt::PluginChannelAdapter; using Vamp::HostExt::PluginBufferingAdapter; @@ -61,71 +62,72 @@ m_sampleRate = sampleRate; } -bool FeatureExtractionManager::addFeatureExtractor(string library, string plugname, vector<FeatureWriter*> writers) +bool FeatureExtractionManager::addDefaultFeatureExtractor +(TransformId transformId, const vector<FeatureWriter*> &writers) { - PluginLoader *loader = PluginLoader::getInstance(); - - PluginLoader::PluginKey key = loader->composePluginKey(library, plugname); - - Plugin* plugin = loader->loadPlugin(key, m_sampleRate, PluginLoader::ADAPT_ALL); + TransformFactory *tf = TransformFactory::getInstance(); + + transform = tf->getDefaultTransformFor(transformId, m_sampleRate); + + PluginBase *pb = tf->instantiatePluginFor(transform); + Plugin *plugin = tf->downcastVampPlugin(pb); if (!plugin) { - cerr << "ERROR: Failed to load plugin \"" << plugin << "\" from library \"" << library << "\"" << endl; + //!!! todo: handle non-Vamp plugins too, or make the main --list + // option print out only Vamp transforms + cerr << "ERROR: Failed to load plugin for transform \"" + << transformId.toStdString() << "\"" << endl; + delete pb; return false; } - + plugins.push_back(plugin); pluginWriters.push_back(writers); - - // create a Transform recording all the parameter settings etc. - Transform transform; - TransformFactory *tf = TransformFactory::getInstance(); - - transform = tf->getDefaultTransformFor - (Transform::getIdentifierForPluginOutput(key.c_str(), ""), - m_sampleRate); - - tf->setParametersFromPlugin(transform, plugin); transforms.push_back(transform); return true; } -bool FeatureExtractionManager::addFeatureExtractor(string transformXmlFile, vector<FeatureWriter*> writers) +bool FeatureExtractionManager::addFeatureExtractorFromFile +(QString transformXmlFile, const vector<FeatureWriter*> &writers) { - FILE* file = fopen(transformXmlFile.c_str(),"r"); - if (!file) { + QFile file(transformXmlFile); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { cerr << "ERROR: Failed to open transform XML file \"" - << transformXmlFile << "\" for reading" << endl; - perror("Failed to open transform file"); + << transformXmlFile.toStdString() << "\" for reading" << endl; return false; } QTextStream *qts = new QTextStream(file); QString qs = qts->readAll(); delete qts; - fclose(file); + file.close(); Transform transform(qs); - if (transform.getSampleRate() != m_sampleRate) - { + if (transform.getSampleRate() != m_sampleRate) { cerr << "ERROR: transform sample rate " << transform.getSampleRate() << " doesn't match the one you set for audio extraction " << m_sampleRate << endl; print(transform); cerr << endl; return false; } - Plugin* plugin = TransformFactory::getInstance()->downcastVampPlugin(TransformFactory::getInstance()->instantiatePluginFor(transform)); + TransformFactory *tf = TransformFactory::getInstance(); + + PluginBase *pb = tf->instantiatePluginFor(transform); + Plugin *plugin = tf->downcastVampPlugin(pb); if (!plugin) { - cerr << "ERROR: Failed to load plugin from transform " << transformXmlFile << endl; - print(transform); - cerr << endl; + //!!! todo: handle non-Vamp plugins too, or make the main --list + // option print out only Vamp transforms + cerr << "ERROR: Failed to load plugin for transform \"" + << transform.getIdentifier().toStdString() << "\"" << endl; + delete pb; return false; } // adapt the plugin for buffering, channels, etc. - if (plugin->getInputDomain() == Plugin::FrequencyDomain) - plugin = new PluginInputDomainAdapter(plugin); + if (plugin->getInputDomain() == Plugin::FrequencyDomain) { + plugin = new PluginInputDomainAdapter(plugin); + } plugin = new PluginBufferingAdapter(plugin); plugin = new PluginChannelAdapter(plugin); @@ -136,39 +138,34 @@ return true; } -void FeatureExtractionManager::extractFeatures(string audioSource) +void FeatureExtractionManager::extractFeatures(QString audioSource) { - cerr << "Creating FileSource..." << endl; - - ProgressPrinter printer("Retrieving data..."); - FileSource source(audioSource.c_str(), &printer); - if (!source.isAvailable()) - { - cerr << "ERROR: File or URL \"" << audioSource << "\" could not be located" << endl; + ProgressPrinter printer("Retrieving audio data..."); + + FileSource source(audioSource, &printer); + if (!source.isAvailable()) { + cerr << "ERROR: File or URL \"" << audioSource.toStdString() + << "\" could not be located" << endl; exit(1); } - cerr << "Retrieving or locating \"" << audioSource << "\"..." << endl; - source.waitForData(); - cerr << "Opening and/or decoding audio file..." << endl; - AudioFileReader *reader = AudioFileReaderFactory::createReader(source, m_sampleRate, &printer); - if (!reader) - { - cerr << "ERROR: File or URL \"" << audioSource << "\" could not be opened" << endl; + if (!reader) { + cerr << "ERROR: File or URL \"" << audioSource.toStdString() + << "\" could not be opened" << endl; exit(1); } - // read using an arbitrary fixed block size - int blockSize = 2048; - int stepSize = 2048; + // We can read using an arbitrary fixed block size -- + // PluginBufferingAdapter handles this for us. It's likely to be + // quicker to use larger sizes than smallish ones like 1024 + int blockSize = 16384; + int stepSize = blockSize; - cerr << "Using block size = " << blockSize << ", step size = " << stepSize << endl; - size_t channels = reader->getChannelCount(); // reject file if it has too few channels, plugin will handle if it has too many @@ -193,7 +190,7 @@ if (!plugins[i]->initialise(m_channels, stepSize, blockSize)) { cerr << "ERROR: Plugin initialise (channels = " << m_channels << ", stepSize = " << stepSize << ", blockSize = " << blockSize << ") failed." << endl; - // TODO: + //!!! TODO: // decide how to handle this error... } } @@ -229,9 +226,15 @@ for (int k = 0; k < plugins.size(); ++k) { - Vamp::Plugin::FeatureSet featureSet = plugins[k]->process(data, timestamp); - for (int j = 0; j < pluginWriters[k].size(); ++j) - pluginWriters[k][j]->write(audioSource.c_str(), plugins[k]->getIdentifier(), plugins[k]->getOutputDescriptors(), featureSet); + Vamp::Plugin::FeatureSet featureSet = + plugins[k]->process(data, timestamp); + for (int j = 0; j < pluginWriters[k].size(); ++j) { + pluginWriters[k][j]->write + (audioSource, + transforms[k].getIdentifier(), + plugins[k]->getOutputDescriptors(), //!!! inefficient + featureSet); + } } } @@ -240,8 +243,9 @@ // we may want to set the start and duration times for extraction // in the transform record (defaults of zero indicate extraction // from the whole file) - transforms[k].setStartTime(RealTime()); - transforms[k].setDuration(RealTime::frame2RealTime(reader->getFrameCount(), m_sampleRate)); + transforms[k].setStartTime(RealTime::zeroTime); + transforms[k].setDuration + (RealTime::frame2RealTime(reader->getFrameCount(), m_sampleRate)); print(transforms[k]); @@ -249,8 +253,13 @@ // in case they wanted to add header information // or even rename files according to some convention - for (int j = 0; j < pluginWriters[k].size(); ++j) - pluginWriters[k][j]->write(audioSource.c_str(), plugins[k]->getIdentifier(), plugins[k]->getOutputDescriptors(), plugins[k]->getRemainingFeatures()); + for (int j = 0; j < pluginWriters[k].size(); ++j) { + pluginWriters[k][j]->write + (audioSource, + transforms[k].getIdentifier(), + plugins[k]->getOutputDescriptors(), //!!! inefficient + plugins[k]->getRemainingFeatures()); + } } TempDirectory::getInstance()->cleanup(); Modified: runner/trunk/FeatureExtractionManager.h =================================================================== --- runner/trunk/FeatureExtractionManager.h 2008-03-26 14:38:38 UTC (rev 1030) +++ runner/trunk/FeatureExtractionManager.h 2008-03-27 10:15:26 UTC (rev 1031) @@ -32,15 +32,26 @@ public: FeatureExtractionManager(); virtual ~FeatureExtractionManager(); + void setChannels(int channels); void setSampleRate(int sampleRate); - bool addFeatureExtractor(string transformXmlFile, vector<FeatureWriter*> writers); - bool addFeatureExtractor(string library, string plugname, vector<FeatureWriter*> writers); - void extractFeatures(string audioSource); + + bool addFeatureExtractorFromFile(QString transformXmlFile, + const vector<FeatureWriter*> &writers); + bool addDefaultFeatureExtractor(TransformId transformId, + const vector<FeatureWriter*> &writers); + + void extractFeatures(QString audioSource); + private: vector<Vamp::Plugin*> plugins; - vector<vector<FeatureWriter*> > pluginWriters; // parallel vector of writers for each plugin - vector<Transform> transforms; // parallel vector of transform records for each plugin + + // parallel vector of writers for each plugin + vector<vector<FeatureWriter*> > pluginWriters; + + // parallel vector of transform records for each plugin + vector<Transform> transforms; + int m_sampleRate; int m_channels; Modified: runner/trunk/FeatureWriter.h =================================================================== --- runner/trunk/FeatureWriter.h 2008-03-26 14:38:38 UTC (rev 1030) +++ runner/trunk/FeatureWriter.h 2008-03-27 10:15:26 UTC (rev 1031) @@ -20,6 +20,10 @@ #include <map> #include <vector> +#include <QString> + +#include "transform/Transform.h" + #include <vamp-sdk/Plugin.h> using std::string; @@ -31,7 +35,7 @@ public: virtual ~FeatureWriter() { } - struct Parameter { + struct Parameter { // parameter of the writer, not the plugin string name; string description; bool hasArg; @@ -45,8 +49,8 @@ return; } - virtual void write(const string& trackid, - const string& pluginid, + virtual void write(QString trackid, + TransformId transformId, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet) = 0; }; Modified: runner/trunk/RDFFeatureWriter.cpp =================================================================== --- runner/trunk/RDFFeatureWriter.cpp 2008-03-26 14:38:38 UTC (rev 1030) +++ runner/trunk/RDFFeatureWriter.cpp 2008-03-27 10:15:26 UTC (rev 1031) @@ -23,10 +23,8 @@ using namespace std; using namespace Vamp; -RDFFeatureWriter::RDFFeatureWriter() : - catalogueId("."), baseDir(".") //!!! +RDFFeatureWriter::RDFFeatureWriter() { - } RDFFeatureWriter::~RDFFeatureWriter() @@ -78,8 +76,8 @@ } } -void RDFFeatureWriter::write(const string& trackid, - const string& pluginid, +void RDFFeatureWriter::write(QString trackid, + TransformId transformId, const Plugin::OutputList& outputList, const Plugin::FeatureSet& featureSet) { @@ -93,38 +91,38 @@ for (unsigned int i = 0; i < featureList.size(); ++i) { // replace output files if necessary - replaceFeatureWriter(trackid, pluginid); - featureWriters[pluginid]->write(trackid, pluginid, outputList, featureSet); + replaceFeatureWriter(trackid, transformId); + featureWriters[transformId]->write + (trackid, transformId, outputList, featureSet); } } } -bool RDFFeatureWriter::newFeatureWriter(const string& trackid, const string& identifier) +bool RDFFeatureWriter::newFeatureWriter(QString trackid, TransformId transformId) { string filepath = baseDir + "/" + catalogueId + "/" + trackid + "." + identifier + ".rdf"; featureWriters[identifier] = new RDFSinglePluginWriter(trackid, filepath); - if (!(featureWriters[identifier]->out)) - return false; + if (!(featureWriters[identifier]->out)) return false; return true; } -// replace writer if no writer open for this track&plugin, else return false -bool RDFFeatureWriter::replaceFeatureWriter(const string& trackid, const string& pluginid) +// replace writer if no writer open for this track/transform, else return false +bool RDFFeatureWriter::replaceFeatureWriter(QString trackid, TransformId transformId) { - if (featureWriters.find(pluginid) != featureWriters.end()) + if (featureWriters.find(transformId) != featureWriters.end()) { - if (featureWriters[pluginid]->trackid == trackid) + if (featureWriters[transformId]->trackid == trackid) return false; // have a feature writer for this track & plugin else // track has changed { cerr<<"found feature writer with old track"<<endl; - cerr<<"new : "<<trackid<<", old : "<<featureWriters[pluginid]->trackid<<endl; - delete featureWriters[pluginid]; - featureWriters.erase(pluginid); + cerr<<"new : "<<trackid<<", old : "<<featureWriters[transformId]->trackid<<endl; + delete featureWriters[transformId]; + featureWriters.erase(transformId); } } cerr<<"allocating new RDFSinglePluginWriter"<<endl; - newFeatureWriter(trackid, pluginid); + newFeatureWriter(trackid, transformId); return true; } @@ -134,53 +132,56 @@ return (fin != NULL); } -string RDFFeatureWriter::getDescriptionFileForPlugin(const string& pluginid) +QString RDFFeatureWriter::getDescriptionFileForTransform(TransformId transformId) { - string path = ""; + QString type, soname, label; + QString pluginIdentifier; + Transform transform; + transform.setIdentifier(transformId); + pluginIdentifier = transformId.getPluginIdentifier(); + PluginIdentifier::parseIdentifier(identifier, type, soname, label); + vector<string> paths = PluginHostAdapter::getPluginPath(); + paths.push_back("."); // look in current directory as well - paths.push_back("."); //!!! + QStringList filters; + filters << "*.rdf"; + filters << "*.RDF"; + filters << "*.n3"; + filters << "*.N3"; - vector<string> rdf_exts; - rdf_exts.push_back("rdf"); rdf_exts.push_back("RDF"); - rdf_exts.push_back("n3"); rdf_exts.push_back("N3"); + // Search each Vamp plugin path for a .rdf file that either has + // name "soname_label" or "soname/label" plus RDF extension - HostExt::PluginLoader *loader = HostExt::PluginLoader::getInstance(); - vector<string> keys = loader->listPlugins(); - string libname = ""; - for (vector<string>::iterator kitr = keys.begin(); kitr != keys.end(); kitr++) - { - string::size_type ci = (*kitr).find(':'); - if (ci != string::npos && (*kitr).substr(ci + 1) == pluginid) - { - libname = (*kitr).substr(0,ci); - cerr<<"Found library name for plugin : "<<libname<<endl; + for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) { + + QDir dir(i->c_str()); + if (!dir.exists()) continue; + + QDir subdir = QDir(dir.filePath(soname)); + if (subdir.exists()) { + QStringList entries = subdir.entryList + (filters, QDir::Files | QDir::Readable); + for (QStringList::const_iterator j = entries.begin(); + j != entries.end(); ++j) { + QFileInfo fi(subdir.filePath(*j)); + if (fi.baseName().compare(label, Qt::CaseInsensitive) == 0) { + return fi.filePath(); + } + } } + + QStringList entries = dir.entryList + (filters, QDir::Files | QDir::Readable); + for (QStringList::const_iterator j = entries.begin(); + j != entries.end(); ++j) { + QFileInfo fi(subdir.filePath(*j)); + if (fi.baseName().compare(QString("%1_%2").arg(soname).arg(label), + Qt::CaseInsensitive) == 0) { + return fi.filePath(); + } + } } - if (libname == "") - cerr<<"Couldn't find library name for plugin "<<pluginid<<" !"<<endl; - - // Search each Vamp plugin path for a .rdf file matching the plugin identifier - // (possibly in a library-named directory) - - for (vector<string>::const_iterator pitr = paths.begin(); pitr != paths.end(); pitr++) - { - for (vector<string>::const_iterator eitr = rdf_exts.begin(); eitr != rdf_exts.end(); eitr++) - { - path = *pitr + "/" + pluginid + "." + *eitr; - cerr<<"Looking for "<<path<<endl; - // Check for file - if (fileExists(path)) - return path; - path = *pitr + "/" + libname + "/" + pluginid + "." + *eitr; // is dir delimiter "/" portable ? - cerr<<"Looking for "<<path<<endl; - // Check for file - if (fileExists(path)) - return path; - } - } - - cerr<<"Couldn't find description of plugin !"<<endl; return ""; } Modified: runner/trunk/RDFFeatureWriter.h =================================================================== --- runner/trunk/RDFFeatureWriter.h 2008-03-26 14:38:38 UTC (rev 1030) +++ runner/trunk/RDFFeatureWriter.h 2008-03-27 10:15:26 UTC (rev 1031) @@ -34,22 +34,19 @@ virtual ParameterList getSupportedParameters() const; virtual void setParameters(map<string, string> ¶ms); - virtual void write(const string& trackid, - const string& pluginid, + virtual void write(QString trackid, + TransformId transformId, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); - static string getDescriptionFileForPlugin(const string& pluginid); + static QString getDescriptionFileForTransform(TransformId transformId); private: - string catalogueId; - string baseDir; - - typedef map<string, RDFSinglePluginWriter*> WriterMap; + typedef map<TransformId, RDFSinglePluginWriter*> WriterMap; WriterMap featureWriters; - bool newFeatureWriter(const string& trackid, const string& identifier); - bool replaceFeatureWriter(const string& trackid, const string& identifier); + bool newFeatureWriter(QString trackid, TransformId transformId); + bool replaceFeatureWriter(QString trackid, TransformId transformId); }; #endif Modified: runner/trunk/RDFSinglePluginWriter.h =================================================================== --- runner/trunk/RDFSinglePluginWriter.h 2008-03-26 14:38:38 UTC (rev 1030) +++ runner/trunk/RDFSinglePluginWriter.h 2008-03-27 10:15:26 UTC (rev 1031) @@ -34,10 +34,18 @@ class RDFSinglePluginWriter : public FeatureWriter { public: - RDFSinglePluginWriter(const string& trackid, const string& outfilename); + RDFSinglePluginWriter(QString trackid, QString outfilename); virtual ~RDFSinglePluginWriter() { } - virtual void init(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList); - virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); + + virtual void init(QString trackid, + TransformId transformId, + const Vamp::Plugin::OutputList& outputList); + + virtual void write(QString trackid, + TransformId transformId, + const Vamp::Plugin::OutputList& outputList, + const Vamp::Plugin::FeatureSet& featureSet); + bool am_initialised; string trackid; int fe_count; Modified: runner/trunk/SimpleRDFFeatureWriter.h =================================================================== --- runner/trunk/SimpleRDFFeatureWriter.h 2008-03-26 14:38:38 UTC (rev 1030) +++ runner/trunk/SimpleRDFFeatureWriter.h 2008-03-27 10:15:26 UTC (rev 1031) @@ -23,8 +23,15 @@ { public: virtual ~SimpleRDFFeatureWriter() { } - virtual void init(const string& trackid, const Vamp::Plugin::OutputList& outputList); - virtual void write(const string& trackid, const string& pluginid, const Vamp::Plugin::OutputList& outputList, const Vamp::Plugin::FeatureSet& featureSet); + + virtual void init(QString trackid, + TransformId transformId, + const Vamp::Plugin::OutputList& outputList); + + virtual void write(QString trackid, + TransformId transformId, + const Vamp::Plugin::OutputList& outputList, + const Vamp::Plugin::FeatureSet& featureSet); }; #endif Modified: runner/trunk/main.cpp =================================================================== --- runner/trunk/main.cpp 2008-03-26 14:38:38 UTC (rev 1030) +++ runner/trunk/main.cpp 2008-03-27 10:15:26 UTC (rev 1031) @@ -507,7 +507,7 @@ for (set<string>::const_iterator i = requestedTransformFiles.begin(); i != requestedTransformFiles.end(); ++i) { - manager.addFeatureExtractor(*i, writers); + manager.addFeatureExtractorFromFile(i->c_str(), writers); } QStringList sources; @@ -530,7 +530,7 @@ for (QStringList::const_iterator i = sources.begin(); i != sources.end(); ++i) { std::cerr << "Extracting features for: \"" << i->toStdString() << "\"" << std::endl; - manager.extractFeatures(i->toStdString()); + manager.extractFeatures(*i); } return 0; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |