Test::Results TestDefaultParameters::test(string key, Options options) { Plugin::FeatureSet f[2]; int rate = 44100; Results r; float **data = 0; size_t channels = 0; size_t count = 100; for (int run = 0; run < 2; ++run) { auto_ptr<Plugin> p(load(key, rate)); if (p->getParameterDescriptors().empty()) return r; if (run == 1) { Plugin::ParameterList pl = p->getParameterDescriptors(); for (int i = 0; i < (int)pl.size(); ++i) { if (p->getParameter(pl[i].identifier) != pl[i].defaultValue) { if (options & Verbose) { cout << "Parameter: " << pl[i].identifier << endl; cout << "Expected: " << pl[i].defaultValue << endl; cout << "Actual: " << p->getParameter(pl[i].identifier) << endl; } r.push_back(error("Not all parameters have their default values when queried directly after construction")); } p->setParameter(pl[i].identifier, pl[i].defaultValue); } } if (!initAdapted(p.get(), channels, _step, _step, r)) return r; if (!data) data = createTestAudio(channels, _step, count); for (size_t i = 0; i < count; ++i) { #ifdef __GNUC__ float *ptr[channels]; #else float **ptr = (float **)alloca(channels * sizeof(float)); #endif size_t idx = i * _step; for (size_t c = 0; c < channels; ++c) ptr[c] = data[c] + idx; RealTime timestamp = RealTime::frame2RealTime(idx, rate); Plugin::FeatureSet fs = p->process(ptr, timestamp); appendFeatures(f[run], fs); } Plugin::FeatureSet fs = p->getRemainingFeatures(); appendFeatures(f[run], fs); } if (data) destroyTestAudio(data, channels); if (!(f[0] == f[1])) { string message = "Explicitly setting parameters to their supposed default values changes the results"; Result res; if (options & NonDeterministic) res = note(message); else res = error(message); if (options & Verbose) dumpDiff(res, f[0], f[1]); r.push_back(res); } else { r.push_back(success()); } return r; }
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; } }
Test::Results TestParametersOnReset::test(string key, Options options) { Plugin::FeatureSet f[2]; int rate = 44100; Results r; float **data = 0; size_t channels = 0; size_t count = 100; for (int run = 0; run < 2; ++run) { auto_ptr<Plugin> p(load(key, rate)); if (p->getParameterDescriptors().empty()) return r; // Set all parameters to non-default values Plugin::ParameterList pl = p->getParameterDescriptors(); for (int i = 0; i < (int)pl.size(); ++i) { // Half-way between default and max value, seems a // reasonable guess for something to set it to. We want to // avoid the real extremes because they can sometimes be // very slow, and we want to avoid setting everything to // the same values (e.g. min) because plugins will // sometimes legitimately reject that. // Remember to take into account quantization float value = (pl[i].defaultValue + pl[i].maxValue) / 2; if (pl[i].isQuantized) { value = round(value / pl[i].quantizeStep) * pl[i].quantizeStep; } if (value > pl[i].maxValue) { value = pl[i].maxValue; } if (value < pl[i].minValue) { value = pl[i].minValue; } if (value == pl[i].defaultValue) { if (pl[i].defaultValue == pl[i].minValue) { value = pl[i].maxValue; } else { value = pl[i].minValue; } } p->setParameter(pl[i].identifier, value); } if (!initAdapted(p.get(), channels, _step, _step, r)) { // OK, plugin didn't like that. Let's try a different tack // -- set everything to min except those parameters whose // default is min, and set those to half way instead for (int i = 0; i < (int)pl.size(); ++i) { float value = pl[i].minValue; if (value == pl[i].defaultValue) { value = (pl[i].maxValue + pl[i].minValue) / 2; value = ceil(value / pl[i].quantizeStep) * pl[i].quantizeStep; if (value > pl[i].maxValue) { value = pl[i].maxValue; } } p->setParameter(pl[i].identifier, value); } r = Results(); if (!initAdapted(p.get(), channels, _step, _step, r)) { // Still didn't work, give up return r; } } // First run: construct, set params, init, process // Second run: construct, set params, init, reset, process // We expect these to produce the same results if (run == 1) p->reset(); if (!data) data = createTestAudio(channels, _step, count); for (size_t i = 0; i < count; ++i) { #ifdef __GNUC__ float *ptr[channels]; #else float **ptr = (float **)alloca(channels * sizeof(float)); #endif size_t idx = i * _step; for (size_t c = 0; c < channels; ++c) ptr[c] = data[c] + idx; RealTime timestamp = RealTime::frame2RealTime(idx, rate); Plugin::FeatureSet fs = p->process(ptr, timestamp); appendFeatures(f[run], fs); } Plugin::FeatureSet fs = p->getRemainingFeatures(); appendFeatures(f[run], fs); } if (data) destroyTestAudio(data, channels); if (!(f[0] == f[1])) { string message = "Call to reset after setting parameters, but before processing, changes the results (parameter values not retained through reset?)"; Result res; if (options & NonDeterministic) res = note(message); else res = error(message); if (options & Verbose) dumpDiff(res, f[0], f[1]); r.push_back(res); } else { r.push_back(success()); } return r; }