// Get & load plugins that return timing marks std::list<std::string> xLightsVamp::GetAvailablePlugins(AudioManager* paudio) { std::list<std::string> ret; // Load the plugins in case they have not already been loaded LoadPlugins(paudio); for (std::vector<Vamp::Plugin *>::iterator it = _loadedPlugins.begin(); it != _loadedPlugins.end(); ++it) { Plugin::OutputList outputs = (*it)->getOutputDescriptors(); for (Plugin::OutputList::iterator j = outputs.begin(); j != outputs.end(); ++j) { if (j->sampleType == Plugin::OutputDescriptor::FixedSampleRate || j->sampleType == Plugin::OutputDescriptor::OneSamplePerStep || !j->hasFixedBinCount || (j->hasFixedBinCount && j->binCount > 1)) { // We are filering out this from our return array continue; } std::string name = std::string(wxString::FromUTF8((*it)->getName().c_str()).c_str()); if (outputs.size() > 1) { // This is not the plugin's only output. // Use "plugin name: output name" as the effect name, // unless the output name is the same as the plugin name std::string outputName = std::string(wxString::FromUTF8(j->name.c_str()).c_str()); if (outputName != name) { std::ostringstream stringStream; stringStream << name << ": " << outputName.c_str(); name = stringStream.str(); } } _plugins[name] = (*it); } } for (std::map<std::string, Vamp::Plugin *>::iterator it = _plugins.begin(); it != _plugins.end(); ++it) { ret.push_back(it->first); } return ret; }
void DlgPrefBeats::populate() { VampAnalyser::initializePluginPaths(); m_listIdentifier.clear(); m_listName.clear(); m_listLibrary.clear(); disconnect(plugincombo, SIGNAL(currentIndexChanged(int)), this, SLOT(pluginSelected(int))); plugincombo->clear(); plugincombo->setDuplicatesEnabled(false); connect(plugincombo, SIGNAL(currentIndexChanged(int)), this, SLOT(pluginSelected(int))); VampPluginLoader *loader = VampPluginLoader::getInstance(); std::vector<PluginLoader::PluginKey> plugins = loader->listPlugins(); qDebug() << "VampPluginLoader::listPlugins() returned" << plugins.size() << "plugins"; for (unsigned int iplugin=0; iplugin < plugins.size(); iplugin++) { // TODO(XXX): WTF, 48000 Plugin *plugin = loader->loadPlugin(plugins[iplugin], 48000); //TODO: find a way to add beat trackers only if (plugin) { Plugin::OutputList outputs = plugin->getOutputDescriptors(); for (unsigned int ioutput=0; ioutput < outputs.size(); ioutput++) { QString displayname = QString::fromStdString(plugin->getIdentifier()) + ":" + QString::number(ioutput); QString displaynametext = QString::fromStdString(plugin->getName()); qDebug() << "Plugin output displayname:" << displayname << displaynametext; bool goodones = ((displayname.contains("mixxxbpmdetection")|| displayname.contains("qm-tempotracker:0"))|| displayname.contains("beatroot:0")|| displayname.contains("marsyas_ibt:0")|| displayname.contains("aubiotempo:0") ); if (goodones) { m_listName << displaynametext; QString pluginlibrary = QString::fromStdString(plugins[iplugin]).section(":",0,0); m_listLibrary << pluginlibrary; QString displayname = QString::fromStdString(plugin->getIdentifier()) + ":" + QString::number(ioutput); m_listIdentifier << displayname; plugincombo->addItem(displaynametext, displayname); } } delete plugin; plugin = 0; } } }
// Get a list of all plugins std::list<std::string> xLightsVamp::GetAllAvailablePlugins(AudioManager* paudio) { std::list<std::string> ret; // load the plugins if they have not already been loaded LoadPlugins(paudio); for (std::vector<Vamp::Plugin *>::iterator it = _loadedPlugins.begin(); it != _loadedPlugins.end(); ++it) { Plugin::OutputList outputs = (*it)->getOutputDescriptors(); for (Plugin::OutputList::iterator j = outputs.begin(); j != outputs.end(); ++j) { std::string name = std::string(wxString::FromUTF8((*it)->getName().c_str()).c_str()); if (outputs.size() > 1) { // This is not the plugin's only output. // Use "plugin name: output name" as the effect name, // unless the output name is the same as the plugin name std::string outputName = std::string(wxString::FromUTF8(j->name.c_str()).c_str()); if (outputName != name) { std::ostringstream stringStream; stringStream << name << ": " << outputName.c_str(); name = stringStream.str(); } } _allplugins[name] = *it; } } for (std::map<std::string, Vamp::Plugin *>::iterator it = _allplugins.begin(); it != _allplugins.end(); ++it) { ret.push_back(it->first); } return ret; }
void DlgPrefKey::populate() { VampAnalyser::initializePluginPaths(); m_listIdentifier.clear(); m_listName.clear(); m_listLibrary.clear(); plugincombo->clear(); plugincombo->setDuplicatesEnabled(false); VampPluginLoader* loader = VampPluginLoader::getInstance(); std::vector<PluginLoader::PluginKey> plugins = loader->listPlugins(); qDebug() << "VampPluginLoader::listPlugins() returned" << plugins.size() << "plugins"; for (unsigned int iplugin=0; iplugin < plugins.size(); iplugin++) { // TODO(XXX): WTF, 48000 Plugin* plugin = loader->loadPlugin(plugins[iplugin], 48000); //TODO(XXX): find a general way to add key detectors only if (plugin) { Plugin::OutputList outputs = plugin->getOutputDescriptors(); for (unsigned int ioutput=0; ioutput < outputs.size(); ioutput++) { QString displayname = QString::fromStdString(plugin->getIdentifier()) + ":" + QString::number(ioutput); QString displaynametext = QString::fromStdString(plugin->getName()); qDebug() << "Plugin output displayname:" << displayname << displaynametext; bool goodones = displayname.contains(VAMP_ANALYSER_KEY_DEFAULT_PLUGIN_ID); if (goodones) { m_listName << displaynametext; QString pluginlibrary = QString::fromStdString(plugins[iplugin]).section(":",0,0); m_listLibrary << pluginlibrary; QString displayname = QString::fromStdString(plugin->getIdentifier()) + ":" + QString::number(ioutput); m_listIdentifier << displayname; plugincombo->addItem(displaynametext, displayname); } } delete plugin; plugin = 0; } } }
void enumeratePlugins(Verbosity verbosity) { PluginLoader *loader = PluginLoader::getInstance(); if (verbosity == PluginInformation) { cout << "\nVamp plugin libraries found in search path:" << endl; } vector<PluginLoader::PluginKey> plugins = loader->listPlugins(); typedef multimap<string, PluginLoader::PluginKey> LibraryMap; LibraryMap libraryMap; for (size_t i = 0; i < plugins.size(); ++i) { string path = loader->getLibraryPathForPlugin(plugins[i]); libraryMap.insert(LibraryMap::value_type(path, plugins[i])); } string prevPath = ""; int index = 0; for (LibraryMap::iterator i = libraryMap.begin(); i != libraryMap.end(); ++i) { string path = i->first; PluginLoader::PluginKey key = i->second; if (path != prevPath) { prevPath = path; index = 0; if (verbosity == PluginInformation) { cout << "\n " << path << ":" << endl; } else if (verbosity == PluginInformationDetailed) { string::size_type ki = i->second.find(':'); string text = "Library \"" + i->second.substr(0, ki) + "\""; cout << "\n" << header(text, 1); } } Plugin *plugin = loader->loadPlugin(key, 48000); if (plugin) { char c = char('A' + index); if (c > 'Z') c = char('a' + (index - 26)); PluginLoader::PluginCategoryHierarchy category = loader->getPluginCategory(key); string catstr; if (!category.empty()) { for (size_t ci = 0; ci < category.size(); ++ci) { if (ci > 0) catstr += " > "; catstr += category[ci]; } } if (verbosity == PluginInformation) { cout << " [" << c << "] [v" << plugin->getVampApiVersion() << "] " << plugin->getName() << ", \"" << plugin->getIdentifier() << "\"" << " [" << plugin->getMaker() << "]" << endl; if (catstr != "") { cout << " > " << catstr << endl; } if (plugin->getDescription() != "") { cout << " - " << plugin->getDescription() << endl; } } else if (verbosity == PluginInformationDetailed) { cout << header(plugin->getName(), 2); cout << " - Identifier: " << key << endl; cout << " - Plugin Version: " << plugin->getPluginVersion() << endl; cout << " - Vamp API Version: " << plugin->getVampApiVersion() << endl; cout << " - Maker: \"" << plugin->getMaker() << "\"" << endl; cout << " - Copyright: \"" << plugin->getCopyright() << "\"" << endl; cout << " - Description: \"" << plugin->getDescription() << "\"" << endl; cout << " - Input Domain: " << (plugin->getInputDomain() == Vamp::Plugin::TimeDomain ? "Time Domain" : "Frequency Domain") << endl; cout << " - Default Step Size: " << plugin->getPreferredStepSize() << endl; cout << " - Default Block Size: " << plugin->getPreferredBlockSize() << endl; cout << " - Minimum Channels: " << plugin->getMinChannelCount() << endl; cout << " - Maximum Channels: " << plugin->getMaxChannelCount() << endl; } else if (verbosity == PluginIds) { cout << "vamp:" << key << endl; } Plugin::OutputList outputs = plugin->getOutputDescriptors(); if (verbosity == PluginInformationDetailed) { Plugin::ParameterList params = plugin->getParameterDescriptors(); for (size_t j = 0; j < params.size(); ++j) { Plugin::ParameterDescriptor &pd(params[j]); cout << "\nParameter " << j+1 << ": \"" << pd.name << "\"" << endl; cout << " - Identifier: " << pd.identifier << endl; cout << " - Description: \"" << pd.description << "\"" << endl; if (pd.unit != "") { cout << " - Unit: " << pd.unit << endl; } cout << " - Range: "; cout << pd.minValue << " -> " << pd.maxValue << endl; cout << " - Default: "; cout << pd.defaultValue << endl; if (pd.isQuantized) { cout << " - Quantize Step: " << pd.quantizeStep << endl; } if (!pd.valueNames.empty()) { cout << " - Value Names: "; for (size_t k = 0; k < pd.valueNames.size(); ++k) { if (k > 0) cout << ", "; cout << "\"" << pd.valueNames[k] << "\""; } cout << endl; } } if (outputs.empty()) { cout << "\n** Note: This plugin reports no outputs!" << endl; } for (size_t j = 0; j < outputs.size(); ++j) { Plugin::OutputDescriptor &od(outputs[j]); cout << "\nOutput " << j+1 << ": \"" << od.name << "\"" << endl; cout << " - Identifier: " << od.identifier << endl; cout << " - Description: \"" << od.description << "\"" << endl; if (od.unit != "") { cout << " - Unit: " << od.unit << endl; } if (od.hasFixedBinCount) { cout << " - Default Bin Count: " << od.binCount << endl; } if (!od.binNames.empty()) { bool have = false; for (size_t k = 0; k < od.binNames.size(); ++k) { if (od.binNames[k] != "") { have = true; break; } } if (have) { cout << " - Bin Names: "; for (size_t k = 0; k < od.binNames.size(); ++k) { if (k > 0) cout << ", "; cout << "\"" << od.binNames[k] << "\""; } cout << endl; } } if (od.hasKnownExtents) { cout << " - Default Extents: "; cout << od.minValue << " -> " << od.maxValue << endl; } if (od.isQuantized) { cout << " - Quantize Step: " << od.quantizeStep << endl; } cout << " - Sample Type: " << (od.sampleType == Plugin::OutputDescriptor::OneSamplePerStep ? "One Sample Per Step" : od.sampleType == Plugin::OutputDescriptor::FixedSampleRate ? "Fixed Sample Rate" : "Variable Sample Rate") << endl; if (od.sampleType != Plugin::OutputDescriptor::OneSamplePerStep) { cout << " - Default Rate: " << od.sampleRate << endl; } cout << " - Has Duration: " << (od.hasDuration ? "Yes" : "No") << endl; } } if (outputs.size() > 1 || verbosity == PluginOutputIds) { for (size_t j = 0; j < outputs.size(); ++j) { if (verbosity == PluginInformation) { cout << " (" << j << ") " << outputs[j].name << ", \"" << outputs[j].identifier << "\"" << endl; if (outputs[j].description != "") { cout << " - " << outputs[j].description << endl; } } else if (verbosity == PluginOutputIds) { cout << "vamp:" << key << ":" << outputs[j].identifier << endl; } } } ++index; delete plugin; } } if (verbosity == PluginInformation || verbosity == PluginInformationDetailed) { cout << endl; } }
int runPlugin(string myname, string soname, string id, string output, int outputNo, bool useFrames, PaStreamParameters inputParameters) { float *recordedSamples; float *fifo; PaStream* stream; PaError err = paNoError; int elapsed = 0; int returnValue = 1; RealTime rt; PluginWrapper *wrapper = 0; RealTime adjustment = RealTime::zeroTime; PluginLoader *loader = PluginLoader::getInstance(); PluginLoader::PluginKey key = loader->composePluginKey(soname, id); // load plugin Plugin *plugin = loader->loadPlugin(key, SAMPLE_RATE, PluginLoader::ADAPT_ALL_SAFE); if (!plugin) { cerr << myname << ": ERROR: Failed to load plugin \"" << id << "\" from library \"" << soname << "\"" << endl; return 1; } // Find block/step size 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; } // set up port audio fifo = new float[blockSize](); recordedSamples = new float[stepSize](); ofstream *out = 0; cerr << "Running plugin: \"" << plugin->getIdentifier() << "\"..." << endl; cerr << "Using block size = " << blockSize << ", step size = " << stepSize << endl; // display output name Plugin::OutputList outputs = plugin->getOutputDescriptors(); Plugin::OutputDescriptor od; 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; // Initialise plugin if (!plugin->initialise(1, stepSize, blockSize)) { cerr << "ERROR: Plugin initialise (stepSize = " << stepSize << ", blockSize = " << blockSize << ") failed." << endl; goto done; } // Compensate timestamp if in freq domain wrapper = dynamic_cast<PluginWrapper *>(plugin); if (wrapper) { PluginInputDomainAdapter *ida = wrapper->getWrapper<PluginInputDomainAdapter>(); if (ida) adjustment = ida->getTimestampAdjustment(); } // Open portaudio stream err = Pa_OpenStream( &stream, &inputParameters, NULL, SAMPLE_RATE, stepSize, paClipOff, NULL, NULL ); if( err != paNoError ) throwError(err); // Start the audio stream err = Pa_StartStream( stream ); if( err != paNoError ) throwError(err); // printf("Now recording!!\n"); fflush(stdout); // do until interruptFlag is true while (1) { // read step of audio data err = Pa_ReadStream( stream, recordedSamples, stepSize ); if( err != paNoError ) throwError(err); // shift buffer along a step size for (int i=stepSize; i<blockSize; i++) fifo[i-stepSize] = fifo[i]; // add new step onto end for (int i=0; i<stepSize; i++) fifo[blockSize-stepSize+i] = recordedSamples[i]; // process and print features rt = RealTime::frame2RealTime(elapsed*stepSize, SAMPLE_RATE); printFeatures(RealTime::realTime2Frame(rt + adjustment, SAMPLE_RATE), SAMPLE_RATE, outputNo, plugin->process(&fifo, rt), out, useFrames); // note number of blocks processed elapsed++; // break out of loop if (interruptFlag) break; } // stop the audio stream err = Pa_CloseStream( stream ); if( err != paNoError ) throwError(err); // clean up variables delete [] recordedSamples; delete [] fifo; returnValue = 0; done: delete plugin; return returnValue; }
int runPlugin(string myname, string soname, string id, string output, int outputNo, string wavname, string outfilename, bool useFrames, map<string,float> parameters) { PluginLoader *loader = PluginLoader::getInstance(); PluginLoader::PluginKey key = loader->composePluginKey(soname, id); SNDFILE *sndfile; SF_INFO sfinfo; memset(&sfinfo, 0, sizeof(SF_INFO)); if (wavname == "") sndfile = sf_open_fd(0, SFM_READ, &sfinfo, true); else sndfile = sf_open(wavname.c_str(), SFM_READ, &sfinfo); if (!sndfile) { cerr << myname << ": ERROR: Failed to open input file \"" << wavname << "\": " << sf_strerror(sndfile) << endl; return 1; } ofstream *out = 0; if (outfilename != "") { out = new ofstream(outfilename.c_str(), ios::out); if (!*out) { cerr << myname << ": ERROR: Failed to open output file \"" << outfilename << "\" for writing" << endl; delete out; 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); if (out) { out->close(); delete out; } return 1; } cerr << "Running plugin: \"" << plugin->getIdentifier() << "\"..." << endl; // parameters for (map<string,float>::iterator iter = parameters.begin(); iter!=parameters.end(); iter++) { plugin->setParameter(iter->first, iter->second); cerr << "Set parameter " << iter->first << " = " << iter->second << 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); printFeatures (RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate), sfinfo.samplerate, outputNo, plugin->process(plugbuf, rt), out, useFrames); if (sfinfo.frames > 0){ int pp = progress; progress = (int)((float(currentStep * stepSize) / sfinfo.frames) * 100.f + 0.5f); if (progress != pp && out) { cerr << "\r" << progress << "%"; } } ++currentStep; } while (finalStepsRemaining > 0); if (out) cerr << "\rDone" << endl; rt = RealTime::frame2RealTime(currentStep * stepSize, sfinfo.samplerate); printFeatures(RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate), sfinfo.samplerate, outputNo, plugin->getRemainingFeatures(), out, useFrames); returnValue = 0; done: delete plugin; if (out) { out->close(); delete out; } sf_close(sndfile); return returnValue; }
bool VampEffectsModule::AutoRegisterPlugins(PluginManagerInterface & pm) { #ifdef EFFECT_CATEGORIES InitCategoryMap(); #endif PluginLoader *loader = PluginLoader::getInstance(); EffectManager& em = EffectManager::Get(); PluginLoader::PluginKeyList keys = loader->listPlugins(); for (PluginLoader::PluginKeyList::iterator i = keys.begin(); i != keys.end(); ++i) { Plugin *vp = loader->loadPlugin(*i, 48000); // rate doesn't matter here if (!vp) continue; #ifdef EFFECT_CATEGORIES PluginLoader::PluginCategoryHierarchy category = loader->getPluginCategory(*i); wxString vampCategory = VampHierarchyToUri(category); #endif // We limit the listed plugin outputs to those whose results can // readily be displayed in an Audacity label track. // // - Any output whose features have no values (time instants only), // with or without duration, is fine // // - Any output whose features have more than one value, or an // unknown or variable number of values, is right out // // - Any output whose features have exactly one value, with // variable sample rate or with duration, should be OK -- // this implies a sparse feature, of which the time and/or // duration are significant aspects worth displaying // // - An output whose features have exactly one value, with // fixed sample rate and no duration, cannot be usefully // displayed -- the value is the only significant piece of // data there and we have no good value plot Plugin::OutputList outputs = vp->getOutputDescriptors(); int n = 0; bool hasParameters = !vp->getParameterDescriptors().empty(); for (Plugin::OutputList::iterator j = outputs.begin(); j != outputs.end(); ++j) { if (j->sampleType == Plugin::OutputDescriptor::FixedSampleRate || j->sampleType == Plugin::OutputDescriptor::OneSamplePerStep || !j->hasFixedBinCount || (j->hasFixedBinCount && j->binCount > 1)) { // All of these qualities disqualify (see notes above) ++n; continue; } wxString name = LAT1CTOWX(vp->getName().c_str()); if (outputs.size() > 1) { // This is not the plugin's only output. // Use "plugin name: output name" as the effect name, // unless the output name is the same as the plugin name wxString outputName = LAT1CTOWX(j->name.c_str()); if (outputName != name) { name = wxString::Format(wxT("%s: %s"), name.c_str(), outputName.c_str()); } } #ifdef EFFECT_CATEGORIES VampEffect *effect = new VampEffect(*i, n, hasParameters, name, vampCategory); #else VampEffect *effect = new VampEffect(*i, n, hasParameters, name); #endif em.RegisterEffect(this, effect); ++n; } delete vp; } return true; }
int main(int argc, char **argv) { const char *myname = argv[0]; if (argc != 2) { cerr << "usage: " << myname << " file.wav" << endl; return 2; } const char *infile = argv[1]; SF_INFO sfinfo; SNDFILE *sndfile = sf_open(infile, SFM_READ, &sfinfo); if (!sndfile) { cerr << myname << ": Failed to open input file " << infile << ": " << sf_strerror(sndfile) << endl; return 1; } Chordino *chordino = new Chordino(sfinfo.samplerate); PluginInputDomainAdapter *ia = new PluginInputDomainAdapter(chordino); ia->setProcessTimestampMethod(PluginInputDomainAdapter::ShiftData); PluginBufferingAdapter *adapter = new PluginBufferingAdapter(ia); int blocksize = adapter->getPreferredBlockSize(); // Plugin requires 1 channel (we will mix down) if (!adapter->initialise(1, blocksize, blocksize)) { cerr << myname << ": Failed to initialise Chordino adapter!" << endl; return 1; } float *filebuf = new float[sfinfo.channels * blocksize]; float *mixbuf = new float[blocksize]; Plugin::FeatureList chordFeatures; Plugin::FeatureSet fs; int chordFeatureNo = -1; Plugin::OutputList outputs = adapter->getOutputDescriptors(); for (int i = 0; i < int(outputs.size()); ++i) { if (outputs[i].identifier == "simplechord") { chordFeatureNo = i; } } if (chordFeatureNo < 0) { cerr << myname << ": Failed to identify chords output!" << endl; return 1; } int frame = 0; while (frame < sfinfo.frames) { int count = -1; if ((count = sf_readf_float(sndfile, filebuf, blocksize)) <= 0) break; // mix down for (int i = 0; i < blocksize; ++i) { mixbuf[i] = 0.f; if (i < count) { for (int c = 0; c < sfinfo.channels; ++c) { mixbuf[i] += filebuf[i * sfinfo.channels + c] / sfinfo.channels; } } } RealTime timestamp = RealTime::frame2RealTime(frame, sfinfo.samplerate); // feed to plugin: can just take address of buffer, as only one channel fs = adapter->process(&mixbuf, timestamp); chordFeatures.insert(chordFeatures.end(), fs[chordFeatureNo].begin(), fs[chordFeatureNo].end()); frame += count; } sf_close(sndfile); // features at end of processing (actually Chordino does all its work here) fs = adapter->getRemainingFeatures(); // chord output is output index 0 chordFeatures.insert(chordFeatures.end(), fs[chordFeatureNo].begin(), fs[chordFeatureNo].end()); for (int i = 0; i < (int)chordFeatures.size(); ++i) { cout << chordFeatures[i].timestamp.toString() << ": " << chordFeatures[i].label << endl; } delete[] filebuf; delete[] mixbuf; delete adapter; }
void VampAnalyser::SelectOutput(const int outputnumber) { Plugin::OutputList outputs = m_plugin->getOutputDescriptors(); if (outputnumber >= 0 && outputnumber < int(outputs.size())) { m_iOutput = outputnumber; } }
bool VampAnalyser::Init(const QString pluginlibrary, const QString pluginid, const int samplerate, const int TotalSamples, bool bFastAnalysis) { m_iRemainingSamples = TotalSamples; m_rate = samplerate; if (samplerate <= 0.0) { qDebug() << "VampAnalyser: Track has non-positive samplerate"; return false; } if (TotalSamples <= 0) { qDebug() << "VampAnalyser: Track has non-positive # of samples"; return false; } if (m_plugin != NULL) { delete m_plugin; m_plugin = NULL; qDebug() << "VampAnalyser: kill plugin"; } VampPluginLoader *loader = VampPluginLoader::getInstance(); QStringList pluginlist = pluginid.split(":"); if (pluginlist.size() != 2) { qDebug() << "VampAnalyser: got malformed pluginid: " << pluginid; return false; } bool isNumber = false; int outputnumber = (pluginlist.at(1)).toInt(&isNumber); if (!isNumber) { qDebug() << "VampAnalyser: got malformed pluginid: " << pluginid; return false; } QString plugin = pluginlist.at(0); m_key = loader->composePluginKey(pluginlibrary.toStdString(), plugin.toStdString()); m_plugin = loader->loadPlugin(m_key, m_rate, Vamp::HostExt::PluginLoader::ADAPT_ALL_SAFE); if (!m_plugin) { qDebug() << "VampAnalyser: Cannot load Vamp Plug-in."; qDebug() << "Please copy libmixxxminimal.so from build dir to one of the following:"; std::vector<std::string> path = PluginHostAdapter::getPluginPath(); for (unsigned int i = 0; i < path.size(); i++) { qDebug() << QString::fromStdString(path[i]); } return false; } Plugin::OutputList outputs = m_plugin->getOutputDescriptors(); if (outputs.empty()) { qDebug() << "VampAnalyser: Plugin has no outputs!"; return false; } SelectOutput(outputnumber); m_iBlockSize = m_plugin->getPreferredBlockSize(); qDebug() << "Vampanalyser BlockSize: " << m_iBlockSize; if (m_iBlockSize == 0) { // A plugin that can handle any block size may return 0. The final block // size will be set in the initialise() call. Since 0 means it is // accepting any size, 1024 should be good m_iBlockSize = 1024; qDebug() << "Vampanalyser: setting m_iBlockSize to 1024"; } m_iStepSize = m_plugin->getPreferredStepSize(); qDebug() << "Vampanalyser StepSize: " << m_iStepSize; if (m_iStepSize == 0 || m_iStepSize > m_iBlockSize) { // A plugin may return 0 if it has no particular interest in the step // size. In this case, the host should make the step size equal to the // block size if the plugin is accepting input in the time domain. If // the plugin is accepting input in the frequency domain, the host may // use any step size. The final step size will be set in the // initialise() call. m_iStepSize = m_iBlockSize; qDebug() << "Vampanalyser: setting m_iStepSize to" << m_iStepSize; } if (!m_plugin->initialise(2, m_iStepSize, m_iBlockSize)) { qDebug() << "VampAnalyser: Cannot initialise plugin"; return false; } // Here we are using m_iBlockSize: it cannot be 0 m_pluginbuf[0] = new CSAMPLE[m_iBlockSize]; m_pluginbuf[1] = new CSAMPLE[m_iBlockSize]; m_FastAnalysisEnabled = bFastAnalysis; if (m_FastAnalysisEnabled) { qDebug() << "Using fast analysis methods for BPM and Replay Gain."; m_iMaxSamplesToAnalyse = 120 * m_rate; //only consider the first minute } return true; }
Plugin *VampEffectsModule::FindPlugin(const wxString & path, int & output, bool & hasParameters) { PluginLoader::PluginKey key = path.BeforeLast(wxT('/')).ToUTF8().data(); Plugin *vp = PluginLoader::getInstance()->loadPlugin(key, 48000); // rate doesn't matter here if (!vp) { return false; } // We limit the listed plugin outputs to those whose results can // readily be displayed in an Audacity label track. // // - Any output whose features have no values (time instants only), // with or without duration, is fine // // - Any output whose features have more than one value, or an // unknown or variable number of values, is right out // // - Any output whose features have exactly one value, with // variable sample rate or with duration, should be OK -- // this implies a sparse feature, of which the time and/or // duration are significant aspects worth displaying // // - An output whose features have exactly one value, with // fixed sample rate and no duration, cannot be usefully // displayed -- the value is the only significant piece of // data there and we have no good value plot Plugin::OutputList outputs = vp->getOutputDescriptors(); output = 0; hasParameters = !vp->getParameterDescriptors().empty(); for (Plugin::OutputList::iterator j = outputs.begin(); j != outputs.end(); ++j) { if (j->sampleType == Plugin::OutputDescriptor::FixedSampleRate || j->sampleType == Plugin::OutputDescriptor::OneSamplePerStep || !j->hasFixedBinCount || (j->hasFixedBinCount && j->binCount > 1)) { // All of these qualities disqualify (see notes above) ++output; continue; } wxString name = wxString::FromUTF8(vp->getName().c_str()); if (outputs.size() > 1) { // This is not the plugin's only output. // Use "plugin name: output name" as the effect name, // unless the output name is the same as the plugin name wxString outputName = wxString::FromUTF8(j->name.c_str()); if (outputName != name) { name = wxString::Format(wxT("%s: %s"), name.c_str(), outputName.c_str()); } } if (wxString::FromUTF8(key.c_str()) + wxT("/") + name == path) { return vp; } ++output; } delete vp; return NULL; }
wxArrayString VampEffectsModule::FindPlugins(PluginManagerInterface & WXUNUSED(pm)) { wxArrayString names; PluginLoader *loader = PluginLoader::getInstance(); PluginLoader::PluginKeyList keys = loader->listPlugins(); for (PluginLoader::PluginKeyList::iterator i = keys.begin(); i != keys.end(); ++i) { Plugin *vp = PluginLoader::getInstance()->loadPlugin(*i, 48000); // rate doesn't matter here if (!vp) { continue; } // We limit the listed plugin outputs to those whose results can // readily be displayed in an Audacity label track. // // - Any output whose features have no values (time instants only), // with or without duration, is fine // // - Any output whose features have more than one value, or an // unknown or variable number of values, is right out // // - Any output whose features have exactly one value, with // variable sample rate or with duration, should be OK -- // this implies a sparse feature, of which the time and/or // duration are significant aspects worth displaying // // - An output whose features have exactly one value, with // fixed sample rate and no duration, cannot be usefully // displayed -- the value is the only significant piece of // data there and we have no good value plot Plugin::OutputList outputs = vp->getOutputDescriptors(); int output = 0; for (Plugin::OutputList::iterator j = outputs.begin(); j != outputs.end(); ++j) { if (j->sampleType == Plugin::OutputDescriptor::FixedSampleRate || j->sampleType == Plugin::OutputDescriptor::OneSamplePerStep || !j->hasFixedBinCount || (j->hasFixedBinCount && j->binCount > 1)) { // All of these qualities disqualify (see notes above) ++output; continue; } wxString name = wxString::FromUTF8(vp->getName().c_str()); if (outputs.size() > 1) { // This is not the plugin's only output. // Use "plugin name: output name" as the effect name, // unless the output name is the same as the plugin name wxString outputName = wxString::FromUTF8(j->name.c_str()); if (outputName != name) { name = wxString::Format(wxT("%s: %s"), name.c_str(), outputName.c_str()); } } wxString path = wxString::FromUTF8(i->c_str()) + wxT("/") + name; names.Add(path); ++output; } delete vp; } return names; }
wxString VAMPPluginDialog::ProcessPlugin(xLightsXmlFile* xml_file, xLightsFrame *xLightsParent, const wxString &name, AudioManager* media) { Vamp::Plugin *p = media->GetVamp()->GetPlugin(std::string(name.c_str())); Label1->SetLabel(p->getName()); Label2->SetLabel(p->getDescription()); int output = 0; Plugin::OutputList outputs = p->getOutputDescriptors(); if (outputs.size() > 1) { for (int x = 0; x < outputs.size(); x++) { wxString pname = wxString::FromUTF8(p->getName().c_str()); wxString outputName = wxString::FromUTF8(outputs[x].name.c_str()); if (outputName != pname) { pname = wxString::Format(wxT("%s: %s"), pname.c_str(), outputName.c_str()); } if (name == pname) { output = x; TimingName->SetValue(outputName); } } } else { TimingName->SetValue(p->getName()); } PluginBase::ParameterList params = p->getParameterDescriptors(); std::vector<void *> controls; for (int x = 0; x < params.size(); x++) { wxString tip = wxString::FromUTF8(params[x].description.c_str()); wxString unit = wxString::FromUTF8(params[x].unit.c_str()); float value = p->getParameter(params[x].identifier); wxString labelText = wxString::FromUTF8(params[x].name.c_str()); if (!unit.IsEmpty()) { labelText += wxT(" (") + unit + wxT(")"); } wxStaticText *desc = new wxStaticText(this, wxID_ANY, labelText + wxT(":")); SettingsSizer->Add(desc, 1, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5); if (params[x].isQuantized && params[x].quantizeStep == 1.0 && params[x].minValue == 0.0 && params[x].maxValue == 1.0) { wxCheckBox *cb = new wxCheckBox(this, wxID_ANY, _("")); cb->SetValue(value > 0.5); if (!tip.IsEmpty()) { cb->SetToolTip(tip); } SettingsSizer->Add(cb, 1, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5); controls.push_back(cb); } else if (params[x].isQuantized && params[x].quantizeStep == 1.0 && !params[x].valueNames.empty()) { wxChoice *choice = new wxChoice(this, wxID_ANY); for (size_t i = 0, cnt = params[x].valueNames.size(); i < cnt; i++) { wxString choicetxt = wxString::FromUTF8(params[x].valueNames[i].c_str()); choice->Append(choicetxt); if (size_t(value - params[x].minValue + 0.5) == i) { choice->SetSelection(i); } } choice->SetSizeHints(-1, -1); if (!tip.IsEmpty()) { choice->SetToolTip(tip); } SettingsSizer->Add(choice, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5); controls.push_back(choice); } else { FloatSliderControl *slider = new FloatSliderControl(this, value, params[x].minValue, params[x].maxValue, tip); SettingsSizer->Add(slider, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5); controls.push_back(slider); } } Fit(); int res = ShowModal(); if (res == wxID_OK) { while (xml_file->TimingAlreadyExists(TimingName->GetValue().ToStdString(), xLightsParent)) { wxMessageBox("Timing track " + TimingName->GetValue() + " already exists"); res = ShowModal(); if (res != wxID_OK) { return ""; } } std::vector<int> starts; std::vector<int> ends; std::vector<std::string> labels; size_t step = p->getPreferredStepSize(); size_t block = p->getPreferredBlockSize(); if (block == 0) { if (step != 0) { block = step; } else { block = 1024; } } if (step == 0) { step = block; } float *pdata[2]; std::string error; media->SetStepBlock(step, block); for (int x = 0; x < params.size(); x++) { if (params[x].isQuantized && params[x].quantizeStep == 1.0 && params[x].minValue == 0.0 && params[x].maxValue == 1.0) { wxCheckBox *cb = (wxCheckBox*)controls[x]; p->setParameter(params[x].identifier, cb->GetValue()); } else if (params[x].isQuantized && params[x].quantizeStep == 1.0 && !params[x].valueNames.empty()) { wxChoice *choice = (wxChoice*)controls[x]; p->setParameter(params[x].identifier, choice->GetSelection()); } else { FloatSliderControl *slider = (FloatSliderControl*)controls[x]; p->setParameter(params[x].identifier, slider->GetValue()); } } int channels = media->GetChannels(); if (channels > p->getMaxChannelCount()) { channels = 1; } p->initialise(channels, step, block); pdata[0] =media->GetLeftDataPtr(0); pdata[1] = media->GetRightDataPtr(0); wxProgressDialog progress("Processing Audio", ""); int totalLen = media->GetTrackSize(); int len = media->GetTrackSize(); int percent = 0; int start = 0; while (len) { int request = block; if (request > len) request = len; pdata[0] = media->GetLeftDataPtr(start); pdata[1] = media->GetRightDataPtr(start); Vamp::RealTime timestamp = Vamp::RealTime::frame2RealTime(start, media->GetRate()); Vamp::Plugin::FeatureSet features = p->process(pdata, timestamp); processFeatures(features[output], starts, ends, labels); if (len > (int)step) { len -= step; } else { len = 0; } start += step; int newp = (start * 100) / totalLen; if (newp != percent) { percent = newp; progress.Update(percent); } } Vamp::Plugin::FeatureSet features = p->getRemainingFeatures(); processFeatures(features[output], starts, ends, labels); progress.Update(100); xml_file->AddNewTimingSection(TimingName->GetValue().ToStdString(), xLightsParent, starts, ends, labels); return TimingName->GetValue(); } return ""; }