# HG changeset patch # User cannam # Date 1221657369 0 # Node ID 1982246a3902e2434fa3d4e008409dc4ecb2f1ac # Parent 5ce2c3f79a4501446f5175326f29158b470c3abb * Provide PluginWrapper method for getting hold of a nested wrapper directly (a bit gross, but useful) * Use the above to enable the simple host to adjust timestamps appropriately when printing out results from input domain adapter wrapped plugins diff -r 5ce2c3f79a45 -r 1982246a3902 examples/SpectralCentroid.cpp --- a/examples/SpectralCentroid.cpp Wed Sep 17 11:00:51 2008 +0000 +++ b/examples/SpectralCentroid.cpp Wed Sep 17 13:16:09 2008 +0000 @@ -133,8 +133,10 @@ return list; } +//static int scount = 0; + SpectralCentroid::FeatureSet -SpectralCentroid::process(const float *const *inputBuffers, Vamp::RealTime) +SpectralCentroid::process(const float *const *inputBuffers, Vamp::RealTime timestamp) { if (m_stepSize == 0) { cerr << "ERROR: SpectralCentroid::process: " @@ -143,6 +145,8 @@ return FeatureSet(); } +// std::cerr << "SpectralCentroid::process: count = " << scount++ << ", timestamp = " << timestamp << ", total power = "; + double numLin = 0.0, numLog = 0.0, denom = 0.0; for (size_t i = 1; i <= m_blockSize/2; ++i) { @@ -155,10 +159,10 @@ denom += power; } +// std::cerr << denom << std::endl; + FeatureSet returnFeatures; -// std::cerr << "power " << denom << ", block size " << m_blockSize << std::endl; - if (denom != 0.0) { float centroidLin = float(numLin / denom); float centroidLog = powf(10, float(numLog / denom)); diff -r 5ce2c3f79a45 -r 1982246a3902 examples/ZeroCrossing.cpp --- a/examples/ZeroCrossing.cpp Wed Sep 17 11:00:51 2008 +0000 +++ b/examples/ZeroCrossing.cpp Wed Sep 17 13:16:09 2008 +0000 @@ -41,6 +41,7 @@ using std::cerr; using std::endl; +#include ZeroCrossing::ZeroCrossing(float inputSampleRate) : Plugin(inputSampleRate), @@ -137,6 +138,8 @@ return list; } +//static int scount = 0; + ZeroCrossing::FeatureSet ZeroCrossing::process(const float *const *inputBuffers, Vamp::RealTime timestamp) @@ -148,11 +151,15 @@ return FeatureSet(); } +// std::cerr << "ZeroCrossing::process: count = " << scount++ << ", timestamp = " << timestamp << ", rms = "; + float prev = m_previousSample; size_t count = 0; FeatureSet returnFeatures; +// double acc = 0.0; + for (size_t i = 0; i < m_stepSize; ++i) { float sample = inputBuffers[0][i]; @@ -173,9 +180,14 @@ returnFeatures[1].push_back(feature); } +// acc += sample * sample; + prev = sample; } +// acc /= m_stepSize; +// std::cerr << sqrt(acc) << std::endl; + m_previousSample = prev; Feature feature; diff -r 5ce2c3f79a45 -r 1982246a3902 host/vamp-simple-host.cpp --- a/host/vamp-simple-host.cpp Wed Sep 17 11:00:51 2008 +0000 +++ b/host/vamp-simple-host.cpp Wed Sep 17 13:16:09 2008 +0000 @@ -36,7 +36,6 @@ */ #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" @@ -59,8 +58,10 @@ using Vamp::PluginHostAdapter; using Vamp::RealTime; using Vamp::HostExt::PluginLoader; +using Vamp::HostExt::PluginWrapper; +using Vamp::HostExt::PluginInputDomainAdapter; -#define HOST_VERSION "1.1" +#define HOST_VERSION "1.3" enum Verbosity { PluginIds, @@ -328,6 +329,10 @@ int returnValue = 1; int progress = 0; + RealTime rt; + PluginWrapper *wrapper = 0; + RealTime adjustment = RealTime::zeroTime; + if (outputs.empty()) { cerr << "ERROR: Plugin has no outputs!" << endl; goto done; @@ -365,6 +370,13 @@ goto done; } + wrapper = dynamic_cast(plugin); + if (wrapper) { + PluginInputDomainAdapter *ida = + wrapper->getWrapper(); + if (ida) adjustment = ida->getTimestampAdjustment(); + } + for (size_t i = 0; i < sfinfo.frames; i += stepSize) { int count; @@ -391,9 +403,11 @@ } } + rt = RealTime::frame2RealTime(i, sfinfo.samplerate); + printFeatures - (i, sfinfo.samplerate, outputNo, plugin->process - (plugbuf, RealTime::frame2RealTime(i, sfinfo.samplerate)), + (RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate), + sfinfo.samplerate, outputNo, plugin->process(plugbuf, rt), out, useFrames); int pp = progress; @@ -404,7 +418,10 @@ } if (out) cerr << "\rDone" << endl; - printFeatures(sfinfo.frames, sfinfo.samplerate, outputNo, + rt = RealTime::frame2RealTime(sfinfo.frames, sfinfo.samplerate); + + printFeatures(RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate), + sfinfo.samplerate, outputNo, plugin->getRemainingFeatures(), out, useFrames); returnValue = 0; diff -r 5ce2c3f79a45 -r 1982246a3902 vamp-sdk/Plugin.h --- a/vamp-sdk/Plugin.h Wed Sep 17 11:00:51 2008 +0000 +++ b/vamp-sdk/Plugin.h Wed Sep 17 13:16:09 2008 +0000 @@ -378,9 +378,9 @@ * If the plugin's inputDomain is TimeDomain, inputBuffers will * point to one array of floats per input channel, and each of * these arrays will contain blockSize consecutive audio samples - * (the host will zero-pad as necessary). The timestamp will be - * the real time in seconds of the start of the supplied block of - * samples. + * (the host will zero-pad as necessary). The timestamp in this + * case will be the real time in seconds of the start of the + * supplied block of samples. * * If the plugin's inputDomain is FrequencyDomain, inputBuffers * will point to one array of floats per input channel, and each diff -r 5ce2c3f79a45 -r 1982246a3902 vamp-sdk/hostext/PluginInputDomainAdapter.cpp --- a/vamp-sdk/hostext/PluginInputDomainAdapter.cpp Wed Sep 17 11:00:51 2008 +0000 +++ b/vamp-sdk/hostext/PluginInputDomainAdapter.cpp Wed Sep 17 13:16:09 2008 +0000 @@ -86,6 +86,8 @@ size_t getPreferredBlockSize() const; FeatureSet process(const float *const *inputBuffers, RealTime timestamp); + + RealTime getTimestampAdjustment() const; protected: Plugin *m_plugin; @@ -151,6 +153,13 @@ return m_impl->process(inputBuffers, timestamp); } +RealTime +PluginInputDomainAdapter::getTimestampAdjustment() const +{ + return m_impl->getTimestampAdjustment(); +} + + PluginInputDomainAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) : m_plugin(plugin), m_inputSampleRate(inputSampleRate), @@ -338,6 +347,17 @@ return blockSize; } +RealTime +PluginInputDomainAdapter::Impl::getTimestampAdjustment() const +{ + if (m_plugin->getInputDomain() == TimeDomain) { + return RealTime::zeroTime; + } else { + return RealTime::frame2RealTime + (m_blockSize/2, int(m_inputSampleRate + 0.5)); + } +} + Plugin::FeatureSet PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers, RealTime timestamp) @@ -390,8 +410,7 @@ // std::cerr << "PluginInputDomainAdapter: sampleRate " << m_inputSampleRate << ", blocksize " << m_blockSize << ", adjusting time from " << timestamp; - timestamp = timestamp + RealTime::frame2RealTime - (m_blockSize/2, int(m_inputSampleRate + 0.5)); + timestamp = timestamp + getTimestampAdjustment(); // std::cerr << " to " << timestamp << std::endl; diff -r 5ce2c3f79a45 -r 1982246a3902 vamp-sdk/hostext/PluginInputDomainAdapter.h --- a/vamp-sdk/hostext/PluginInputDomainAdapter.h Wed Sep 17 11:00:51 2008 +0000 +++ b/vamp-sdk/hostext/PluginInputDomainAdapter.h Wed Sep 17 13:16:09 2008 +0000 @@ -91,6 +91,29 @@ FeatureSet process(const float *const *inputBuffers, RealTime timestamp); + /** + * Return the amount by which the timestamps supplied to process() + * are being incremented when they are passed to the plugin's own + * process() implementation. + * + * The Vamp API mandates that the timestamp passed to the plugin + * for time-domain input should be the time of the first sample in + * the block, but the timestamp passed for frequency-domain input + * should be the timestamp of the centre of the block. + * + * The PluginInputDomainAdapter adjusts its timestamps properly so + * that the plugin receives correct times, but in some + * circumstances (such as for establishing the correct timing of + * implicitly-timed features, i.e. features without their own + * timestamps) the host may need to be aware that this adjustment + * is taking place. + * + * If the plugin requires time-domain input, this function will + * return zero. The result of calling this function before + * initialise() has been called is undefined. + */ + RealTime getTimestampAdjustment() const; + protected: class Impl; Impl *m_impl; diff -r 5ce2c3f79a45 -r 1982246a3902 vamp-sdk/hostext/PluginWrapper.h --- a/vamp-sdk/hostext/PluginWrapper.h Wed Sep 17 11:00:51 2008 +0000 +++ b/vamp-sdk/hostext/PluginWrapper.h Wed Sep 17 13:16:09 2008 +0000 @@ -94,6 +94,30 @@ FeatureSet getRemainingFeatures(); + /** + * Return a pointer to the plugin wrapper of type WrapperType + * surrounding this wrapper's plugin, if present. + * + * This is useful in situations where a plugin is wrapped by + * multiple different wrappers (one inside another) and the host + * wants to call some wrapper-specific function on one of the + * layers without having to care about the order in which they are + * wrapped. For example, the plugin returned by + * PluginLoader::loadPlugin may have more than one wrapper; if the + * host wanted to query or fine-tune some property of one of them, + * it would be hard to do so without knowing the order of the + * wrappers. This function therefore gives direct access to the + * wrapper of a particular type. + */ + template + WrapperType *getWrapper() { + WrapperType *w = dynamic_cast(this); + if (w) return w; + PluginWrapper *pw = dynamic_cast(m_plugin); + if (pw) return pw->getWrapper(); + return 0; + } + protected: PluginWrapper(Plugin *plugin); // I take ownership of plugin Plugin *m_plugin;