diff options
| author | Comment <tim@gray.(none)> | 2013-07-26 22:46:17 +0100 |
|---|---|---|
| committer | Comment <tim@gray.(none)> | 2013-07-26 22:46:17 +0100 |
| commit | f4170d6bfb763ad0af4002277a37dcd1692534d5 (patch) | |
| tree | db32d9753de780063e3afeb64764e13e5c4f5087 /rotord/src/vampHost.cpp | |
| parent | 3d7eea02aa7a155b84c8c74ecbfd55a1941a9297 (diff) | |
tidy files
Diffstat (limited to 'rotord/src/vampHost.cpp')
| -rw-r--r-- | rotord/src/vampHost.cpp | 815 |
1 files changed, 815 insertions, 0 deletions
diff --git a/rotord/src/vampHost.cpp b/rotord/src/vampHost.cpp new file mode 100644 index 0000000..65755eb --- /dev/null +++ b/rotord/src/vampHost.cpp @@ -0,0 +1,815 @@ +#include "vampHost.h" + +int vampHost::runPlugin(string myname, string soname, string id, string output, + int outputNo, string inputFile, ostream& out, bool useFrames) +{ + PluginLoader *loader = PluginLoader::getInstance(); + + PluginLoader::PluginKey key = loader->composePluginKey(soname, id); + + SNDFILE *sndfile; + SF_INFO sfinfo; + memset(&sfinfo, 0, sizeof(SF_INFO)); + + sndfile = sf_open(inputFile.c_str(), SFM_READ, &sfinfo); + if (!sndfile) { + cerr << myname << ": ERROR: Failed to open input file \"" + << inputFile << "\": " << sf_strerror(sndfile) << endl; + return 1; + } + + Plugin *plugin = loader->loadPlugin + (key, sfinfo.samplerate, PluginLoader::ADAPT_ALL_SAFE); + if (!plugin) { + cerr << myname << ": ERROR: Failed to load plugin \"" << id + << "\" from library \"" << soname << "\"" << endl; + sf_close(sndfile); + return 1; + } + + cerr << "Running plugin: \"" << plugin->getIdentifier() << "\"..." << endl; + + // Note that the following would be much simpler if we used a + // PluginBufferingAdapter as well -- i.e. if we had passed + // PluginLoader::ADAPT_ALL to loader->loadPlugin() above, instead + // of ADAPT_ALL_SAFE. Then we could simply specify our own block + // size, keep the step size equal to the block size, and ignore + // the plugin's bleatings. However, there are some issues with + // using a PluginBufferingAdapter that make the results sometimes + // technically different from (if effectively the same as) the + // un-adapted plugin, so we aren't doing that here. See the + // PluginBufferingAdapter documentation for details. + + int blockSize = plugin->getPreferredBlockSize(); + int 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; + } + int overlapSize = blockSize - stepSize; + sf_count_t currentStep = 0; + int finalStepsRemaining = max(1, (blockSize / stepSize) - 1); // at end of file, this many part-silent frames needed after we hit EOF + + int channels = sfinfo.channels; + + float *filebuf = new float[blockSize * channels]; + float **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 progress = 0; + + RealTime rt; + PluginWrapper *wrapper = 0; + RealTime adjustment = RealTime::zeroTime; + + if (outputs.empty()) { + cerr << "ERROR: Plugin has no outputs!" << endl; + goto done; + } + + 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; + goto done; + } + + } else { + + if (int(outputs.size()) <= outputNo) { + cerr << "ERROR: Output " << outputNo << " requested, but plugin has only " << outputs.size() << " output(s)" << endl; + goto done; + } + } + + 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; + goto done; + } + + wrapper = dynamic_cast<PluginWrapper *>(plugin); + if (wrapper) { + // See documentation for + // PluginInputDomainAdapter::getTimestampAdjustment + PluginInputDomainAdapter *ida = + wrapper->getWrapper<PluginInputDomainAdapter>(); + if (ida) adjustment = ida->getTimestampAdjustment(); + } + + // Here we iterate over the frames, avoiding asking the numframes in case it's streaming input. + do { + + int count; + + if ((blockSize==stepSize) || (currentStep==0)) { + // read a full fresh block + if ((count = sf_readf_float(sndfile, filebuf, blockSize)) < 0) { + cerr << "ERROR: sf_readf_float failed: " << sf_strerror(sndfile) << endl; + break; + } + if (count != blockSize) --finalStepsRemaining; + } else { + // otherwise shunt the existing data down and read the remainder. + memmove(filebuf, filebuf + (stepSize * channels), overlapSize * channels * sizeof(float)); + if ((count = sf_readf_float(sndfile, filebuf + (overlapSize * channels), stepSize)) < 0) { + cerr << "ERROR: sf_readf_float failed: " << sf_strerror(sndfile) << endl; + break; + } + if (count != stepSize) --finalStepsRemaining; + count += overlapSize; + } + + for (int c = 0; c < channels; ++c) { + int j = 0; + while (j < count) { + plugbuf[c][j] = filebuf[j * sfinfo.channels + c]; + ++j; + } + while (j < blockSize) { + plugbuf[c][j] = 0.0f; + ++j; + } + } + + rt = RealTime::frame2RealTime(currentStep * stepSize, sfinfo.samplerate); + + vampHost::printFeatures + (RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate), + sfinfo.samplerate, outputNo, plugin->process(plugbuf, rt), + out, useFrames); + + if (sfinfo.frames > 0){ + int pp = progress; + progress = lrintf((float(currentStep * stepSize) / sfinfo.frames) * 100.f); + if (progress != pp && out) { + cerr << "\r" << progress << "%"; + } + } + + ++currentStep; + + } while (finalStepsRemaining > 0); + + if (out) cerr << "\rDone" << endl; + + rt = RealTime::frame2RealTime(currentStep * stepSize, sfinfo.samplerate); + + vampHost::printFeatures(RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate), + sfinfo.samplerate, outputNo, + plugin->getRemainingFeatures(), out, useFrames); + + returnValue = 0; + +done: + delete plugin; + sf_close(sndfile); + return returnValue; +} + +int vampHost::rotorRunPlugin(string soname, string id, string output, + int outputNo, string inputFile, vector<float>& out, float& progress) +{ + PluginLoader *loader = PluginLoader::getInstance(); + + PluginLoader::PluginKey key = loader->composePluginKey(soname, id); + + SNDFILE *sndfile; + SF_INFO sfinfo; + memset(&sfinfo, 0, sizeof(SF_INFO)); + + sndfile = sf_open(inputFile.c_str(), SFM_READ, &sfinfo); + if (!sndfile) { + cerr << ": ERROR: Failed to open input file \"" + << inputFile << "\": " << sf_strerror(sndfile) << endl; + return 1; + } + + Plugin *plugin = loader->loadPlugin + (key, sfinfo.samplerate, PluginLoader::ADAPT_ALL_SAFE); + if (!plugin) { + cerr << ": ERROR: Failed to load plugin \"" << id + << "\" from library \"" << soname << "\"" << endl; + sf_close(sndfile); + return 1; + } + + cerr << "Running plugin: \"" << plugin->getIdentifier() << "\"..." << endl; + + // Note that the following would be much simpler if we used a + // PluginBufferingAdapter as well -- i.e. if we had passed + // PluginLoader::ADAPT_ALL to loader->loadPlugin() above, instead + // of ADAPT_ALL_SAFE. Then we could simply specify our own block + // size, keep the step size equal to the block size, and ignore + // the plugin's bleatings. However, there are some issues with + // using a PluginBufferingAdapter that make the results sometimes + // technically different from (if effectively the same as) the + // un-adapted plugin, so we aren't doing that here. See the + // PluginBufferingAdapter documentation for details. + + int blockSize = plugin->getPreferredBlockSize(); + int 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; + } + int overlapSize = blockSize - stepSize; + sf_count_t currentStep = 0; + int finalStepsRemaining = max(1, (blockSize / stepSize) - 1); // at end of file, this many part-silent frames needed after we hit EOF + + int channels = sfinfo.channels; + + float *filebuf = new float[blockSize * channels]; + float **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; + goto done; + } + + 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; + goto done; + } + + } else { + + if (int(outputs.size()) <= outputNo) { + cerr << "ERROR: Output " << outputNo << " requested, but plugin has only " << outputs.size() << " output(s)" << endl; + goto done; + } + } + + 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; + goto done; + } + + wrapper = dynamic_cast<PluginWrapper *>(plugin); + if (wrapper) { + // See documentation for + // PluginInputDomainAdapter::getTimestampAdjustment + PluginInputDomainAdapter *ida = + wrapper->getWrapper<PluginInputDomainAdapter>(); + if (ida) adjustment = ida->getTimestampAdjustment(); + } + + // Here we iterate over the frames, avoiding asking the numframes in case it's streaming input. + do { + + int count; + + if ((blockSize==stepSize) || (currentStep==0)) { + // read a full fresh block + if ((count = sf_readf_float(sndfile, filebuf, blockSize)) < 0) { + cerr << "ERROR: sf_readf_float failed: " << sf_strerror(sndfile) << endl; + break; + } + if (count != blockSize) --finalStepsRemaining; + } else { + // otherwise shunt the existing data down and read the remainder. + memmove(filebuf, filebuf + (stepSize * channels), overlapSize * channels * sizeof(float)); + if ((count = sf_readf_float(sndfile, filebuf + (overlapSize * channels), stepSize)) < 0) { + cerr << "ERROR: sf_readf_float failed: " << sf_strerror(sndfile) << endl; + break; + } + if (count != stepSize) --finalStepsRemaining; + count += overlapSize; + } + + for (int c = 0; c < channels; ++c) { + int j = 0; + while (j < count) { + plugbuf[c][j] = filebuf[j * sfinfo.channels + c]; + ++j; + } + while (j < blockSize) { + plugbuf[c][j] = 0.0f; + ++j; + } + } + + rt = RealTime::frame2RealTime(currentStep * stepSize, sfinfo.samplerate); + + vampHost::rotorGetFeatures(RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate),sfinfo.samplerate, outputNo,plugin->getRemainingFeatures(), out, progress); + + if (sfinfo.frames > 0){ + int pp = prog; + prog = lrintf((float(currentStep * stepSize) / sfinfo.frames) * 100.f); + if (prog != pp ) { + cerr << "\r" << progress << "%"; + } + } + + ++currentStep; + + } while (finalStepsRemaining > 0); + + cerr << "\rDone" << endl; + + rt = RealTime::frame2RealTime(currentStep * stepSize, sfinfo.samplerate); + + vampHost::rotorGetFeatures(RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate),sfinfo.samplerate, outputNo,plugin->getRemainingFeatures(), out, progress); + + returnValue = 0; + +done: + delete plugin; + sf_close(sndfile); + return returnValue; +} + +void vampHost::printFeatures(int frame, int sr, int output, + Plugin::FeatureSet features, ostream& out, bool useFrames) +{ + if (features[output].size()) { + cout << "." << features[output].size(); + } + for (unsigned int i = 0; i < features[output].size(); ++i) { + + if (useFrames) { + + int displayFrame = frame; + + if (features[output][i].hasTimestamp) { + displayFrame = RealTime::realTime2Frame + (features[output][i].timestamp, sr); + } + + out << displayFrame; + + if (features[output][i].hasDuration) { + displayFrame = RealTime::realTime2Frame + (features[output][i].duration, sr); + out << "," << displayFrame; + } + + out << ":"; + + } else { + + RealTime rt = RealTime::frame2RealTime(frame, sr); + + if (features[output][i].hasTimestamp) { + rt = features[output][i].timestamp; + } + + out << rt.toString(); + + if (features[output][i].hasDuration) { + rt = features[output][i].duration; + out<< "," << rt.toString(); + } + + out << ":"; + } + + for (unsigned int j = 0; j < features[output][i].values.size(); ++j) { + out<< " " << features[output][i].values[j]; + } + out << " " << features[output][i].label; + + out << endl; + } + +} + + + +void vampHost::rotorGetFeatures(int frame, int sr, int output,Plugin::FeatureSet features, vector<float>& out, float& progress) +{ + if (features[output].size()) { + cout << "." << features[output].size(); + } + for (unsigned int i = 0; i < features[output].size(); ++i) { + + + + int displayFrame = frame; + + if (features[output][i].hasTimestamp) { + displayFrame = RealTime::realTime2Frame + (features[output][i].timestamp, sr); + } + + cout << displayFrame; + + + cout << endl; + } + +} + + +int vampHost::QMAnalyser::process(const string inputFile){ + //vampHost::runPlugin("",settings.soname,settings.filtername, "",0, settings.inputFile, ostr,true); + //would run the plugin, outputting progress to cerr and the data to ostr + // + //int runPlugin(string myname, string soname, string id, string output,int outputNo, string inputFile, ostream& out, bool frames); + + + //we want to run a specific plugin, outputting progress to a mutex-protected passed variable + //and ultimately passing the data back as a string? + //or capture it as an array of floats? + //get the progress as a float + //how to handle errors? + + //debugger fucking up! program stalls after 1 request in debug!? + + string soname="qm-vamp-plugins"; + string id="qm-tempotracker"; + string myname=""; + string output=""; + int outputNo=0; + + vampHost::rotorRunPlugin(soname,id,output,outputNo,inputFile,beats,progress); + +} + +void vampHost::getTimestamps(int output,Plugin::FeatureSet features, vector<float>& out){ + + /* + vamp-simple-host qm-vamp-plugins:qm-tempotracker 01.wav + + 0.046439908: 156.61 bpm + 0.429569160: 156.61 bpm + 0.812698412: 161.50 bpm + 1.184217686: 152.00 bpm + + + vamp-simple-host qm-vamp-plugins:qm-segmenter 01.wav + + 0.000000000: 4 4 + 23.800000000: 6 6 + 44.600000000: 5 5 + 55.000000000: 7 7 + 72.800000000: 1 1 + 90.600000000: 2 2 + 109.200000000: 5 5 + 116.000000000: 3 3 + 143.800000000: 5 5 + 153.400000000: 3 3 + 163.000000000: 8 8 + + seems to be FP seconds then another metric + for now we can just take the first part + + features[output][i].timestamp is of type RealTime: represents time values to nanosecond precision + int sec; + int nsec; + 1 sec = 10^9 nanosec + + actually maybe this would be the way to go for rotor- avoiding rounding errors etc + for now - ideally will get a float representation + + features[output][i].values is a vector of floats + a description + WE DON'T CARE ABOUT ANYTHING <.01 seconds + + static long realTime2Frame(const RealTime &r, unsigned int sampleRate); + + get a vector of floats out, using frames, presuming data has a timestamp + + + this is crashing with "Aborted (core dumped)" + if we check for timestamp + + */ + + cout << "." << features[output].size(); + + //if (!features[output][0].hasTimestamp) { + // cerr << output << " channel, getTimestamps: error, featureset doesn't support timestamp" << endl; + //}_ + //else { + for (unsigned int i = 0; i < features[output].size(); ++i) { + out.push_back( ((float)RealTime::realTime2Frame(features[output][i].timestamp, 1000))*.001f); + cout << "feature found.\n"; + } + //} +} +float vampHost::QMAnalyser::get_progress(){ + float p; + mutex.lock(); + p=progress; + mutex.unlock(); + return p; +} +bool vampHost::Analyser::init(const string &soname,const string &id,const int &_channels,const int &_bits,const int &_samples,const int &_rate,int _outputNo,const map<string,float> ¶ms){ + + //stuff that only happens once + channels =_channels; + samples=_samples; + rate=_rate; + bits=_bits; + outputNo=_outputNo; + //output=_output; + + //http://www.mega-nerd.com/libsndfile/api.html#note1 + //libsndfile returns -1..1 for fp data + bytes=(bits>>3); + stride=channels*bytes; + scale=(1.0f/pow(2.0f,bits)); + + features.clear(); //in case of reuse + features[0.0f]=0; + + loader = PluginLoader::getInstance(); + key = loader->composePluginKey(soname, id); + plugin = loader->loadPlugin(key, _rate, PluginLoader::ADAPT_ALL_SAFE); + if (!plugin) { + cerr << ": ERROR: Failed to load plugin \"" << id + << "\" from library \"" << soname << "\"" << endl; + return false; + } + + cerr << "Running plugin: \"" << plugin->getIdentifier() << "\"... Domain:"; + + if (plugin->getInputDomain() == Plugin::FrequencyDomain) { + cerr << "frequency" << endl; + } + else { + + cerr << "time" << 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 false; + } + + 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 false; + } + } + else { + if (int(outputs.size()) <= outputNo) { + cerr << "ERROR: Output " << outputNo << " requested, but plugin has only " << outputs.size() << " output(s)" << endl; + return false; + } + } + od = outputs[outputNo]; + cerr << "Output number "<<outputNo<<": \"" << od.identifier << "\"" << endl; + + + for (auto i:params){ + plugin->setParameter(i.first,i.second); + cerr << "Set plugin parameter: "<<i.first<<" : "<<i.second<<endl; + } + + if (!plugin->initialise(channels, stepSize, blockSize)) { + cerr << "ERROR: Plugin initialise (channels = " << channels + << ", stepSize = " << stepSize << ", blockSize = " + << blockSize << ") failed." << endl; + return false; + } + + 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; + + return true; +} +void vampHost::Analyser::process_frame(uint8_t *data,int samples_in_frame){ + int sample=0; + + uint16_t *_data=(uint16_t*)data; + //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++) { + //unsigned int this_val=0; + // this_val+=data[(sample*stride)+(i*bytes)+j]<<((1-j)*8); + //} + //plugbuf[i][in_block]=((float)((int16_t)this_val))*scale; + plugbuf[i][in_block]=((float)_data[sample])*scale; + } + 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); //48000); //setting different rate doesn't affect it + + 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++; + } + + //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::Analyser::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); // //setting different + + 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; +} |
