summaryrefslogtreecommitdiff
path: root/rotord/vampHost.cpp
diff options
context:
space:
mode:
authorTim Redfern <tim@herge.(none)>2013-04-05 17:05:38 +0100
committerTim Redfern <tim@herge.(none)>2013-04-05 17:05:38 +0100
commit81d4c56683303021aed05b9f5bf57abb1b154d8c (patch)
treed1a8d403ad455f761f63f480240b81555611c689 /rotord/vampHost.cpp
parent332c7c24301700ca0a4ceb104051bcd3a3b3bc4b (diff)
making audio analysis adapter
Diffstat (limited to 'rotord/vampHost.cpp')
-rw-r--r--rotord/vampHost.cpp155
1 files changed, 149 insertions, 6 deletions
diff --git a/rotord/vampHost.cpp b/rotord/vampHost.cpp
index b9b0781..e28419c 100644
--- a/rotord/vampHost.cpp
+++ b/rotord/vampHost.cpp
@@ -588,21 +588,164 @@ float vampHost::QMAnalyser::get_progress(){
mutex.unlock();
return p;
}
-void vampHost::Analyser::init(const string &soname,const string &id,const int &rate){
+bool vampHost::Analyser::init(const string &soname,const string &id,const int &_channels,const int &_bits,const int &_samples,const int &_rate,const int &_outputNo,const string &_output){
+
+ //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));
+
+
loader = PluginLoader::getInstance();
key = loader->composePluginKey(soname, id);
- Plugin *plugin = loader->loadPlugin(key, rate, PluginLoader::ADAPT_ALL_SAFE);
+ Plugin *plugin = loader->loadPlugin(key, _rate, PluginLoader::ADAPT_ALL_SAFE);
if (!plugin) {
cerr << ": ERROR: Failed to load plugin \"" << id
<< "\" from library \"" << soname << "\"" << endl;
- return;
+ return false;
}
cerr << "Running plugin: \"" << plugin->getIdentifier() << "\"..." << endl;
- delete plugin;
+ blockSize = plugin->getPreferredBlockSize();
+ stepSize = plugin->getPreferredStepSize();
- return;
-}
+ 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
+
+ filebuf = new float[blockSize * channels];
+ 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 is: \"" << od.identifier << "\"" << 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;
+
+ return true;
+}
+void vampHost::Analyser::process_frame(uint8_t *data,int samples_in_frame){
+ 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++) {
+ unsigned int this_val=0;
+ for (int j=0;j<bytes;j++) {
+ this_val+=data[(sample*stride)+(i*bytes)+j]<<(j*8);
+ }
+ plugbuf[i][in_block]=((float)((int16_t)this_val))*scale;
+ }
+ in_block++;
+ sample++;
+ }
+ if (in_block==blockSize) {
+ //block is ready to be processed
+ cerr<<"processing block "<<blocks_processed<<endl;
+ in_block=0;
+ blocks_processed++;
+ }
+ }
+}
+void vampHost::Analyser::cleanup(){
+ delete[] filebuf;
+ for (int c = 0; c < channels; ++c) {
+ delete[] plugbuf[c];
+ }
+ delete[] plugbuf;
+ delete plugin;
+}