summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTim Redfern <tim@eclectronics.org>2013-05-29 13:24:40 +0100
committerTim Redfern <tim@eclectronics.org>2013-05-29 13:24:40 +0100
commit296e1ecf1d4402166bb0d958980f8bf0faba4f5f (patch)
tree589c36da53d07243f6cb3ae65d3d32a423785eba /src
parent40aef5fefdb5e0f25ccd67d61e1556997560f396 (diff)
various
Diffstat (limited to 'src')
-rw-r--r--src/ofxVamphost.cpp249
-rw-r--r--src/ofxVamphost.h64
2 files changed, 313 insertions, 0 deletions
diff --git a/src/ofxVamphost.cpp b/src/ofxVamphost.cpp
new file mode 100644
index 0000000..e5ef92b
--- /dev/null
+++ b/src/ofxVamphost.cpp
@@ -0,0 +1,249 @@
+#include "ofxVamphost.h"
+
+using namespace std;
+using namespace Vamp;
+
+int Vamphost::getRT(){
+ return rt.msec();
+}
+
+
+
+Vamphost::Vamphost(){
+ loader = PluginLoader::getInstance();
+ list=loader->listPlugins();
+ for (auto p: list) {
+ cerr<<p<<endl;
+ }
+}
+
+int Vamphost::init(int whichplugin,const int &_channels,const int &_rate,const int &_outputNo,const string &_output){
+ key = list[whichplugin];
+ init(_channels,_rate,_outputNo,_output);
+}
+
+
+int Vamphost::init(const string &soname,const string &id,const int &_channels,const int &_rate,const int &_outputNo,const string &_output){
+ key = loader->composePluginKey(soname, id);
+ init(_channels,_rate,_outputNo,_output);
+}
+int Vamphost::init(const int &_channels,const int &_rate,const int &_outputNo,const string &_output){
+ channels =_channels;
+ rate=_rate;
+ outputNo=_outputNo;
+ output=_output;
+ init();
+}
+int Vamphost::init(int whichplugin){
+ key = list[whichplugin];
+ init();
+}
+int Vamphost::init(){
+ //stuff that only happens once
+
+
+ features[0.0f]=0;
+
+
+
+ plugin = loader->loadPlugin(key, rate, PluginLoader::ADAPT_ALL_SAFE);
+ if (!plugin) {
+ cerr << ": ERROR: Failed to load plugin \"" << key<< "\"" << endl;
+ return -1;
+ }
+
+ cerr << "Running plugin: \"" << plugin->getIdentifier() << "\"..." << endl;
+
+ blockSize = plugin->getPreferredBlockSize();
+ stepSize = plugin->getPreferredStepSize();
+
+ if (blockSize == 0) {
+ blockSize = 1024;
+ }
+ if (stepSize == 0) {
+ if (plugin->getInputDomain() == Plugin::FrequencyDomain) {
+ stepSize = blockSize/2;
+ } else {
+ stepSize = blockSize;
+ }
+ }
+ else if (stepSize > blockSize) {
+ cerr << "WARNING: stepSize " << stepSize << " > blockSize " << blockSize << ", resetting blockSize to ";
+ if (plugin->getInputDomain() == Plugin::FrequencyDomain) {
+ blockSize = stepSize * 2;
+ } else {
+ blockSize = stepSize;
+ }
+ cerr << blockSize << endl;
+ }
+ overlapSize = blockSize - stepSize;
+ currentStep = 0;
+ finalStepsRemaining = max(1, (blockSize / stepSize) - 1); // at end of file, this many part-silent frames needed after we hit EOF
+
+ plugbuf = new float*[channels];
+ for (int c = 0; c < channels; ++c) plugbuf[c] = new float[blockSize + 2];
+
+ cerr << "Using block size = " << blockSize << ", step size = "
+ << stepSize << endl;
+
+ // The channel queries here are for informational purposes only --
+ // a PluginChannelAdapter is being used automatically behind the
+ // scenes, and it will take case of any channel mismatch
+
+ int minch = plugin->getMinChannelCount();
+ int maxch = plugin->getMaxChannelCount();
+ cerr << "Plugin accepts " << minch << " -> " << maxch << " channel(s)" << endl;
+ cerr << "Sound file has " << channels << " (will mix/augment if necessary)" << endl;
+
+ Plugin::OutputList outputs = plugin->getOutputDescriptors();
+ Plugin::OutputDescriptor od;
+
+ int returnValue = 1;
+ int prog = 0;
+
+ RealTime rt;
+ PluginWrapper *wrapper = 0;
+ RealTime adjustment = RealTime::zeroTime;
+
+ if (outputs.empty()) {
+ cerr << "ERROR: Plugin has no outputs!" << endl;
+ return -1;
+ }
+
+ if (outputNo < 0) {
+ for (size_t oi = 0; oi < outputs.size(); ++oi) {
+ if (outputs[oi].identifier == output) {
+ outputNo = oi;
+ break;
+ }
+ }
+ if (outputNo < 0) {
+ cerr << "ERROR: Non-existent output \"" << output << "\" requested" << endl;
+ return -1;
+ }
+ }
+ else {
+ if (int(outputs.size()) <= outputNo) {
+ cerr << "ERROR: Output " << outputNo << " requested, but plugin has only " << outputs.size() << " output(s)" << endl;
+ return -1;
+ }
+ }
+ od = outputs[outputNo];
+ cerr << "Output is: \"" << od.identifier << "\"" << endl;
+
+ if (!plugin->initialise(channels, stepSize, blockSize)) {
+ cerr << "ERROR: Plugin initialise (channels = " << channels
+ << ", stepSize = " << stepSize << ", blockSize = "
+ << blockSize << ") failed." << endl;
+ return -1;
+ }
+
+ wrapper = dynamic_cast<PluginWrapper *>(plugin);
+ if (wrapper) {
+ // See documentation for
+ // PluginInputDomainAdapter::getTimestampAdjustment
+ PluginInputDomainAdapter *ida =wrapper->getWrapper<PluginInputDomainAdapter>();
+ if (ida) adjustment = ida->getTimestampAdjustment();
+ }
+
+ //everything is prepared to start consuming data in blocks
+
+ in_block=0;
+ blocks_processed=0;
+ currentStep=0;
+
+ featureNo=1;
+
+
+ avg=0.0f;
+ num=0;
+ numFeat=0;
+
+ return blockSize;
+}
+void Vamphost::process_frame(float *data,int samples_in_frame){
+ //
+ //
+
+ //plugbuf[0]=data;
+ //
+ //
+
+ int sample=0;
+
+ //process the whole frame which may be f>1<f blocks
+ //when the frame is finished leave the partial block for the next frame
+ while(sample<samples_in_frame) {
+ while(sample<samples_in_frame&&in_block<blockSize) {
+ for (int i=0;i<channels;i++) {
+ plugbuf[i][in_block]=data[sample];
+ num++;
+ avg+=(data[sample]/num);
+ }
+ in_block++;
+ sample++;
+ }
+ if (in_block==blockSize) {
+ //block is ready to be processed
+ //cerr<<plugin->getIdentifier()<<" processed block "<<blocks_processed<<endl;
+
+ //I /think/ that the vamp plugin keeps processing through the plugbuf until it encounters 0s
+ rt = RealTime::frame2RealTime(currentStep * stepSize, rate);
+
+ Plugin::FeatureSet feat=plugin->process(plugbuf, rt);
+
+ //if (feat[outputNo].size()>0) cerr<<"BEAT"<<endl;
+
+ for (unsigned int i = 0; i < feat[outputNo].size(); ++i) {
+ features[((float)feat[outputNo][i].timestamp.sec)+(((float)feat[outputNo][i].timestamp.nsec)*.000000001)]=featureNo;
+ featureNo++;
+ numFeat++;
+ }
+
+ //shunt it down
+ for (int i=0;i<blockSize-stepSize;i++){
+ for (int j=0;j<channels;j++){
+ plugbuf[j][i]=plugbuf[j][i+stepSize];
+ }
+ }
+
+ in_block-=stepSize;
+ currentStep++;
+ }
+ }
+}
+
+void Vamphost::cleanup(){
+
+ //process final block
+ while(in_block<blockSize) {
+ for (int i=0;i<channels;i++) {
+ plugbuf[i][in_block]=0.0f;
+ }
+ in_block++;
+ }
+
+ rt = RealTime::frame2RealTime(currentStep * stepSize, rate);
+
+ Plugin::FeatureSet feat=plugin->process(plugbuf, rt);
+
+ for (unsigned int i = 0; i < feat[outputNo].size(); ++i) {
+ features[((float)feat[outputNo][i].timestamp.sec)+(((float)feat[outputNo][i].timestamp.nsec)*.000000001)]=featureNo;
+ featureNo++;
+ }
+
+ feat=plugin->getRemainingFeatures();
+
+ for (unsigned int i = 0; i < feat[outputNo].size(); ++i) {
+ features[((float)feat[outputNo][i].timestamp.sec)+(((float)feat[outputNo][i].timestamp.nsec)*.000000001)]=featureNo;
+ featureNo++;
+ }
+
+ cerr<<plugin->getIdentifier()<<" found "<<(features.size()-1)<<" features"<<endl;
+ //deal with left over data?
+ for (int c = 0; c < channels; ++c) {
+ delete[] plugbuf[c];
+ }
+ delete[] plugbuf;
+ delete plugin;
+}
diff --git a/src/ofxVamphost.h b/src/ofxVamphost.h
new file mode 100644
index 0000000..245b7ff
--- /dev/null
+++ b/src/ofxVamphost.h
@@ -0,0 +1,64 @@
+#ifndef OFXVAMPHOST_H_
+#define OFXVAMPHOST_H_
+
+#include <vamp-hostsdk/PluginHostAdapter.h>
+#include <vamp-hostsdk/PluginInputDomainAdapter.h>
+#include <vamp-hostsdk/PluginLoader.h>
+
+#include <map>
+#include <math.h>
+#include <sndfile.h>
+
+using Vamp::Plugin;
+using Vamp::PluginHostAdapter;
+using Vamp::RealTime;
+using Vamp::HostExt::PluginLoader;
+using Vamp::HostExt::PluginWrapper;
+using Vamp::HostExt::PluginInputDomainAdapter;
+
+#define HOST_VERSION "1.5"
+
+class Vamphost{
+ //can load any vamp analysis plugin and present its data with a unified interface
+ public:
+ Vamphost();
+ int init(const std::string &soname,const std::string &id,const int &_channels,const int &_rate,const int &_outputNo=0,const std::string &_output="");
+ int init(int whichplugin,const int &_channels,const int &_rate,const int &_outputNo=0,const std::string &_output="");
+ int init(const int &_channels,const int &_rate,const int &_outputNo=0,const std::string &_output="");
+ int init(int whichplugin);
+ int init();
+ void process_frame(float *data,int samples_in_frame);
+ void cleanup();
+
+ std::map<float,int> features;
+ //map<time,featureNo>
+ //this is the best way to store features: because map allows to search for the key below and above the present time
+ int getRT();
+
+ float avg;
+ int num;
+ int numFeat;
+
+ PluginLoader::PluginKey key;
+ PluginLoader::PluginKeyList list;
+
+ private:
+
+ PluginLoader *loader;
+ Plugin *plugin;
+ RealTime rt;
+ int channels,bits,samples,rate;
+ int bytes,stride;
+ float scale;
+ int blockSize,stepSize,overlapSize,finalStepsRemaining,currentStep,outputNo;
+ int in_block,blocks_processed;
+ std::string output;
+ float **plugbuf;
+
+ int featureNo;
+
+
+};
+
+#endif
+