base rename
This commit is contained in:
parent
103f458e8e
commit
e95b339dbb
@ -1,50 +0,0 @@
|
||||
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||
|
||||
/*
|
||||
Vamp
|
||||
|
||||
An API for audio analysis and feature extraction plugins.
|
||||
|
||||
Centre for Digital Music, Queen Mary, University of London.
|
||||
Copyright 2006 Chris Cannam.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
||||
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the names of the Centre for
|
||||
Digital Music; Queen Mary, University of London; and Chris Cannam
|
||||
shall not be used in advertising or otherwise to promote the sale,
|
||||
use or other dealings in this Software without prior written
|
||||
authorization.
|
||||
*/
|
||||
|
||||
#ifndef _SYSTEM_H_
|
||||
#define _SYSTEM_H_
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define DLOPEN(a,b) dlopen((a).c_str(),(b))
|
||||
#define DLSYM(a,b) dlsym((a),(b))
|
||||
#define DLCLOSE(a) dlclose((a))
|
||||
#define DLERROR() dlerror()
|
||||
#define PLUGIN_SUFFIX "so"
|
||||
#define HAVE_OPENDIR 1
|
||||
|
||||
#endif
|
||||
|
@ -1,40 +0,0 @@
|
||||
|
||||
#include <vamp-hostsdk/host-c.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
int libcount = vhGetLibraryCount();
|
||||
|
||||
printf("Vamp plugin libraries found:\n");
|
||||
for (i = 0; i < libcount; ++i) {
|
||||
printf("%d: %s\n", i, vhGetLibraryName(i));
|
||||
}
|
||||
|
||||
printf("Going to try loading qm-vamp-plugins...\n");
|
||||
int libindex = vhGetLibraryIndex("qm-vamp-plugins");
|
||||
vhLibrary lib = vhLoadLibrary(libindex);
|
||||
if (!lib) {
|
||||
printf("Failure!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int plugincount = vhGetPluginCount(lib);
|
||||
printf("Success: it contains %d plugins; they are:\n", plugincount);
|
||||
|
||||
for (i = 0; i < plugincount; ++i) {
|
||||
const VampPluginDescriptor *descriptor = vhGetPluginDescriptor(lib, i);
|
||||
if (!descriptor) {
|
||||
printf("<unknown! failed to load>\n");
|
||||
} else {
|
||||
printf("%s\n", descriptor->identifier);
|
||||
}
|
||||
}
|
||||
|
||||
vhUnloadLibrary(lib);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,863 +0,0 @@
|
||||
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||
|
||||
/*
|
||||
Vamp
|
||||
|
||||
An API for audio analysis and feature extraction plugins.
|
||||
|
||||
Centre for Digital Music, Queen Mary, University of London.
|
||||
Copyright 2006 Chris Cannam, copyright 2007-2008 QMUL.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
||||
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the names of the Centre for
|
||||
Digital Music; Queen Mary, University of London; and Chris Cannam
|
||||
shall not be used in advertising or otherwise to promote the sale,
|
||||
use or other dealings in this Software without prior written
|
||||
authorization.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This "simple" Vamp plugin host is no longer as simple as it was; it
|
||||
* now has a lot of options and includes a lot of code to handle the
|
||||
* various useful listing modes it supports.
|
||||
*
|
||||
* However, the runPlugin function still contains a reasonable
|
||||
* implementation of a fairly generic Vamp plugin host capable of
|
||||
* evaluating a given output on a given plugin for a sound file read
|
||||
* via libsndfile.
|
||||
*/
|
||||
|
||||
#include <vamp-hostsdk/PluginHostAdapter.h>
|
||||
#include <vamp-hostsdk/PluginInputDomainAdapter.h>
|
||||
#include <vamp-hostsdk/PluginLoader.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <set>
|
||||
#include <sndfile.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
using namespace std;
|
||||
|
||||
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"
|
||||
|
||||
enum Verbosity {
|
||||
PluginIds,
|
||||
PluginOutputIds,
|
||||
PluginInformation,
|
||||
PluginInformationDetailed
|
||||
};
|
||||
|
||||
void printFeatures(int, int,
|
||||
const Plugin::OutputDescriptor &, int,
|
||||
const Plugin::FeatureSet &, ofstream *, bool frames);
|
||||
void transformInput(float *, size_t);
|
||||
void fft(unsigned int, bool, double *, double *, double *, double *);
|
||||
void printPluginPath(bool verbose);
|
||||
void printPluginCategoryList();
|
||||
void enumeratePlugins(Verbosity);
|
||||
void listPluginsInLibrary(string soname);
|
||||
int runPlugin(string myname, string soname, string id, string output,
|
||||
int outputNo, string inputFile, string outfilename, bool frames);
|
||||
|
||||
void usage(const char *name)
|
||||
{
|
||||
cerr << "\n"
|
||||
<< name << ": A command-line host for Vamp audio analysis plugins.\n\n"
|
||||
"Centre for Digital Music, Queen Mary, University of London.\n"
|
||||
"Copyright 2006-2009 Chris Cannam and QMUL.\n"
|
||||
"Freely redistributable; published under a BSD-style license.\n\n"
|
||||
"Usage:\n\n"
|
||||
" " << name << " [-s] pluginlibrary[." << PLUGIN_SUFFIX << "]:plugin[:output] file.wav [-o out.txt]\n"
|
||||
" " << name << " [-s] pluginlibrary[." << PLUGIN_SUFFIX << "]:plugin file.wav [outputno] [-o out.txt]\n\n"
|
||||
" -- Load plugin id \"plugin\" from \"pluginlibrary\" and run it on the\n"
|
||||
" audio data in \"file.wav\", retrieving the named \"output\", or output\n"
|
||||
" number \"outputno\" (the first output by default) and dumping it to\n"
|
||||
" standard output, or to \"out.txt\" if the -o option is given.\n\n"
|
||||
" \"pluginlibrary\" should be a library name, not a file path; the\n"
|
||||
" standard Vamp library search path will be used to locate it. If\n"
|
||||
" a file path is supplied, the directory part(s) will be ignored.\n\n"
|
||||
" If the -s option is given, results will be labelled with the audio\n"
|
||||
" sample frame at which they occur. Otherwise, they will be labelled\n"
|
||||
" with time in seconds.\n\n"
|
||||
" " << name << " -l\n"
|
||||
" " << name << " --list\n\n"
|
||||
" -- List the plugin libraries and Vamp plugins in the library search path\n"
|
||||
" in a verbose human-readable format.\n\n"
|
||||
" " << name << " -L\n"
|
||||
" " << name << " --list-full\n\n"
|
||||
" -- List all data reported by all the Vamp plugins in the library search\n"
|
||||
" path in a very verbose human-readable format.\n\n"
|
||||
" " << name << " --list-ids\n\n"
|
||||
" -- List the plugins in the search path in a terse machine-readable format,\n"
|
||||
" in the form vamp:soname:identifier.\n\n"
|
||||
" " << name << " --list-outputs\n\n"
|
||||
" -- List the outputs for plugins in the search path in a machine-readable\n"
|
||||
" format, in the form vamp:soname:identifier:output.\n\n"
|
||||
" " << name << " --list-by-category\n\n"
|
||||
" -- List the plugins as a plugin index by category, in a machine-readable\n"
|
||||
" format. The format may change in future releases.\n\n"
|
||||
" " << name << " -p\n\n"
|
||||
" -- Print out the Vamp library search path.\n\n"
|
||||
" " << name << " -v\n\n"
|
||||
" -- Display version information only.\n"
|
||||
<< endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *scooter = argv[0];
|
||||
char *name = 0;
|
||||
while (scooter && *scooter) {
|
||||
if (*scooter == '/' || *scooter == '\\') name = ++scooter;
|
||||
else ++scooter;
|
||||
}
|
||||
if (!name || !*name) name = argv[0];
|
||||
|
||||
if (argc < 2) usage(name);
|
||||
|
||||
if (argc == 2) {
|
||||
|
||||
if (!strcmp(argv[1], "-v")) {
|
||||
|
||||
cout << "Simple Vamp plugin host version: " << HOST_VERSION << endl
|
||||
<< "Vamp API version: " << VAMP_API_VERSION << endl
|
||||
<< "Vamp SDK version: " << VAMP_SDK_VERSION << endl;
|
||||
return 0;
|
||||
|
||||
} else if (!strcmp(argv[1], "-l") || !strcmp(argv[1], "--list")) {
|
||||
|
||||
printPluginPath(true);
|
||||
enumeratePlugins(PluginInformation);
|
||||
return 0;
|
||||
|
||||
} else if (!strcmp(argv[1], "-L") || !strcmp(argv[1], "--list-full")) {
|
||||
|
||||
enumeratePlugins(PluginInformationDetailed);
|
||||
return 0;
|
||||
|
||||
} else if (!strcmp(argv[1], "-p")) {
|
||||
|
||||
printPluginPath(false);
|
||||
return 0;
|
||||
|
||||
} else if (!strcmp(argv[1], "--list-ids")) {
|
||||
|
||||
enumeratePlugins(PluginIds);
|
||||
return 0;
|
||||
|
||||
} else if (!strcmp(argv[1], "--list-outputs")) {
|
||||
|
||||
enumeratePlugins(PluginOutputIds);
|
||||
return 0;
|
||||
|
||||
} else if (!strcmp(argv[1], "--list-by-category")) {
|
||||
|
||||
printPluginCategoryList();
|
||||
return 0;
|
||||
|
||||
} else usage(name);
|
||||
}
|
||||
|
||||
if (argc < 3) usage(name);
|
||||
|
||||
bool useFrames = false;
|
||||
|
||||
int base = 1;
|
||||
if (!strcmp(argv[1], "-s")) {
|
||||
useFrames = true;
|
||||
base = 2;
|
||||
}
|
||||
|
||||
string soname = argv[base];
|
||||
string wavname = argv[base+1];
|
||||
string plugid = "";
|
||||
string output = "";
|
||||
int outputNo = -1;
|
||||
string outfilename;
|
||||
|
||||
if (argc >= base+3) {
|
||||
|
||||
int idx = base+2;
|
||||
|
||||
if (isdigit(*argv[idx])) {
|
||||
outputNo = atoi(argv[idx++]);
|
||||
}
|
||||
|
||||
if (argc == idx + 2) {
|
||||
if (!strcmp(argv[idx], "-o")) {
|
||||
outfilename = argv[idx+1];
|
||||
} else usage(name);
|
||||
} else if (argc != idx) {
|
||||
(usage(name));
|
||||
}
|
||||
}
|
||||
|
||||
cerr << endl << name << ": Running..." << endl;
|
||||
|
||||
cerr << "Reading file: \"" << wavname << "\", writing to ";
|
||||
if (outfilename == "") {
|
||||
cerr << "standard output" << endl;
|
||||
} else {
|
||||
cerr << "\"" << outfilename << "\"" << endl;
|
||||
}
|
||||
|
||||
string::size_type sep = soname.find(':');
|
||||
|
||||
if (sep != string::npos) {
|
||||
plugid = soname.substr(sep + 1);
|
||||
soname = soname.substr(0, sep);
|
||||
|
||||
sep = plugid.find(':');
|
||||
if (sep != string::npos) {
|
||||
output = plugid.substr(sep + 1);
|
||||
plugid = plugid.substr(0, sep);
|
||||
}
|
||||
}
|
||||
|
||||
if (plugid == "") {
|
||||
usage(name);
|
||||
}
|
||||
|
||||
if (output != "" && outputNo != -1) {
|
||||
usage(name);
|
||||
}
|
||||
|
||||
if (output == "" && outputNo == -1) {
|
||||
outputNo = 0;
|
||||
}
|
||||
|
||||
return runPlugin(name, soname, plugid, output, outputNo,
|
||||
wavname, outfilename, useFrames);
|
||||
}
|
||||
|
||||
|
||||
int runPlugin(string myname, string soname, string id,
|
||||
string output, int outputNo, string wavname,
|
||||
string outfilename, 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(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;
|
||||
|
||||
// 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;
|
||||
Plugin::FeatureSet features;
|
||||
|
||||
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);
|
||||
|
||||
features = plugin->process(plugbuf, rt);
|
||||
|
||||
printFeatures
|
||||
(RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate),
|
||||
sfinfo.samplerate, od, outputNo, features, 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);
|
||||
|
||||
features = plugin->getRemainingFeatures();
|
||||
|
||||
printFeatures(RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate),
|
||||
sfinfo.samplerate, od, outputNo, features, out, useFrames);
|
||||
|
||||
returnValue = 0;
|
||||
|
||||
done:
|
||||
delete plugin;
|
||||
if (out) {
|
||||
out->close();
|
||||
delete out;
|
||||
}
|
||||
sf_close(sndfile);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
static double
|
||||
toSeconds(const RealTime &time)
|
||||
{
|
||||
return time.sec + double(time.nsec + 1) / 1000000000.0;
|
||||
}
|
||||
|
||||
void
|
||||
printFeatures(int frame, int sr,
|
||||
const Plugin::OutputDescriptor &output, int outputNo,
|
||||
const Plugin::FeatureSet &features, ofstream *out, bool useFrames)
|
||||
{
|
||||
static int featureCount = -1;
|
||||
|
||||
if (features.find(outputNo) == features.end()) return;
|
||||
|
||||
for (size_t i = 0; i < features.at(outputNo).size(); ++i) {
|
||||
|
||||
const Plugin::Feature &f = features.at(outputNo).at(i);
|
||||
|
||||
bool haveRt = false;
|
||||
RealTime rt;
|
||||
|
||||
if (output.sampleType == Plugin::OutputDescriptor::VariableSampleRate) {
|
||||
rt = f.timestamp;
|
||||
haveRt = true;
|
||||
} else if (output.sampleType == Plugin::OutputDescriptor::FixedSampleRate) {
|
||||
int n = featureCount + 1;
|
||||
if (f.hasTimestamp) {
|
||||
n = int(round(toSeconds(f.timestamp) * output.sampleRate));
|
||||
}
|
||||
rt = RealTime::fromSeconds(double(n) / output.sampleRate);
|
||||
haveRt = true;
|
||||
featureCount = n;
|
||||
}
|
||||
|
||||
if (useFrames) {
|
||||
|
||||
int displayFrame = frame;
|
||||
|
||||
if (haveRt) {
|
||||
displayFrame = RealTime::realTime2Frame(rt, sr);
|
||||
}
|
||||
|
||||
(out ? *out : cout) << displayFrame;
|
||||
|
||||
if (f.hasDuration) {
|
||||
displayFrame = RealTime::realTime2Frame(f.duration, sr);
|
||||
(out ? *out : cout) << "," << displayFrame;
|
||||
}
|
||||
|
||||
(out ? *out : cout) << ":";
|
||||
|
||||
} else {
|
||||
|
||||
if (!haveRt) {
|
||||
rt = RealTime::frame2RealTime(frame, sr);
|
||||
}
|
||||
|
||||
(out ? *out : cout) << rt.toString();
|
||||
|
||||
if (f.hasDuration) {
|
||||
rt = f.duration;
|
||||
(out ? *out : cout) << "," << rt.toString();
|
||||
}
|
||||
|
||||
(out ? *out : cout) << ":";
|
||||
}
|
||||
|
||||
for (unsigned int j = 0; j < f.values.size(); ++j) {
|
||||
(out ? *out : cout) << " " << f.values[j];
|
||||
}
|
||||
(out ? *out : cout) << " " << f.label;
|
||||
|
||||
(out ? *out : cout) << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
printPluginPath(bool verbose)
|
||||
{
|
||||
if (verbose) {
|
||||
cout << "\nVamp plugin search path: ";
|
||||
}
|
||||
|
||||
vector<string> path = PluginHostAdapter::getPluginPath();
|
||||
for (size_t i = 0; i < path.size(); ++i) {
|
||||
if (verbose) {
|
||||
cout << "[" << path[i] << "]";
|
||||
} else {
|
||||
cout << path[i] << endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose) cout << endl;
|
||||
}
|
||||
|
||||
static
|
||||
string
|
||||
header(string text, int level)
|
||||
{
|
||||
string out = '\n' + text + '\n';
|
||||
for (size_t i = 0; i < text.length(); ++i) {
|
||||
out += (level == 1 ? '=' : level == 2 ? '-' : '~');
|
||||
}
|
||||
out += '\n';
|
||||
return out;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
printPluginCategoryList()
|
||||
{
|
||||
PluginLoader *loader = PluginLoader::getInstance();
|
||||
|
||||
vector<PluginLoader::PluginKey> plugins = loader->listPlugins();
|
||||
|
||||
set<string> printedcats;
|
||||
|
||||
for (size_t i = 0; i < plugins.size(); ++i) {
|
||||
|
||||
PluginLoader::PluginKey key = plugins[i];
|
||||
|
||||
PluginLoader::PluginCategoryHierarchy category =
|
||||
loader->getPluginCategory(key);
|
||||
|
||||
Plugin *plugin = loader->loadPlugin(key, 48000);
|
||||
if (!plugin) continue;
|
||||
|
||||
string catstr = "";
|
||||
|
||||
if (category.empty()) catstr = '|';
|
||||
else {
|
||||
for (size_t j = 0; j < category.size(); ++j) {
|
||||
catstr += category[j];
|
||||
catstr += '|';
|
||||
if (printedcats.find(catstr) == printedcats.end()) {
|
||||
std::cout << catstr << std::endl;
|
||||
printedcats.insert(catstr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << catstr << key << ":::" << plugin->getName() << ":::" << plugin->getMaker() << ":::" << plugin->getDescription() << std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
inc += include_directories('.')
|
||||
|
||||
headers = [
|
||||
'vamp-sdk/real_time/real_time.hpp',
|
||||
|
||||
'vamp.h',
|
||||
'vamp-hostsdk/Files.h',
|
||||
'vamp-hostsdk/host-c.h',
|
||||
@ -17,17 +19,15 @@ headers = [
|
||||
'vamp-sdk/ext/vamp_kiss_fft.h',
|
||||
'vamp-sdk/ext/vamp_kiss_fft_guts.h',
|
||||
'vamp-sdk/ext/vamp_kiss_fftr.h',
|
||||
|
||||
'vamp-sdk/FFT.h',
|
||||
'vamp-sdk/Plugin.h',
|
||||
'vamp-sdk/PluginAdapter.h',
|
||||
'vamp-sdk/PluginBase.h',
|
||||
'vamp-sdk/RealTime.h',
|
||||
'vamp-sdk/vamp-sdk.h'
|
||||
]
|
||||
|
||||
sources = [
|
||||
'vamp-hostsdk/acsymbols.cpp',
|
||||
'vamp-sdk/real_time/real_time.cpp',
|
||||
|
||||
'vamp-hostsdk/Files.cpp',
|
||||
'vamp-hostsdk/host-c.cpp',
|
||||
'vamp-hostsdk/PluginBufferingAdapter.cpp',
|
||||
@ -38,10 +38,8 @@ sources = [
|
||||
'vamp-hostsdk/PluginSummarisingAdapter.cpp',
|
||||
'vamp-hostsdk/PluginWrapper.cpp',
|
||||
|
||||
'vamp-sdk/acsymbols.cpp',
|
||||
'vamp-sdk/FFT.cpp',
|
||||
'vamp-sdk/PluginAdapter.cpp',
|
||||
'vamp-sdk/RealTime.cpp'
|
||||
]
|
||||
|
||||
lib = library(
|
||||
|
@ -18,7 +18,7 @@ std::vector<std::string> Files::listLibraryFiles()
|
||||
|
||||
std::vector<std::string> Files::listLibraryFilesMatching(Filter filter)
|
||||
{
|
||||
std::vector<std::string> path = Vamp::PluginHostAdapter::getPluginPath();
|
||||
std::vector<std::string> path = vamp::PluginHostAdapter::getPluginPath();
|
||||
std::vector<std::string> libraryFiles;
|
||||
|
||||
// we match case-insensitively, but only with ascii range
|
||||
|
@ -3,9 +3,6 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* This is a private implementation class for the Vamp Host SDK.
|
||||
*/
|
||||
class Files
|
||||
{
|
||||
public:
|
||||
|
@ -5,20 +5,16 @@
|
||||
#include "vamp-hostsdk/PluginInputDomainAdapter.h"
|
||||
|
||||
#include <iostream>
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
||||
using std::vector;
|
||||
using std::map;
|
||||
|
||||
namespace Vamp {
|
||||
|
||||
namespace HostExt {
|
||||
|
||||
namespace vamp::host
|
||||
{
|
||||
class PluginBufferingAdapter::Impl
|
||||
{
|
||||
public:
|
||||
Impl(Plugin *plugin, float inputSampleRate);
|
||||
Impl(plugin* p, float inputSampleRate);
|
||||
~Impl();
|
||||
|
||||
void setPluginStepSize(size_t stepSize);
|
||||
@ -35,7 +31,7 @@ public:
|
||||
|
||||
void reset();
|
||||
|
||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
||||
FeatureSet process(const float *const *inputBuffers, real_time timestamp);
|
||||
|
||||
FeatureSet getRemainingFeatures();
|
||||
|
||||
@ -194,7 +190,7 @@ protected:
|
||||
RingBuffer &operator=(const RingBuffer &); // not provided
|
||||
};
|
||||
|
||||
Plugin *m_plugin;
|
||||
plugin* m_plugin;
|
||||
size_t m_inputStepSize; // value passed to wrapper initialise()
|
||||
size_t m_inputBlockSize; // value passed to wrapper initialise()
|
||||
size_t m_setStepSize; // value passed to setPluginStepSize()
|
||||
@ -215,10 +211,9 @@ protected:
|
||||
void adjustFixedRateFeatureTime(int outputNo, Feature &);
|
||||
};
|
||||
|
||||
PluginBufferingAdapter::PluginBufferingAdapter(Plugin *plugin) :
|
||||
PluginWrapper(plugin)
|
||||
PluginBufferingAdapter::PluginBufferingAdapter(plugin* p) : PluginWrapper(p)
|
||||
{
|
||||
m_impl = new Impl(plugin, m_inputSampleRate);
|
||||
m_impl = new Impl(p, m_inputSampleRate);
|
||||
}
|
||||
|
||||
PluginBufferingAdapter::~PluginBufferingAdapter()
|
||||
@ -301,7 +296,7 @@ PluginBufferingAdapter::reset()
|
||||
|
||||
PluginBufferingAdapter::FeatureSet
|
||||
PluginBufferingAdapter::process(const float *const *inputBuffers,
|
||||
RealTime timestamp)
|
||||
real_time timestamp)
|
||||
{
|
||||
return m_impl->process(inputBuffers, timestamp);
|
||||
}
|
||||
@ -312,8 +307,8 @@ PluginBufferingAdapter::getRemainingFeatures()
|
||||
return m_impl->getRemainingFeatures();
|
||||
}
|
||||
|
||||
PluginBufferingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
|
||||
m_plugin(plugin),
|
||||
PluginBufferingAdapter::Impl::Impl(plugin* p, float inputSampleRate) :
|
||||
m_plugin(p),
|
||||
m_inputStepSize(0),
|
||||
m_inputBlockSize(0),
|
||||
m_setStepSize(0),
|
||||
@ -400,7 +395,7 @@ PluginBufferingAdapter::Impl::initialise(size_t channels, size_t stepSize, size_
|
||||
m_blockSize = m_plugin->getPreferredBlockSize();
|
||||
}
|
||||
|
||||
bool freq = (m_plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain);
|
||||
bool freq = (m_plugin->getInputDomain() == vamp::plugin::FrequencyDomain);
|
||||
|
||||
// or sensible defaults if it has no preference
|
||||
if (m_blockSize == 0) {
|
||||
@ -504,7 +499,7 @@ PluginBufferingAdapter::Impl::getOutputDescriptors() const
|
||||
void
|
||||
PluginBufferingAdapter::Impl::setParameter(std::string name, float value)
|
||||
{
|
||||
m_plugin->setParameter(name, value);
|
||||
m_plugin->set_parameter(name, value);
|
||||
|
||||
// Re-query outputs; properties such as bin count may have changed
|
||||
m_outputs.clear();
|
||||
@ -514,7 +509,7 @@ PluginBufferingAdapter::Impl::setParameter(std::string name, float value)
|
||||
void
|
||||
PluginBufferingAdapter::Impl::selectProgram(std::string name)
|
||||
{
|
||||
m_plugin->selectProgram(name);
|
||||
m_plugin->select_program(name);
|
||||
|
||||
// Re-query outputs; properties such as bin count may have changed
|
||||
m_outputs.clear();
|
||||
@ -538,7 +533,7 @@ PluginBufferingAdapter::Impl::reset()
|
||||
|
||||
PluginBufferingAdapter::FeatureSet
|
||||
PluginBufferingAdapter::Impl::process(const float *const *inputBuffers,
|
||||
RealTime timestamp)
|
||||
real_time timestamp)
|
||||
{
|
||||
if (m_inputStepSize == 0) {
|
||||
std::cerr << "PluginBufferingAdapter::process: ERROR: Plugin has not been initialised" << std::endl;
|
||||
@ -548,8 +543,7 @@ PluginBufferingAdapter::Impl::process(const float *const *inputBuffers,
|
||||
FeatureSet allFeatureSets;
|
||||
|
||||
if (m_unrun) {
|
||||
m_frame = RealTime::realTime2Frame(timestamp,
|
||||
int(m_inputSampleRate + 0.5));
|
||||
m_frame = real_time::rt2f(timestamp, int(m_inputSampleRate + 0.5));
|
||||
m_unrun = false;
|
||||
}
|
||||
|
||||
@ -594,7 +588,7 @@ PluginBufferingAdapter::Impl::adjustFixedRateFeatureTime(int outputNo,
|
||||
// cerr << " [secs = " << secs << ", no = " << m_fixedRateFeatureNos[outputNo] << "]";
|
||||
}
|
||||
|
||||
feature.timestamp = RealTime::fromSeconds
|
||||
feature.timestamp = real_time::from_seconds
|
||||
(m_fixedRateFeatureNos[outputNo] / rate);
|
||||
|
||||
// cerr << " to " << feature.timestamp << " (rate = " << rate << ", hasTimestamp = " << feature.hasTimestamp << ")" << endl;
|
||||
@ -654,13 +648,12 @@ PluginBufferingAdapter::Impl::processBlock(FeatureSet& allFeatureSets)
|
||||
}
|
||||
|
||||
long frame = m_frame;
|
||||
RealTime timestamp = RealTime::frame2RealTime
|
||||
(frame, int(m_inputSampleRate + 0.5));
|
||||
real_time timestamp = real_time::f2rt(frame, int(m_inputSampleRate + 0.5));
|
||||
|
||||
FeatureSet featureSet = m_plugin->process(m_buffers, timestamp);
|
||||
|
||||
PluginWrapper *wrapper = dynamic_cast<PluginWrapper *>(m_plugin);
|
||||
RealTime adjustment;
|
||||
real_time adjustment;
|
||||
if (wrapper) {
|
||||
PluginInputDomainAdapter *ida =
|
||||
wrapper->getWrapper<PluginInputDomainAdapter>();
|
||||
@ -716,7 +709,4 @@ PluginBufferingAdapter::Impl::processBlock(FeatureSet& allFeatureSets)
|
||||
// increment internal frame counter each time we step forward
|
||||
m_frame += m_stepSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,130 +2,20 @@
|
||||
|
||||
#include "vamp-hostsdk/PluginWrapper.h"
|
||||
|
||||
namespace Vamp {
|
||||
|
||||
namespace HostExt {
|
||||
|
||||
/**
|
||||
* \class PluginBufferingAdapter PluginBufferingAdapter.h <vamp-hostsdk/PluginBufferingAdapter.h>
|
||||
*
|
||||
* PluginBufferingAdapter is a Vamp plugin adapter that allows plugins
|
||||
* to be used by a host supplying an audio stream in non-overlapping
|
||||
* buffers of arbitrary size.
|
||||
*
|
||||
* A host using PluginBufferingAdapter may ignore the preferred step
|
||||
* and block size reported by the plugin, and still expect the plugin
|
||||
* to run. The value of blockSize and stepSize passed to initialise
|
||||
* should be the size of the buffer which the host will supply; the
|
||||
* stepSize should be equal to the blockSize.
|
||||
*
|
||||
* If the internal step size used for the plugin differs from that
|
||||
* supplied by the host, the adapter will modify the sample type and
|
||||
* rate specifications for the plugin outputs appropriately, and set
|
||||
* timestamps on the output features for outputs that formerly used a
|
||||
* different sample rate specification. This is necessary in order to
|
||||
* obtain correct time stamping.
|
||||
*
|
||||
* In other respects, the PluginBufferingAdapter behaves identically
|
||||
* to the plugin that it wraps. The wrapped plugin will be deleted
|
||||
* when the wrapper is deleted.
|
||||
*/
|
||||
|
||||
namespace vamp::host
|
||||
{
|
||||
class PluginBufferingAdapter : public PluginWrapper
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Construct a PluginBufferingAdapter wrapping the given plugin.
|
||||
* The adapter takes ownership of the plugin, which will be
|
||||
* deleted when the adapter is deleted.
|
||||
*/
|
||||
PluginBufferingAdapter(Plugin *plugin);
|
||||
PluginBufferingAdapter(plugin* p);
|
||||
virtual ~PluginBufferingAdapter();
|
||||
|
||||
/**
|
||||
* Return the preferred step size for this adapter.
|
||||
*
|
||||
* Because of the way this adapter works, its preferred step size
|
||||
* will always be the same as its preferred block size. This may
|
||||
* or may not be the same as the preferred step size of the
|
||||
* underlying plugin, which may be obtained by calling
|
||||
* getPluginPreferredStepSize().
|
||||
*/
|
||||
size_t getPreferredStepSize() const;
|
||||
|
||||
/**
|
||||
* Return the preferred block size for this adapter.
|
||||
*
|
||||
* This may or may not be the same as the preferred block size of
|
||||
* the underlying plugin, which may be obtained by calling
|
||||
* getPluginPreferredBlockSize().
|
||||
*
|
||||
* Note that this adapter may be initialised with any block size,
|
||||
* not just its supposedly preferred one.
|
||||
*/
|
||||
size_t getPreferredBlockSize() const;
|
||||
|
||||
/**
|
||||
* Initialise the adapter (and therefore the plugin) for the given
|
||||
* number of channels. Initialise the adapter for the given step
|
||||
* and block size, which must be equal.
|
||||
*
|
||||
* The step and block size used for the underlying plugin will
|
||||
* depend on its preferences, or any values previously passed to
|
||||
* setPluginStepSize and setPluginBlockSize.
|
||||
*/
|
||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||
|
||||
/**
|
||||
* Return the preferred step size of the plugin wrapped by this
|
||||
* adapter.
|
||||
*
|
||||
* This is included mainly for informational purposes. This value
|
||||
* is not likely to be a valid step size for the adapter itself,
|
||||
* and it is not usually of any use in interpreting the results
|
||||
* (because the adapter re-writes OneSamplePerStep outputs to
|
||||
* FixedSampleRate so that the hop size no longer needs to be
|
||||
* known beforehand in order to interpret them).
|
||||
*/
|
||||
size_t getPluginPreferredStepSize() const;
|
||||
|
||||
/**
|
||||
* Return the preferred block size of the plugin wrapped by this
|
||||
* adapter.
|
||||
*
|
||||
* This is included mainly for informational purposes.
|
||||
*/
|
||||
size_t getPluginPreferredBlockSize() const;
|
||||
|
||||
/**
|
||||
* Set the step size that will be used for the underlying plugin
|
||||
* when initialise() is called. If this is not set, the plugin's
|
||||
* own preferred step size will be used. You will not usually
|
||||
* need to call this function. If you do call it, it must be
|
||||
* before the first call to initialise().
|
||||
*/
|
||||
void setPluginStepSize(size_t stepSize);
|
||||
|
||||
/**
|
||||
* Set the block size that will be used for the underlying plugin
|
||||
* when initialise() is called. If this is not set, the plugin's
|
||||
* own preferred block size will be used. You will not usually
|
||||
* need to call this function. If you do call it, it must be
|
||||
* before the first call to initialise().
|
||||
*/
|
||||
void setPluginBlockSize(size_t blockSize);
|
||||
|
||||
/**
|
||||
* Return the step and block sizes that were actually used when
|
||||
* initialising the underlying plugin.
|
||||
*
|
||||
* This is included mainly for informational purposes. You will
|
||||
* not usually need to call this function. If this is called
|
||||
* before initialise(), it will return 0 for both values. If it
|
||||
* is called after a failed call to initialise(), it will return
|
||||
* the values that were used in the failed call to the plugin's
|
||||
* initialise() function.
|
||||
*/
|
||||
void getActualStepAndBlockSizes(size_t &stepSize, size_t &blockSize);
|
||||
|
||||
void setParameter(std::string, float);
|
||||
@ -135,7 +25,7 @@ public:
|
||||
|
||||
void reset();
|
||||
|
||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
||||
FeatureSet process(const float *const *inputBuffers, real_time timestamp);
|
||||
|
||||
FeatureSet getRemainingFeatures();
|
||||
|
||||
@ -143,7 +33,4 @@ protected:
|
||||
class Impl;
|
||||
Impl *m_impl;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,22 +1,20 @@
|
||||
#include "vamp-hostsdk/PluginChannelAdapter.h"
|
||||
|
||||
namespace Vamp {
|
||||
|
||||
namespace HostExt {
|
||||
|
||||
namespace vamp::host
|
||||
{
|
||||
class PluginChannelAdapter::Impl
|
||||
{
|
||||
public:
|
||||
Impl(Plugin *plugin);
|
||||
Impl(plugin* p);
|
||||
~Impl();
|
||||
|
||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||
|
||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
||||
FeatureSet processInterleaved(const float *inputBuffers, RealTime timestamp);
|
||||
FeatureSet process(const float *const *inputBuffers, real_time timestamp);
|
||||
FeatureSet processInterleaved(const float *inputBuffers, real_time timestamp);
|
||||
|
||||
protected:
|
||||
Plugin *m_plugin;
|
||||
plugin *m_plugin;
|
||||
size_t m_blockSize;
|
||||
size_t m_inputChannels;
|
||||
size_t m_pluginChannels;
|
||||
@ -25,10 +23,9 @@ protected:
|
||||
const float **m_forwardPtrs;
|
||||
};
|
||||
|
||||
PluginChannelAdapter::PluginChannelAdapter(Plugin *plugin) :
|
||||
PluginWrapper(plugin)
|
||||
PluginChannelAdapter::PluginChannelAdapter(plugin* p) : PluginWrapper(p)
|
||||
{
|
||||
m_impl = new Impl(plugin);
|
||||
m_impl = new Impl(p);
|
||||
}
|
||||
|
||||
PluginChannelAdapter::~PluginChannelAdapter()
|
||||
@ -36,28 +33,23 @@ PluginChannelAdapter::~PluginChannelAdapter()
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginChannelAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
||||
bool PluginChannelAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
||||
{
|
||||
return m_impl->initialise(channels, stepSize, blockSize);
|
||||
}
|
||||
|
||||
PluginChannelAdapter::FeatureSet
|
||||
PluginChannelAdapter::process(const float *const *inputBuffers,
|
||||
RealTime timestamp)
|
||||
PluginChannelAdapter::FeatureSet PluginChannelAdapter::process(const float *const *inputBuffers, real_time timestamp)
|
||||
{
|
||||
return m_impl->process(inputBuffers, timestamp);
|
||||
}
|
||||
|
||||
PluginChannelAdapter::FeatureSet
|
||||
PluginChannelAdapter::processInterleaved(const float *inputBuffers,
|
||||
RealTime timestamp)
|
||||
PluginChannelAdapter::FeatureSet PluginChannelAdapter::processInterleaved(const float *inputBuffers, real_time timestamp)
|
||||
{
|
||||
return m_impl->processInterleaved(inputBuffers, timestamp);
|
||||
}
|
||||
|
||||
PluginChannelAdapter::Impl::Impl(Plugin *plugin) :
|
||||
m_plugin(plugin),
|
||||
PluginChannelAdapter::Impl::Impl(plugin* p) :
|
||||
m_plugin(p),
|
||||
m_blockSize(0),
|
||||
m_inputChannels(0),
|
||||
m_pluginChannels(0),
|
||||
@ -69,13 +61,16 @@ PluginChannelAdapter::Impl::Impl(Plugin *plugin) :
|
||||
|
||||
PluginChannelAdapter::Impl::~Impl()
|
||||
{
|
||||
// the adapter will delete the plugin
|
||||
|
||||
if (m_buffer) {
|
||||
if (m_inputChannels > m_pluginChannels) {
|
||||
if (m_buffer)
|
||||
{
|
||||
if (m_inputChannels > m_pluginChannels)
|
||||
{
|
||||
delete[] m_buffer[0];
|
||||
} else {
|
||||
for (size_t i = 0; i < m_pluginChannels - m_inputChannels; ++i) {
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < m_pluginChannels - m_inputChannels; ++i)
|
||||
{
|
||||
delete[] m_buffer[i];
|
||||
}
|
||||
}
|
||||
@ -83,22 +78,24 @@ PluginChannelAdapter::Impl::~Impl()
|
||||
m_buffer = 0;
|
||||
}
|
||||
|
||||
if (m_deinterleave) {
|
||||
for (size_t i = 0; i < m_inputChannels; ++i) {
|
||||
if (m_deinterleave)
|
||||
{
|
||||
for (size_t i = 0; i < m_inputChannels; ++i)
|
||||
{
|
||||
delete[] m_deinterleave[i];
|
||||
}
|
||||
delete[] m_deinterleave;
|
||||
m_deinterleave = 0;
|
||||
}
|
||||
|
||||
if (m_forwardPtrs) {
|
||||
if (m_forwardPtrs)
|
||||
{
|
||||
delete[] m_forwardPtrs;
|
||||
m_forwardPtrs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
PluginChannelAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
||||
bool PluginChannelAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
||||
{
|
||||
m_blockSize = blockSize;
|
||||
|
||||
@ -107,17 +104,20 @@ PluginChannelAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t
|
||||
|
||||
m_inputChannels = channels;
|
||||
|
||||
if (m_inputChannels < minch) {
|
||||
|
||||
if (m_inputChannels < minch)
|
||||
{
|
||||
m_forwardPtrs = new const float *[minch];
|
||||
|
||||
if (m_inputChannels > 1) {
|
||||
if (m_inputChannels > 1)
|
||||
{
|
||||
// We need a set of zero-valued buffers to add to the
|
||||
// forwarded pointers
|
||||
m_buffer = new float*[minch - channels];
|
||||
for (size_t i = 0; i < minch; ++i) {
|
||||
for (size_t i = 0; i < minch; ++i)
|
||||
{
|
||||
m_buffer[i] = new float[blockSize];
|
||||
for (size_t j = 0; j < blockSize; ++j) {
|
||||
for (size_t j = 0; j < blockSize; ++j)
|
||||
{
|
||||
m_buffer[i][j] = 0.f;
|
||||
}
|
||||
}
|
||||
@ -125,49 +125,41 @@ PluginChannelAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t
|
||||
|
||||
m_pluginChannels = minch;
|
||||
|
||||
// std::cerr << "PluginChannelAdapter::initialise: expanding " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl;
|
||||
|
||||
} else if (m_inputChannels > maxch) {
|
||||
|
||||
// We only need m_buffer if we are mixing down to a single
|
||||
// channel -- otherwise we can just forward the same float* as
|
||||
// passed in to process(), expecting the excess to be ignored
|
||||
|
||||
if (maxch == 1) {
|
||||
}
|
||||
else if (m_inputChannels > maxch)
|
||||
{
|
||||
if (maxch == 1)
|
||||
{
|
||||
m_buffer = new float *[1];
|
||||
m_buffer[0] = new float[blockSize];
|
||||
|
||||
// std::cerr << "PluginChannelAdapter::initialise: mixing " << m_inputChannels << " to mono for plugin" << std::endl;
|
||||
|
||||
} else {
|
||||
|
||||
// std::cerr << "PluginChannelAdapter::initialise: reducing " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl;
|
||||
}
|
||||
|
||||
m_pluginChannels = maxch;
|
||||
|
||||
} else {
|
||||
|
||||
// std::cerr << "PluginChannelAdapter::initialise: accepting given number of channels (" << m_inputChannels << ")" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pluginChannels = m_inputChannels;
|
||||
}
|
||||
|
||||
return m_plugin->initialise(m_pluginChannels, stepSize, blockSize);
|
||||
}
|
||||
|
||||
PluginChannelAdapter::FeatureSet
|
||||
PluginChannelAdapter::Impl::processInterleaved(const float *inputBuffers,
|
||||
RealTime timestamp)
|
||||
PluginChannelAdapter::FeatureSet PluginChannelAdapter::Impl::processInterleaved(const float *inputBuffers, real_time timestamp)
|
||||
{
|
||||
if (!m_deinterleave)
|
||||
{
|
||||
if (!m_deinterleave) {
|
||||
m_deinterleave = new float *[m_inputChannels];
|
||||
for (size_t i = 0; i < m_inputChannels; ++i) {
|
||||
for (size_t i = 0; i < m_inputChannels; ++i)
|
||||
{
|
||||
m_deinterleave[i] = new float[m_blockSize];
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < m_inputChannels; ++i) {
|
||||
for (size_t j = 0; j < m_blockSize; ++j) {
|
||||
for (size_t i = 0; i < m_inputChannels; ++i)
|
||||
{
|
||||
for (size_t j = 0; j < m_blockSize; ++j)
|
||||
{
|
||||
m_deinterleave[i][j] = inputBuffers[j * m_inputChannels + i];
|
||||
}
|
||||
}
|
||||
@ -175,54 +167,63 @@ PluginChannelAdapter::Impl::processInterleaved(const float *inputBuffers,
|
||||
return process(m_deinterleave, timestamp);
|
||||
}
|
||||
|
||||
PluginChannelAdapter::FeatureSet
|
||||
PluginChannelAdapter::Impl::process(const float *const *inputBuffers,
|
||||
RealTime timestamp)
|
||||
PluginChannelAdapter::FeatureSet PluginChannelAdapter::Impl::process(const float *const *inputBuffers, real_time timestamp)
|
||||
{
|
||||
if (m_inputChannels < m_pluginChannels)
|
||||
{
|
||||
if (m_inputChannels == 1)
|
||||
{
|
||||
for (size_t i = 0; i < m_pluginChannels; ++i)
|
||||
{
|
||||
// std::cerr << "PluginChannelAdapter::process: " << m_inputChannels << " -> " << m_pluginChannels << " channels" << std::endl;
|
||||
|
||||
if (m_inputChannels < m_pluginChannels) {
|
||||
|
||||
if (m_inputChannels == 1) {
|
||||
for (size_t i = 0; i < m_pluginChannels; ++i) {
|
||||
m_forwardPtrs[i] = inputBuffers[0];
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < m_inputChannels; ++i) {
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < m_inputChannels; ++i)
|
||||
{
|
||||
m_forwardPtrs[i] = inputBuffers[i];
|
||||
}
|
||||
for (size_t i = m_inputChannels; i < m_pluginChannels; ++i) {
|
||||
for (size_t i = m_inputChannels; i < m_pluginChannels; ++i)
|
||||
{
|
||||
m_forwardPtrs[i] = m_buffer[i - m_inputChannels];
|
||||
}
|
||||
}
|
||||
|
||||
return m_plugin->process(m_forwardPtrs, timestamp);
|
||||
|
||||
} else if (m_inputChannels > m_pluginChannels) {
|
||||
|
||||
if (m_pluginChannels == 1) {
|
||||
for (size_t j = 0; j < m_blockSize; ++j) {
|
||||
}
|
||||
else if (m_inputChannels > m_pluginChannels)
|
||||
{
|
||||
if (m_pluginChannels == 1)
|
||||
{
|
||||
for (size_t j = 0; j < m_blockSize; ++j)
|
||||
{
|
||||
m_buffer[0][j] = inputBuffers[0][j];
|
||||
}
|
||||
for (size_t i = 1; i < m_inputChannels; ++i) {
|
||||
for (size_t j = 0; j < m_blockSize; ++j) {
|
||||
|
||||
for (size_t i = 1; i < m_inputChannels; ++i)
|
||||
{
|
||||
for (size_t j = 0; j < m_blockSize; ++j)
|
||||
{
|
||||
m_buffer[0][j] += inputBuffers[i][j];
|
||||
}
|
||||
}
|
||||
for (size_t j = 0; j < m_blockSize; ++j) {
|
||||
|
||||
for (size_t j = 0; j < m_blockSize; ++j)
|
||||
{
|
||||
m_buffer[0][j] /= float(m_inputChannels);
|
||||
}
|
||||
|
||||
return m_plugin->process(m_buffer, timestamp);
|
||||
} else {
|
||||
return m_plugin->process(inputBuffers, timestamp);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
else
|
||||
{
|
||||
return m_plugin->process(inputBuffers, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
return m_plugin->process(inputBuffers, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,104 +2,21 @@
|
||||
|
||||
#include "vamp-hostsdk/PluginWrapper.h"
|
||||
|
||||
namespace Vamp {
|
||||
|
||||
namespace HostExt {
|
||||
|
||||
/**
|
||||
* \class PluginChannelAdapter PluginChannelAdapter.h <vamp-hostsdk/PluginChannelAdapter.h>
|
||||
*
|
||||
* PluginChannelAdapter is a Vamp plugin adapter that implements a
|
||||
* policy for management of plugins that expect a different number of
|
||||
* input channels from the number actually available in the source
|
||||
* audio data.
|
||||
*
|
||||
* A host using PluginChannelAdapter may ignore the getMinChannelCount
|
||||
* and getMaxChannelCount reported by the plugin, and still expect the
|
||||
* plugin to run.
|
||||
*
|
||||
* PluginChannelAdapter implements the following policy:
|
||||
*
|
||||
* - If the plugin supports the provided number of channels directly,
|
||||
* PluginChannelAdapter will just run the plugin as normal.
|
||||
*
|
||||
* - If the plugin only supports exactly one channel but more than
|
||||
* one channel is provided, PluginChannelAdapter will use the mean of
|
||||
* the channels. This ensures that the resulting values remain
|
||||
* within the same magnitude range as expected for mono data.
|
||||
*
|
||||
* - If the plugin requires more than one channel but exactly one is
|
||||
* provided, the provided channel will be duplicated across all the
|
||||
* plugin input channels.
|
||||
*
|
||||
* If none of the above apply:
|
||||
*
|
||||
* - If the plugin requires more channels than are provided, the
|
||||
* minimum acceptable number of channels will be produced by adding
|
||||
* empty (zero valued) channels to those provided.
|
||||
*
|
||||
* - If the plugin requires fewer channels than are provided, the
|
||||
* maximum acceptable number of channels will be produced by
|
||||
* discarding the excess channels.
|
||||
*
|
||||
* Hosts requiring a different channel policy from the above will need
|
||||
* to implement it themselves, instead of using PluginChannelAdapter.
|
||||
*
|
||||
* Note that PluginChannelAdapter does not override the minimum and
|
||||
* maximum channel counts returned by the wrapped plugin. The host
|
||||
* will need to be aware that it is using a PluginChannelAdapter, and
|
||||
* be prepared to ignore these counts as necessary. (This contrasts
|
||||
* with the approach used in PluginInputDomainAdapter, which aims to
|
||||
* make the host completely unaware of which underlying input domain
|
||||
* is in fact in use.)
|
||||
*
|
||||
* (The rationale for this is that a host may wish to use the
|
||||
* PluginChannelAdapter but still discriminate in some way on the
|
||||
* basis of the number of channels actually supported. For example, a
|
||||
* simple stereo audio host may prefer to reject plugins that require
|
||||
* more than two channels on the grounds that doesn't actually
|
||||
* understand what they are for, rather than allow the channel adapter
|
||||
* to make a potentially meaningless channel conversion for them.)
|
||||
*
|
||||
* In every respect other than its management of channels, the
|
||||
* PluginChannelAdapter behaves identically to the plugin that it
|
||||
* wraps. The wrapped plugin will be deleted when the wrapper is
|
||||
* deleted.
|
||||
*
|
||||
* \note This class was introduced in version 1.1 of the Vamp plugin SDK.
|
||||
*/
|
||||
|
||||
namespace vamp::host
|
||||
{
|
||||
class PluginChannelAdapter : public PluginWrapper
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Construct a PluginChannelAdapter wrapping the given plugin.
|
||||
* The adapter takes ownership of the plugin, which will be
|
||||
* deleted when the adapter is deleted.
|
||||
*/
|
||||
PluginChannelAdapter(Plugin *plugin);
|
||||
PluginChannelAdapter(plugin* p);
|
||||
virtual ~PluginChannelAdapter();
|
||||
|
||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||
|
||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
||||
|
||||
/**
|
||||
* Call process(), providing interleaved audio data with the
|
||||
* number of channels passed to initialise(). The adapter will
|
||||
* de-interleave into temporary buffers as appropriate before
|
||||
* calling process().
|
||||
*
|
||||
* \note This function was introduced in version 1.4 of the Vamp
|
||||
* plugin SDK.
|
||||
*/
|
||||
FeatureSet processInterleaved(const float *inputBuffer, RealTime timestamp);
|
||||
FeatureSet process(const float *const *inputBuffers, real_time timestamp);
|
||||
FeatureSet processInterleaved(const float *inputBuffer, real_time timestamp);
|
||||
|
||||
protected:
|
||||
class Impl;
|
||||
Impl* m_impl;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,29 +3,19 @@
|
||||
|
||||
#include "vamp-hostsdk/Files.h"
|
||||
|
||||
namespace Vamp
|
||||
namespace vamp
|
||||
{
|
||||
|
||||
PluginHostAdapter::PluginHostAdapter(const VampPluginDescriptor *descriptor,
|
||||
float inputSampleRate) :
|
||||
Plugin(inputSampleRate),
|
||||
m_descriptor(descriptor)
|
||||
PluginHostAdapter::PluginHostAdapter(const VampPluginDescriptor *descriptor, float inputSampleRate) : plugin(inputSampleRate), m_descriptor(descriptor)
|
||||
{
|
||||
// std::cerr << "PluginHostAdapter::PluginHostAdapter (plugin = " << descriptor->name << ")" << std::endl;
|
||||
m_handle = m_descriptor->instantiate(m_descriptor, inputSampleRate);
|
||||
if (!m_handle) {
|
||||
// std::cerr << "WARNING: PluginHostAdapter: Plugin instantiation failed for plugin " << m_descriptor->name << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
PluginHostAdapter::~PluginHostAdapter()
|
||||
{
|
||||
// std::cerr << "PluginHostAdapter::~PluginHostAdapter (plugin = " << m_descriptor->name << ")" << std::endl;
|
||||
if (m_handle) m_descriptor->cleanup(m_handle);
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
PluginHostAdapter::getPluginPath()
|
||||
std::vector<std::string> PluginHostAdapter::getPluginPath()
|
||||
{
|
||||
std::vector<std::string> path;
|
||||
std::string envPath;
|
||||
@ -36,44 +26,26 @@ PluginHostAdapter::getPluginPath()
|
||||
(void)Files::getEnvUtf8("VAMP_PATH", envPath);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PATH_SEPARATOR ';'
|
||||
#define DEFAULT_VAMP_PATH "%ProgramFiles%\\Vamp Plugins"
|
||||
#else
|
||||
#define PATH_SEPARATOR ':'
|
||||
#ifdef __APPLE__
|
||||
#define DEFAULT_VAMP_PATH "$HOME/Library/Audio/Plug-Ins/Vamp:/Library/Audio/Plug-Ins/Vamp"
|
||||
#else
|
||||
#define DEFAULT_VAMP_PATH "$HOME/vamp:$HOME/.vamp:/usr/local/lib/vamp:/usr/lib/vamp"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (envPath == "") {
|
||||
#define PATH_SEPARATOR ':'
|
||||
if (envPath == "")
|
||||
{
|
||||
envPath = DEFAULT_VAMP_PATH;
|
||||
std::string home;
|
||||
if (Files::getEnvUtf8("HOME", home)) {
|
||||
if (Files::getEnvUtf8("HOME", home))
|
||||
{
|
||||
std::string::size_type f;
|
||||
while ((f = envPath.find("$HOME")) != std::string::npos &&
|
||||
f < envPath.length()) {
|
||||
while ((f = envPath.find("$HOME")) != std::string::npos && f < envPath.length())
|
||||
{
|
||||
envPath.replace(f, 5, home);
|
||||
}
|
||||
}
|
||||
#ifdef _WIN32
|
||||
std::string pfiles;
|
||||
if (!Files::getEnvUtf8("ProgramFiles", pfiles)) {
|
||||
pfiles = "C:\\Program Files";
|
||||
}
|
||||
std::string::size_type f;
|
||||
while ((f = envPath.find("%ProgramFiles%")) != std::string::npos &&
|
||||
f < envPath.length()) {
|
||||
envPath.replace(f, 14, pfiles);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string::size_type index = 0, newindex = 0;
|
||||
|
||||
while ((newindex = envPath.find(PATH_SEPARATOR, index)) < envPath.size()) {
|
||||
while ((newindex = envPath.find(PATH_SEPARATOR, index)) < envPath.size())
|
||||
{
|
||||
path.push_back(envPath.substr(index, newindex - index));
|
||||
index = newindex + 1;
|
||||
}
|
||||
@ -83,10 +55,7 @@ PluginHostAdapter::getPluginPath()
|
||||
return path;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginHostAdapter::initialise(size_t channels,
|
||||
size_t stepSize,
|
||||
size_t blockSize)
|
||||
bool PluginHostAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
||||
{
|
||||
if (!m_handle) return false;
|
||||
return m_descriptor->initialise
|
||||
@ -97,88 +66,61 @@ PluginHostAdapter::initialise(size_t channels,
|
||||
true : false;
|
||||
}
|
||||
|
||||
void
|
||||
PluginHostAdapter::reset()
|
||||
void PluginHostAdapter::reset()
|
||||
{
|
||||
if (!m_handle) {
|
||||
// std::cerr << "PluginHostAdapter::reset: no handle" << std::endl;
|
||||
return;
|
||||
}
|
||||
// std::cerr << "PluginHostAdapter::reset(" << m_handle << ")" << std::endl;
|
||||
m_descriptor->reset(m_handle);
|
||||
}
|
||||
|
||||
PluginHostAdapter::InputDomain
|
||||
PluginHostAdapter::getInputDomain() const
|
||||
PluginHostAdapter::InputDomain PluginHostAdapter::getInputDomain() const
|
||||
{
|
||||
if (m_descriptor->inputDomain == vampFrequencyDomain)
|
||||
{
|
||||
if (m_descriptor->inputDomain == vampFrequencyDomain) {
|
||||
return FrequencyDomain;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return TimeDomain;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
PluginHostAdapter::getVampApiVersion() const
|
||||
{
|
||||
return m_descriptor->vampApiVersion;
|
||||
}
|
||||
|
||||
std::string
|
||||
PluginHostAdapter::getIdentifier() const
|
||||
std::string PluginHostAdapter::get_identifier() const
|
||||
{
|
||||
return m_descriptor->identifier;
|
||||
}
|
||||
|
||||
std::string
|
||||
PluginHostAdapter::getName() const
|
||||
std::string PluginHostAdapter::get_name() const
|
||||
{
|
||||
return m_descriptor->name;
|
||||
}
|
||||
|
||||
std::string
|
||||
PluginHostAdapter::getDescription() const
|
||||
std::string PluginHostAdapter::get_description() const
|
||||
{
|
||||
return m_descriptor->description;
|
||||
}
|
||||
|
||||
std::string
|
||||
PluginHostAdapter::getMaker() const
|
||||
std::string PluginHostAdapter::get_maker() const
|
||||
{
|
||||
return m_descriptor->maker;
|
||||
}
|
||||
|
||||
int
|
||||
PluginHostAdapter::getPluginVersion() const
|
||||
PluginHostAdapter::parameter_descriptors PluginHostAdapter::get_parameter_descriptors() const
|
||||
{
|
||||
return m_descriptor->pluginVersion;
|
||||
}
|
||||
|
||||
std::string
|
||||
PluginHostAdapter::getCopyright() const
|
||||
{
|
||||
return m_descriptor->copyright;
|
||||
}
|
||||
|
||||
PluginHostAdapter::ParameterList
|
||||
PluginHostAdapter::getParameterDescriptors() const
|
||||
{
|
||||
ParameterList list;
|
||||
parameter_descriptors list;
|
||||
for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
|
||||
const VampParameterDescriptor *spd = m_descriptor->parameters[i];
|
||||
ParameterDescriptor pd;
|
||||
parameter_descriptor pd;
|
||||
pd.identifier = spd->identifier;
|
||||
pd.name = spd->name;
|
||||
pd.description = spd->description;
|
||||
pd.unit = spd->unit;
|
||||
pd.minValue = spd->minValue;
|
||||
pd.maxValue = spd->maxValue;
|
||||
pd.defaultValue = spd->defaultValue;
|
||||
pd.isQuantized = spd->isQuantized;
|
||||
pd.quantizeStep = spd->quantizeStep;
|
||||
if (pd.isQuantized && spd->valueNames) {
|
||||
pd.min_value = spd->minValue;
|
||||
pd.max_value = spd->maxValue;
|
||||
pd.default_value = spd->defaultValue;
|
||||
pd.is_quantized = spd->isQuantized;
|
||||
pd.quantize_step = spd->quantizeStep;
|
||||
if (pd.is_quantized && spd->valueNames) {
|
||||
for (unsigned int j = 0; spd->valueNames[j]; ++j) {
|
||||
pd.valueNames.push_back(spd->valueNames[j]);
|
||||
pd.value_names.push_back(spd->valueNames[j]);
|
||||
}
|
||||
}
|
||||
list.push_back(pd);
|
||||
@ -186,8 +128,7 @@ PluginHostAdapter::getParameterDescriptors() const
|
||||
return list;
|
||||
}
|
||||
|
||||
float
|
||||
PluginHostAdapter::getParameter(std::string param) const
|
||||
float PluginHostAdapter::get_parameter(std::string param) const
|
||||
{
|
||||
if (!m_handle) return 0.0;
|
||||
|
||||
@ -200,9 +141,7 @@ PluginHostAdapter::getParameter(std::string param) const
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
void
|
||||
PluginHostAdapter::setParameter(std::string param,
|
||||
float value)
|
||||
void PluginHostAdapter::set_parameter(std::string param, float value)
|
||||
{
|
||||
if (!m_handle) return;
|
||||
|
||||
@ -214,10 +153,9 @@ PluginHostAdapter::setParameter(std::string param,
|
||||
}
|
||||
}
|
||||
|
||||
PluginHostAdapter::ProgramList
|
||||
PluginHostAdapter::getPrograms() const
|
||||
PluginHostAdapter::programs PluginHostAdapter::get_programs() const
|
||||
{
|
||||
ProgramList list;
|
||||
programs list;
|
||||
|
||||
for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
|
||||
list.push_back(m_descriptor->programs[i]);
|
||||
@ -226,8 +164,7 @@ PluginHostAdapter::getPrograms() const
|
||||
return list;
|
||||
}
|
||||
|
||||
std::string
|
||||
PluginHostAdapter::getCurrentProgram() const
|
||||
std::string PluginHostAdapter::get_current_program() const
|
||||
{
|
||||
if (!m_handle) return "";
|
||||
|
||||
@ -239,8 +176,7 @@ PluginHostAdapter::getCurrentProgram() const
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginHostAdapter::selectProgram(std::string program)
|
||||
void PluginHostAdapter::select_program(std::string program)
|
||||
{
|
||||
if (!m_handle) return;
|
||||
|
||||
@ -252,22 +188,19 @@ PluginHostAdapter::selectProgram(std::string program)
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
PluginHostAdapter::getPreferredStepSize() const
|
||||
size_t PluginHostAdapter::getPreferredStepSize() const
|
||||
{
|
||||
if (!m_handle) return 0;
|
||||
return m_descriptor->getPreferredStepSize(m_handle);
|
||||
}
|
||||
|
||||
size_t
|
||||
PluginHostAdapter::getPreferredBlockSize() const
|
||||
size_t PluginHostAdapter::getPreferredBlockSize() const
|
||||
{
|
||||
if (!m_handle) return 0;
|
||||
return m_descriptor->getPreferredBlockSize(m_handle);
|
||||
}
|
||||
|
||||
size_t
|
||||
PluginHostAdapter::getMinChannelCount() const
|
||||
size_t PluginHostAdapter::getMinChannelCount() const
|
||||
{
|
||||
if (!m_handle) return 0;
|
||||
return m_descriptor->getMinChannelCount(m_handle);
|
||||
@ -338,7 +271,7 @@ PluginHostAdapter::getOutputDescriptors() const
|
||||
|
||||
PluginHostAdapter::FeatureSet
|
||||
PluginHostAdapter::process(const float *const *inputBuffers,
|
||||
RealTime timestamp)
|
||||
real_time timestamp)
|
||||
{
|
||||
FeatureSet fs;
|
||||
if (!m_handle) return fs;
|
||||
@ -388,14 +321,14 @@ PluginHostAdapter::convertFeatures(VampFeatureList *features,
|
||||
for (unsigned int j = 0; j < list.featureCount; ++j) {
|
||||
|
||||
feature.hasTimestamp = list.features[j].v1.hasTimestamp;
|
||||
feature.timestamp = RealTime(list.features[j].v1.sec,
|
||||
feature.timestamp = real_time(list.features[j].v1.sec,
|
||||
list.features[j].v1.nsec);
|
||||
feature.hasDuration = false;
|
||||
|
||||
if (m_descriptor->vampApiVersion >= 2) {
|
||||
unsigned int j2 = j + list.featureCount;
|
||||
feature.hasDuration = list.features[j2].v2.hasDuration;
|
||||
feature.duration = RealTime(list.features[j2].v2.durationSec,
|
||||
feature.duration = real_time(list.features[j2].v2.durationSec,
|
||||
list.features[j2].v2.durationNsec);
|
||||
}
|
||||
|
||||
@ -420,5 +353,4 @@ PluginHostAdapter::convertFeatures(VampFeatureList *features,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,66 +4,45 @@
|
||||
#include "vamp.h"
|
||||
#include <vector>
|
||||
|
||||
namespace Vamp {
|
||||
|
||||
/**
|
||||
* \class PluginHostAdapter PluginHostAdapter.h <vamp-hostsdk/PluginHostAdapter.h>
|
||||
*
|
||||
* PluginHostAdapter is a wrapper class that a Vamp host can use to
|
||||
* make the C-language VampPluginDescriptor object appear as a C++
|
||||
* Vamp::Plugin object.
|
||||
*
|
||||
* The Vamp API is defined in vamp/vamp.h as a C API. The C++ objects
|
||||
* used for convenience by plugins and hosts actually communicate
|
||||
* using the C low-level API, but the details of this communication
|
||||
* are handled seamlessly by the Vamp SDK implementation provided the
|
||||
* plugin and host use the proper C++ wrapper objects.
|
||||
*
|
||||
* See also PluginAdapter, the plugin-side wrapper that makes a C++
|
||||
* plugin object available using the C query API.
|
||||
*/
|
||||
|
||||
class PluginHostAdapter : public Plugin
|
||||
namespace vamp
|
||||
{
|
||||
class PluginHostAdapter : public plugin
|
||||
{
|
||||
public:
|
||||
PluginHostAdapter(const VampPluginDescriptor *descriptor,
|
||||
float inputSampleRate);
|
||||
PluginHostAdapter(const VampPluginDescriptor* descriptor, float inputSampleRate);
|
||||
virtual ~PluginHostAdapter();
|
||||
|
||||
static std::vector<std::string> getPluginPath();
|
||||
|
||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||
void reset();
|
||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize) override;
|
||||
void reset() override;
|
||||
|
||||
InputDomain getInputDomain() const;
|
||||
InputDomain getInputDomain() const override;
|
||||
|
||||
unsigned int getVampApiVersion() const;
|
||||
std::string getIdentifier() const;
|
||||
std::string getName() const;
|
||||
std::string getDescription() const;
|
||||
std::string getMaker() const;
|
||||
int getPluginVersion() const;
|
||||
std::string getCopyright() const;
|
||||
std::string get_identifier() const override;
|
||||
std::string get_name() const override;
|
||||
std::string get_description() const override;
|
||||
std::string get_maker() const override;
|
||||
|
||||
ParameterList getParameterDescriptors() const;
|
||||
float getParameter(std::string) const;
|
||||
void setParameter(std::string, float);
|
||||
parameter_descriptors get_parameter_descriptors() const override;
|
||||
float get_parameter(std::string) const override;
|
||||
void set_parameter(std::string, float) override;
|
||||
|
||||
ProgramList getPrograms() const;
|
||||
std::string getCurrentProgram() const;
|
||||
void selectProgram(std::string);
|
||||
programs get_programs() const override;
|
||||
std::string get_current_program() const override;
|
||||
void select_program(std::string) override;
|
||||
|
||||
size_t getPreferredStepSize() const;
|
||||
size_t getPreferredBlockSize() const;
|
||||
size_t getPreferredStepSize() const override;
|
||||
size_t getPreferredBlockSize() const override;
|
||||
|
||||
size_t getMinChannelCount() const;
|
||||
size_t getMaxChannelCount() const;
|
||||
size_t getMinChannelCount() const override;
|
||||
size_t getMaxChannelCount() const override;
|
||||
|
||||
OutputList getOutputDescriptors() const;
|
||||
OutputList getOutputDescriptors() const override;
|
||||
|
||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
||||
FeatureSet process(const float *const *inputBuffers, real_time timestamp) override;
|
||||
|
||||
FeatureSet getRemainingFeatures();
|
||||
FeatureSet getRemainingFeatures() override;
|
||||
|
||||
protected:
|
||||
void convertFeatures(VampFeatureList *, FeatureSet &);
|
||||
@ -71,5 +50,4 @@ protected:
|
||||
const VampPluginDescriptor *m_descriptor;
|
||||
VampPluginHandle m_handle;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,24 +1,20 @@
|
||||
#include "vamp-hostsdk/PluginInputDomainAdapter.h"
|
||||
#include "vamp-hostsdk/Window.h"
|
||||
#include "vamp-sdk/ext/vamp_kiss_fft.h"
|
||||
#include "vamp-sdk/ext/vamp_kiss_fftr.h"
|
||||
|
||||
#include <cmath>
|
||||
#include "Window.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
namespace Vamp {
|
||||
|
||||
namespace HostExt {
|
||||
|
||||
namespace vamp::host
|
||||
{
|
||||
class PluginInputDomainAdapter::Impl
|
||||
{
|
||||
public:
|
||||
Impl(Plugin *plugin, float inputSampleRate);
|
||||
Impl(plugin* p, float inputSampleRate);
|
||||
~Impl();
|
||||
|
||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||
@ -27,18 +23,18 @@ public:
|
||||
size_t getPreferredStepSize() const;
|
||||
size_t getPreferredBlockSize() const;
|
||||
|
||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
||||
FeatureSet process(const float *const *inputBuffers, real_time timestamp);
|
||||
|
||||
void setProcessTimestampMethod(ProcessTimestampMethod m);
|
||||
ProcessTimestampMethod getProcessTimestampMethod() const;
|
||||
|
||||
RealTime getTimestampAdjustment() const;
|
||||
real_time getTimestampAdjustment() const;
|
||||
|
||||
WindowType getWindowType() const;
|
||||
void setWindowType(WindowType type);
|
||||
|
||||
protected:
|
||||
Plugin *m_plugin;
|
||||
plugin* m_plugin;
|
||||
float m_inputSampleRate;
|
||||
int m_channels;
|
||||
int m_stepSize;
|
||||
@ -57,18 +53,18 @@ protected:
|
||||
vamp_kiss_fftr_cfg m_cfg;
|
||||
vamp_kiss_fft_cpx *m_cbuf;
|
||||
|
||||
FeatureSet processShiftingTimestamp(const float *const *inputBuffers, RealTime timestamp);
|
||||
FeatureSet processShiftingData(const float *const *inputBuffers, RealTime timestamp);
|
||||
FeatureSet processShiftingTimestamp(const float *const *inputBuffers, real_time timestamp);
|
||||
FeatureSet processShiftingData(const float *const *inputBuffers, real_time timestamp);
|
||||
|
||||
size_t makeBlockSizeAcceptable(size_t) const;
|
||||
|
||||
W::WindowType convertType(WindowType t) const;
|
||||
};
|
||||
|
||||
PluginInputDomainAdapter::PluginInputDomainAdapter(Plugin *plugin) :
|
||||
PluginWrapper(plugin)
|
||||
PluginInputDomainAdapter::PluginInputDomainAdapter(plugin* p) :
|
||||
PluginWrapper(p)
|
||||
{
|
||||
m_impl = new Impl(plugin, m_inputSampleRate);
|
||||
m_impl = new Impl(p, m_inputSampleRate);
|
||||
}
|
||||
|
||||
PluginInputDomainAdapter::~PluginInputDomainAdapter()
|
||||
@ -88,8 +84,7 @@ PluginInputDomainAdapter::reset()
|
||||
m_impl->reset();
|
||||
}
|
||||
|
||||
Plugin::InputDomain
|
||||
PluginInputDomainAdapter::getInputDomain() const
|
||||
plugin::InputDomain PluginInputDomainAdapter::getInputDomain() const
|
||||
{
|
||||
return TimeDomain;
|
||||
}
|
||||
@ -106,8 +101,8 @@ PluginInputDomainAdapter::getPreferredBlockSize() const
|
||||
return m_impl->getPreferredBlockSize();
|
||||
}
|
||||
|
||||
Plugin::FeatureSet
|
||||
PluginInputDomainAdapter::process(const float *const *inputBuffers, RealTime timestamp)
|
||||
plugin::FeatureSet
|
||||
PluginInputDomainAdapter::process(const float *const *inputBuffers, real_time timestamp)
|
||||
{
|
||||
return m_impl->process(inputBuffers, timestamp);
|
||||
}
|
||||
@ -124,7 +119,7 @@ PluginInputDomainAdapter::getProcessTimestampMethod() const
|
||||
return m_impl->getProcessTimestampMethod();
|
||||
}
|
||||
|
||||
RealTime
|
||||
real_time
|
||||
PluginInputDomainAdapter::getTimestampAdjustment() const
|
||||
{
|
||||
return m_impl->getTimestampAdjustment();
|
||||
@ -143,8 +138,8 @@ PluginInputDomainAdapter::setWindowType(WindowType w)
|
||||
}
|
||||
|
||||
|
||||
PluginInputDomainAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
|
||||
m_plugin(plugin),
|
||||
PluginInputDomainAdapter::Impl::Impl(plugin* p, float inputSampleRate) :
|
||||
m_plugin(p),
|
||||
m_inputSampleRate(inputSampleRate),
|
||||
m_channels(0),
|
||||
m_stepSize(0),
|
||||
@ -304,16 +299,14 @@ PluginInputDomainAdapter::Impl::makeBlockSizeAcceptable(size_t blockSize) const
|
||||
return blockSize;
|
||||
}
|
||||
|
||||
RealTime
|
||||
PluginInputDomainAdapter::Impl::getTimestampAdjustment() const
|
||||
real_time PluginInputDomainAdapter::Impl::getTimestampAdjustment() const
|
||||
{
|
||||
if (m_plugin->getInputDomain() == TimeDomain) {
|
||||
return RealTime::zeroTime;
|
||||
return real_time::zero_time;
|
||||
} else if (m_method == ShiftData || m_method == NoShift) {
|
||||
return RealTime::zeroTime;
|
||||
return real_time::zero_time;
|
||||
} else {
|
||||
return RealTime::frame2RealTime
|
||||
(m_blockSize/2, int(m_inputSampleRate + 0.5));
|
||||
return real_time::f2rt(m_blockSize/2, int(m_inputSampleRate + 0.5));
|
||||
}
|
||||
}
|
||||
|
||||
@ -369,9 +362,9 @@ PluginInputDomainAdapter::Impl::convertType(WindowType t) const
|
||||
}
|
||||
}
|
||||
|
||||
Plugin::FeatureSet
|
||||
plugin::FeatureSet
|
||||
PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers,
|
||||
RealTime timestamp)
|
||||
real_time timestamp)
|
||||
{
|
||||
if (m_plugin->getInputDomain() == TimeDomain) {
|
||||
return m_plugin->process(inputBuffers, timestamp);
|
||||
@ -384,9 +377,9 @@ PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers,
|
||||
}
|
||||
}
|
||||
|
||||
Plugin::FeatureSet
|
||||
plugin::FeatureSet
|
||||
PluginInputDomainAdapter::Impl::processShiftingTimestamp(const float *const *inputBuffers,
|
||||
RealTime timestamp)
|
||||
real_time timestamp)
|
||||
{
|
||||
unsigned int roundedRate = 1;
|
||||
if (m_inputSampleRate > 0.f) {
|
||||
@ -397,9 +390,9 @@ PluginInputDomainAdapter::Impl::processShiftingTimestamp(const float *const *inp
|
||||
// we may need to add one nsec if timestamp +
|
||||
// getTimestampAdjustment() rounds down
|
||||
timestamp = timestamp + getTimestampAdjustment();
|
||||
RealTime nsec(0, 1);
|
||||
if (RealTime::realTime2Frame(timestamp, roundedRate) <
|
||||
RealTime::realTime2Frame(timestamp + nsec, roundedRate)) {
|
||||
real_time nsec(0, 1);
|
||||
if (real_time::rt2f(timestamp, roundedRate) <
|
||||
real_time::rt2f(timestamp + nsec, roundedRate)) {
|
||||
timestamp = timestamp + nsec;
|
||||
}
|
||||
}
|
||||
@ -426,9 +419,9 @@ PluginInputDomainAdapter::Impl::processShiftingTimestamp(const float *const *inp
|
||||
return m_plugin->process(m_freqbuf, timestamp);
|
||||
}
|
||||
|
||||
Plugin::FeatureSet
|
||||
plugin::FeatureSet
|
||||
PluginInputDomainAdapter::Impl::processShiftingData(const float *const *inputBuffers,
|
||||
RealTime timestamp)
|
||||
real_time timestamp)
|
||||
{
|
||||
if (m_processCount == 0) {
|
||||
if (!m_shiftBuffers) {
|
||||
@ -476,7 +469,4 @@ PluginInputDomainAdapter::Impl::processShiftingData(const float *const *inputBuf
|
||||
|
||||
return m_plugin->process(m_freqbuf, timestamp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,57 +2,12 @@
|
||||
|
||||
#include "vamp-hostsdk/PluginWrapper.h"
|
||||
|
||||
namespace Vamp {
|
||||
|
||||
namespace HostExt {
|
||||
|
||||
/**
|
||||
* \class PluginInputDomainAdapter PluginInputDomainAdapter.h <vamp-hostsdk/PluginInputDomainAdapter.h>
|
||||
*
|
||||
* PluginInputDomainAdapter is a Vamp plugin adapter that converts
|
||||
* time-domain input into frequency-domain input for plugins that need
|
||||
* it. This permits a host to use time- and frequency-domain plugins
|
||||
* interchangeably without needing to handle the conversion itself.
|
||||
*
|
||||
* This adapter uses a basic windowed FFT (using Hann window by
|
||||
* default) that supports power-of-two block sizes only. If a
|
||||
* frequency domain plugin requests a non-power-of-two blocksize, the
|
||||
* adapter will adjust it to a nearby power of two instead. Thus,
|
||||
* getPreferredBlockSize() will always return a power of two if the
|
||||
* wrapped plugin is a frequency domain one. If the plugin doesn't
|
||||
* accept the adjusted power of two block size, initialise() will
|
||||
* fail.
|
||||
*
|
||||
* The adapter provides no way for the host to discover whether the
|
||||
* underlying plugin is actually a time or frequency domain plugin
|
||||
* (except that if the preferred block size is not a power of two, it
|
||||
* must be a time domain plugin).
|
||||
*
|
||||
* The FFT implementation is simple and self-contained, but unlikely
|
||||
* to be the fastest available: a host can usually do better if it
|
||||
* cares enough.
|
||||
*
|
||||
* The window shape for the FFT frame can be set using setWindowType
|
||||
* and the current shape retrieved using getWindowType. (This was
|
||||
* added in v2.3 of the SDK.)
|
||||
*
|
||||
* In every respect other than its input domain handling, the
|
||||
* PluginInputDomainAdapter behaves identically to the plugin that it
|
||||
* wraps. The wrapped plugin will be deleted when the wrapper is
|
||||
* deleted.
|
||||
*
|
||||
* \note This class was introduced in version 1.1 of the Vamp plugin SDK.
|
||||
*/
|
||||
|
||||
namespace vamp::host
|
||||
{
|
||||
class PluginInputDomainAdapter : public PluginWrapper
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Construct a PluginInputDomainAdapter wrapping the given plugin.
|
||||
* The adapter takes ownership of the plugin, which will be
|
||||
* deleted when the adapter is deleted.
|
||||
*/
|
||||
PluginInputDomainAdapter(Plugin *plugin);
|
||||
PluginInputDomainAdapter(plugin* p);
|
||||
virtual ~PluginInputDomainAdapter();
|
||||
|
||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||
@ -63,95 +18,18 @@ public:
|
||||
size_t getPreferredStepSize() const;
|
||||
size_t getPreferredBlockSize() const;
|
||||
|
||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
||||
FeatureSet process(const float *const *inputBuffers, real_time timestamp);
|
||||
|
||||
/**
|
||||
* ProcessTimestampMethod determines how the
|
||||
* PluginInputDomainAdapter handles timestamps for the data passed
|
||||
* to the process() function of the plugin it wraps, in the case
|
||||
* where the plugin is expecting frequency-domain data.
|
||||
*
|
||||
* The Vamp specification requires that the timestamp passed to
|
||||
* the plugin for frequency-domain input should be that of the
|
||||
* centre of the processing block, rather than the start as is the
|
||||
* case for time-domain input.
|
||||
*
|
||||
* Since PluginInputDomainAdapter aims to be transparent in use,
|
||||
* it needs to handle this timestamp adjustment itself. However,
|
||||
* some control is available over the method used for adjustment,
|
||||
* by means of the ProcessTimestampMethod setting.
|
||||
*
|
||||
* If ProcessTimestampMethod is set to ShiftTimestamp (the
|
||||
* default), then the data passed to the wrapped plugin will be
|
||||
* calculated from the same input data block as passed to the
|
||||
* wrapper, but the timestamp passed to the plugin will be
|
||||
* advanced by half of the window size.
|
||||
*
|
||||
* If ProcessTimestampMethod is set to ShiftData, then the
|
||||
* timestamp passed to the wrapped plugin will be the same as that
|
||||
* passed to the process call of the wrapper, but the data block
|
||||
* used to calculate the input will be shifted back (earlier) by
|
||||
* half of the window size, with half a block of zero padding at
|
||||
* the start of the first process call. This has the advantage of
|
||||
* preserving the first half block of audio without any
|
||||
* deterioration from window shaping.
|
||||
*
|
||||
* If ProcessTimestampMethod is set to NoShift, then no adjustment
|
||||
* will be made and the timestamps will be incorrect.
|
||||
*/
|
||||
enum ProcessTimestampMethod {
|
||||
ShiftTimestamp,
|
||||
ShiftData,
|
||||
NoShift
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the method used for timestamp adjustment in plugins taking
|
||||
* frequency-domain input. See the ProcessTimestampMethod
|
||||
* documentation for details.
|
||||
*
|
||||
* This function must be called before the first call to
|
||||
* process().
|
||||
*/
|
||||
void setProcessTimestampMethod(ProcessTimestampMethod);
|
||||
|
||||
/**
|
||||
* Retrieve the method used for timestamp adjustment in plugins
|
||||
* taking frequency-domain input. See the ProcessTimestampMethod
|
||||
* documentation for details.
|
||||
*/
|
||||
ProcessTimestampMethod getProcessTimestampMethod() const;
|
||||
real_time getTimestampAdjustment() const;
|
||||
|
||||
/**
|
||||
* Return the amount by which the timestamps supplied to process()
|
||||
* are being incremented when they are passed to the plugin's own
|
||||
* process() implementation.
|
||||
*
|
||||
* The Vamp API mandates that the timestamp passed to the plugin
|
||||
* for time-domain input should be the time of the first sample in
|
||||
* the block, but the timestamp passed for frequency-domain input
|
||||
* should be the timestamp of the centre of the block.
|
||||
*
|
||||
* The PluginInputDomainAdapter adjusts its timestamps properly so
|
||||
* that the plugin receives correct times, but in some
|
||||
* circumstances (such as for establishing the correct timing of
|
||||
* implicitly-timed features, i.e. features without their own
|
||||
* timestamps) the host may need to be aware that this adjustment
|
||||
* is taking place.
|
||||
*
|
||||
* If the plugin requires time-domain input or the
|
||||
* PluginInputDomainAdapter is configured with its
|
||||
* ProcessTimestampMethod set to ShiftData instead of
|
||||
* ShiftTimestamp, then this function will return zero.
|
||||
*
|
||||
* The result of calling this function before initialise() has
|
||||
* been called is undefined.
|
||||
*/
|
||||
RealTime getTimestampAdjustment() const;
|
||||
|
||||
/**
|
||||
* The set of supported window shapes.
|
||||
*/
|
||||
enum WindowType {
|
||||
|
||||
RectangularWindow = 0,
|
||||
@ -171,21 +49,11 @@ public:
|
||||
BlackmanHarrisWindow = 8
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the current window shape. The default is HanningWindow.
|
||||
*/
|
||||
WindowType getWindowType() const;
|
||||
|
||||
/**
|
||||
* Set the current window shape.
|
||||
*/
|
||||
void setWindowType(WindowType type);
|
||||
|
||||
|
||||
protected:
|
||||
class Impl;
|
||||
Impl *m_impl;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,16 @@
|
||||
#include "vamp-hostsdk/PluginLoader.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "vamp-hostsdk/PluginInputDomainAdapter.h"
|
||||
#include "vamp-hostsdk/PluginChannelAdapter.h"
|
||||
#include "vamp-hostsdk/PluginBufferingAdapter.h"
|
||||
#include "vamp-hostsdk/PluginHostAdapter.h"
|
||||
|
||||
#include "vamp.h"
|
||||
|
||||
#include "vamp-hostsdk/Files.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace Vamp {
|
||||
|
||||
namespace HostExt {
|
||||
|
||||
namespace vamp::host
|
||||
{
|
||||
class PluginLoader::Impl
|
||||
{
|
||||
public:
|
||||
@ -24,9 +21,7 @@ public:
|
||||
PluginKeyList listPluginsIn(std::vector<std::string>);
|
||||
PluginKeyList listPluginsNotIn(std::vector<std::string>);
|
||||
|
||||
Plugin *loadPlugin(PluginKey key,
|
||||
float inputSampleRate,
|
||||
int adapterFlags);
|
||||
plugin *loadPlugin(PluginKey key, float inputSampleRate, int adapterFlags);
|
||||
|
||||
PluginKey composePluginKey(std::string libraryName, std::string identifier);
|
||||
|
||||
@ -37,15 +32,17 @@ public:
|
||||
static void setInstanceToClean(PluginLoader *instance);
|
||||
|
||||
protected:
|
||||
class PluginDeletionNotifyAdapter : public PluginWrapper {
|
||||
class PluginDeletionNotifyAdapter : public PluginWrapper
|
||||
{
|
||||
public:
|
||||
PluginDeletionNotifyAdapter(Plugin *plugin, Impl *loader);
|
||||
PluginDeletionNotifyAdapter(plugin* p, Impl *loader);
|
||||
virtual ~PluginDeletionNotifyAdapter();
|
||||
protected:
|
||||
Impl *m_loader;
|
||||
};
|
||||
|
||||
class InstanceCleaner {
|
||||
class InstanceCleaner
|
||||
{
|
||||
public:
|
||||
InstanceCleaner() : m_instance(0) { }
|
||||
~InstanceCleaner() { delete m_instance; }
|
||||
@ -59,7 +56,8 @@ protected:
|
||||
std::map<PluginKey, std::string> m_pluginLibraryNameMap;
|
||||
bool m_allPluginsEnumerated;
|
||||
|
||||
struct Enumeration {
|
||||
struct Enumeration
|
||||
{
|
||||
enum { All, SinglePlugin, InLibraries, NotInLibraries } type;
|
||||
PluginKey key;
|
||||
std::vector<std::string> libraryNames;
|
||||
@ -74,10 +72,9 @@ protected:
|
||||
std::map<PluginKey, PluginCategoryHierarchy> m_taxonomy;
|
||||
void generateTaxonomy();
|
||||
|
||||
std::map<Plugin *, void *> m_pluginLibraryHandleMap;
|
||||
std::map<plugin*, void *> m_pluginLibraryHandleMap;
|
||||
|
||||
bool decomposePluginKey(PluginKey key,
|
||||
std::string &libraryName, std::string &identifier);
|
||||
bool decomposePluginKey(PluginKey key, std::string &libraryName, std::string &identifier);
|
||||
|
||||
static InstanceCleaner m_cleaner;
|
||||
};
|
||||
@ -102,9 +99,9 @@ PluginLoader *
|
||||
PluginLoader::getInstance()
|
||||
{
|
||||
if (!m_instance) {
|
||||
// The cleaner doesn't own the instance, because we leave the
|
||||
// instance pointer in the base class for binary backwards
|
||||
// compatibility reasons and to avoid waste
|
||||
// Очиститель не является владельцем экземпляра, потому что мы оставляем указатель
|
||||
// instance в базовом классе для обратной передачи двоичных данных
|
||||
// из соображений совместимости и во избежание ненужных затрат
|
||||
m_instance = new PluginLoader();
|
||||
Impl::setInstanceToClean(m_instance);
|
||||
}
|
||||
@ -129,10 +126,7 @@ PluginLoader::listPluginsNotIn(std::vector<std::string> libs)
|
||||
return m_impl->listPluginsNotIn(libs);
|
||||
}
|
||||
|
||||
Plugin *
|
||||
PluginLoader::loadPlugin(PluginKey key,
|
||||
float inputSampleRate,
|
||||
int adapterFlags)
|
||||
plugin* PluginLoader::loadPlugin(PluginKey key, float inputSampleRate, int adapterFlags)
|
||||
{
|
||||
return m_impl->loadPlugin(key, inputSampleRate, adapterFlags);
|
||||
}
|
||||
@ -363,9 +357,7 @@ PluginLoader::Impl::getLibraryPathForPlugin(PluginKey plugin)
|
||||
return m_pluginLibraryNameMap[plugin];
|
||||
}
|
||||
|
||||
Plugin *
|
||||
PluginLoader::Impl::loadPlugin(PluginKey key,
|
||||
float inputSampleRate, int adapterFlags)
|
||||
plugin* PluginLoader::Impl::loadPlugin(PluginKey key, float inputSampleRate, int adapterFlags)
|
||||
{
|
||||
std::string libname, identifier;
|
||||
if (!decomposePluginKey(key, libname, identifier)) {
|
||||
@ -383,13 +375,11 @@ PluginLoader::Impl::loadPlugin(PluginKey key,
|
||||
void* handle = Files::loadLibrary(fullPath);
|
||||
if (!handle) return 0;
|
||||
|
||||
VampGetPluginDescriptorFunction fn =
|
||||
(VampGetPluginDescriptorFunction)Files::lookupInLibrary
|
||||
(handle, "vampGetPluginDescriptor");
|
||||
VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction)Files::lookupInLibrary(handle, "vampGetPluginDescriptor");
|
||||
|
||||
if (!fn) {
|
||||
std::cerr << "Vamp::HostExt::PluginLoader: No vampGetPluginDescriptor function found in library \""
|
||||
<< fullPath << "\"" << std::endl;
|
||||
if (!fn)
|
||||
{
|
||||
std::cerr << "Vamp::HostExt::PluginLoader: No vampGetPluginDescriptor function found in library \"" << fullPath << "\"" << std::endl;
|
||||
Files::unloadLibrary(handle);
|
||||
return 0;
|
||||
}
|
||||
@ -397,19 +387,18 @@ PluginLoader::Impl::loadPlugin(PluginKey key,
|
||||
int index = 0;
|
||||
const VampPluginDescriptor* descriptor = 0;
|
||||
|
||||
while ((descriptor = fn(VAMP_API_VERSION, index))) {
|
||||
while ((descriptor = fn(VAMP_API_VERSION, index)))
|
||||
{
|
||||
if (std::string(descriptor->identifier) == identifier)
|
||||
{
|
||||
vamp::PluginHostAdapter* p = new vamp::PluginHostAdapter(descriptor, inputSampleRate);
|
||||
|
||||
if (std::string(descriptor->identifier) == identifier) {
|
||||
|
||||
Vamp::PluginHostAdapter *plugin =
|
||||
new Vamp::PluginHostAdapter(descriptor, inputSampleRate);
|
||||
|
||||
Plugin *adapter = new PluginDeletionNotifyAdapter(plugin, this);
|
||||
plugin* adapter = new PluginDeletionNotifyAdapter(p, this);
|
||||
|
||||
m_pluginLibraryHandleMap[adapter] = handle;
|
||||
|
||||
if (adapterFlags & ADAPT_INPUT_DOMAIN) {
|
||||
if (adapter->getInputDomain() == Plugin::FrequencyDomain) {
|
||||
if (adapter->getInputDomain() == plugin::FrequencyDomain) {
|
||||
adapter = new PluginInputDomainAdapter(adapter);
|
||||
}
|
||||
}
|
||||
@ -541,9 +530,8 @@ PluginLoader::Impl::pluginDeleted(PluginDeletionNotifyAdapter *adapter)
|
||||
Files::unloadLibrary(handle);
|
||||
}
|
||||
|
||||
PluginLoader::Impl::PluginDeletionNotifyAdapter::PluginDeletionNotifyAdapter(Plugin *plugin,
|
||||
Impl *loader) :
|
||||
PluginWrapper(plugin),
|
||||
PluginLoader::Impl::PluginDeletionNotifyAdapter::PluginDeletionNotifyAdapter(plugin* p, Impl *loader) :
|
||||
PluginWrapper(p),
|
||||
m_loader(loader)
|
||||
{
|
||||
}
|
||||
@ -561,7 +549,4 @@ PluginLoader::Impl::PluginDeletionNotifyAdapter::~PluginDeletionNotifyAdapter()
|
||||
|
||||
if (m_loader) m_loader->pluginDeleted(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,162 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "vamp-sdk/Plugin.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "vamp-hostsdk/PluginWrapper.h"
|
||||
|
||||
namespace Vamp {
|
||||
|
||||
class Plugin;
|
||||
|
||||
namespace HostExt {
|
||||
|
||||
/**
|
||||
* \class PluginLoader PluginLoader.h <vamp-hostsdk/PluginLoader.h>
|
||||
*
|
||||
* Vamp::HostExt::PluginLoader is a convenience class for discovering
|
||||
* and loading Vamp plugins using the typical plugin-path, library
|
||||
* naming, and categorisation conventions described in the Vamp SDK
|
||||
* documentation. This class is intended to greatly simplify the task
|
||||
* of becoming a Vamp plugin host for any C++ application.
|
||||
*
|
||||
* Hosts are not required by the Vamp specification to use the same
|
||||
* plugin search path and naming conventions as implemented by this
|
||||
* class, and are certainly not required to use this actual class.
|
||||
* But we do strongly recommend it.
|
||||
*
|
||||
* This class is not thread-safe; use it from a single application
|
||||
* thread, or guard access to it with a mutex.
|
||||
*
|
||||
* \note This class was introduced in version 1.1 of the Vamp plugin SDK.
|
||||
*/
|
||||
namespace vamp::host
|
||||
{
|
||||
|
||||
class PluginLoader
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Obtain a pointer to the singleton instance of PluginLoader.
|
||||
* Use this to obtain your loader object.
|
||||
*/
|
||||
static PluginLoader *getInstance();
|
||||
|
||||
/**
|
||||
* PluginKey is a string type that is used to identify a plugin
|
||||
* uniquely within the scope of "the current system". It consists
|
||||
* of the lower-cased base name of the plugin library, a colon
|
||||
* separator, and the identifier string for the plugin. It is
|
||||
* only meaningful in the context of a given plugin path (the one
|
||||
* returned by PluginHostAdapter::getPluginPath()).
|
||||
*
|
||||
* Use composePluginKey() to construct a plugin key from a known
|
||||
* plugin library name and identifier.
|
||||
*
|
||||
* Note: the fact that the library component of the key is
|
||||
* lower-cased implies that library names are matched
|
||||
* case-insensitively by the PluginLoader class, regardless of the
|
||||
* case sensitivity of the underlying filesystem. (Plugin
|
||||
* identifiers _are_ case sensitive, however.) Also, it is not
|
||||
* possible to portably extract a working library name from a
|
||||
* plugin key, as the result may fail on case-sensitive
|
||||
* filesystems. Use getLibraryPathForPlugin() instead.
|
||||
*/
|
||||
typedef std::string PluginKey;
|
||||
|
||||
/**
|
||||
* PluginKeyList is a sequence of plugin keys, such as returned by
|
||||
* listPlugins().
|
||||
*/
|
||||
typedef std::vector<PluginKey> PluginKeyList;
|
||||
|
||||
/**
|
||||
* PluginCategoryHierarchy is a sequence of general->specific
|
||||
* category names, as may be associated with a single plugin.
|
||||
* This sequence describes the location of a plugin within a
|
||||
* category forest, containing the human-readable names of the
|
||||
* plugin's category tree root, followed by each of the nodes down
|
||||
* to the leaf containing the plugin.
|
||||
*
|
||||
* \see getPluginCategory()
|
||||
*/
|
||||
typedef std::vector<std::string> PluginCategoryHierarchy;
|
||||
|
||||
/**
|
||||
* Search for all available Vamp plugins, and return a list of
|
||||
* them in the order in which they were found.
|
||||
*/
|
||||
PluginKeyList listPlugins();
|
||||
|
||||
/**
|
||||
* Search for available Vamp plugins in libraries with the given
|
||||
* library names, and return a list of them in the order in which
|
||||
* they were found. Do not attempt to load any plugin libraries
|
||||
* other than those named.
|
||||
*
|
||||
* The library names should be supplied without path or
|
||||
* suffix. For example, use "vamp-example-plugins" to find plugins
|
||||
* in /install/path/of/vamp-example-plugins.dll (or .so etc). This
|
||||
* is the same concept of "library name" as appears in the plugin
|
||||
* key: \see composePluginKey().
|
||||
*/
|
||||
PluginKeyList listPluginsIn(std::vector<std::string> libraryNames);
|
||||
|
||||
/**
|
||||
* Search for available Vamp plugins in libraries other than those
|
||||
* with the given library names, and return a list of them in the
|
||||
* order in which they were found. Do not attempt to load any of
|
||||
* the libraries named.
|
||||
*
|
||||
* The library names should be supplied without path or
|
||||
* suffix. For example, use "vamp-example-plugins" to find plugins
|
||||
* not appearing in /install/path/of/vamp-example-plugins.dll (or
|
||||
* .so etc). This is the same concept of "library name" as appears
|
||||
* in the plugin key: \see composePluginKey().
|
||||
*/
|
||||
PluginKeyList listPluginsNotIn(std::vector<std::string> libraryNames);
|
||||
|
||||
/**
|
||||
* AdapterFlags contains a set of values that may be OR'd together
|
||||
* to indicate in which circumstances PluginLoader should use a
|
||||
* plugin adapter to make a plugin easier to use for a host that
|
||||
* does not want to cater for complex features.
|
||||
*
|
||||
* The available flags are:
|
||||
*
|
||||
* ADAPT_INPUT_DOMAIN - If the plugin expects frequency domain
|
||||
* input, wrap it in a PluginInputDomainAdapter that automatically
|
||||
* converts the plugin to one that expects time-domain input.
|
||||
* This enables a host to accommodate time- and frequency-domain
|
||||
* plugins without needing to do any conversion itself.
|
||||
*
|
||||
* ADAPT_CHANNEL_COUNT - Wrap the plugin in a PluginChannelAdapter
|
||||
* to handle any mismatch between the number of channels of audio
|
||||
* the plugin can handle and the number available in the host.
|
||||
* This enables a host to use plugins that may require the input
|
||||
* to be mixed down to mono, etc., without having to worry about
|
||||
* doing that itself.
|
||||
*
|
||||
* ADAPT_BUFFER_SIZE - Wrap the plugin in a PluginBufferingAdapter
|
||||
* permitting the host to provide audio input using any block
|
||||
* size, with no overlap, regardless of the plugin's preferred
|
||||
* block size (suitable for hosts that read from non-seekable
|
||||
* streaming media, for example). This adapter introduces some
|
||||
* run-time overhead and also changes the semantics of the plugin
|
||||
* slightly (see the PluginBufferingAdapter header documentation
|
||||
* for details).
|
||||
*
|
||||
* ADAPT_ALL_SAFE - Perform all available adaptations that are
|
||||
* meaningful for the plugin and "safe". Currently this means to
|
||||
* ADAPT_INPUT_DOMAIN if the plugin wants FrequencyDomain input;
|
||||
* ADAPT_CHANNEL_COUNT always; and ADAPT_BUFFER_SIZE never.
|
||||
*
|
||||
* ADAPT_ALL - Perform all available adaptations that are
|
||||
* meaningful for the plugin.
|
||||
*
|
||||
* See PluginInputDomainAdapter, PluginChannelAdapter and
|
||||
* PluginBufferingAdapter for more details of the classes that the
|
||||
* loader may use if these flags are set.
|
||||
*/
|
||||
enum AdapterFlags {
|
||||
|
||||
ADAPT_INPUT_DOMAIN = 0x01,
|
||||
@ -168,56 +30,14 @@ public:
|
||||
ADAPT_ALL = 0xff
|
||||
};
|
||||
|
||||
/**
|
||||
* Load a Vamp plugin, given its identifying key. If the plugin
|
||||
* could not be loaded, returns 0.
|
||||
*
|
||||
* The returned plugin should be deleted (using the standard C++
|
||||
* delete keyword) after use.
|
||||
*
|
||||
* \param adapterFlags a bitwise OR of the values in the AdapterFlags
|
||||
* enumeration, indicating under which circumstances an adapter should be
|
||||
* used to wrap the original plugin. If adapterFlags is 0, no
|
||||
* optional adapters will be used. Otherwise, the returned plugin
|
||||
* may be of an adapter class type which will behave identically
|
||||
* to the original plugin, apart from any particular features
|
||||
* implemented by the adapter itself.
|
||||
*
|
||||
* \see AdapterFlags, PluginInputDomainAdapter, PluginChannelAdapter
|
||||
*/
|
||||
Plugin *loadPlugin(PluginKey key,
|
||||
plugin *loadPlugin(PluginKey key,
|
||||
float inputSampleRate,
|
||||
int adapterFlags = 0);
|
||||
|
||||
/**
|
||||
* Given a Vamp plugin library name and plugin identifier, return
|
||||
* the corresponding plugin key in a form suitable for passing in to
|
||||
* loadPlugin().
|
||||
*
|
||||
* (Note that the reverse of this is not well-defined and is not
|
||||
* offered in this API - consider using getLibraryPathForPlugin
|
||||
* instead. See documentation for the PluginKey type for details.)
|
||||
*
|
||||
* \see PluginKey, getLibraryPathForPlugin, loadPlugin
|
||||
*/
|
||||
PluginKey composePluginKey(std::string libraryName,
|
||||
std::string identifier);
|
||||
|
||||
/**
|
||||
* Return the category hierarchy for a Vamp plugin, given its
|
||||
* identifying key.
|
||||
*
|
||||
* If the plugin has no category information, return an empty
|
||||
* hierarchy.
|
||||
*
|
||||
* \see PluginCategoryHierarchy
|
||||
*/
|
||||
PluginCategoryHierarchy getPluginCategory(PluginKey plugin);
|
||||
|
||||
/**
|
||||
* Return the file path of the dynamic library from which the
|
||||
* given plugin will be loaded (if available).
|
||||
*/
|
||||
std::string getLibraryPathForPlugin(PluginKey plugin);
|
||||
|
||||
protected:
|
||||
@ -229,7 +49,4 @@ protected:
|
||||
|
||||
static PluginLoader *m_instance;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,30 +1,22 @@
|
||||
#include "vamp-hostsdk/PluginSummarisingAdapter.h"
|
||||
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//#define DEBUG_PLUGIN_SUMMARISING_ADAPTER 1
|
||||
//#define DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT 1
|
||||
|
||||
namespace Vamp {
|
||||
|
||||
namespace HostExt {
|
||||
|
||||
namespace vamp::host
|
||||
{
|
||||
class PluginSummarisingAdapter::Impl
|
||||
{
|
||||
public:
|
||||
Impl(Plugin *plugin, float inputSampleRate);
|
||||
Impl(plugin* p, float inputSampleRate);
|
||||
~Impl();
|
||||
|
||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||
|
||||
void reset();
|
||||
|
||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
||||
FeatureSet process(const float *const *inputBuffers, real_time timestamp);
|
||||
FeatureSet getRemainingFeatures();
|
||||
|
||||
void setSummarySegmentBoundaries(const SegmentBoundaries &);
|
||||
@ -37,22 +29,22 @@ public:
|
||||
AveragingMethod avg);
|
||||
|
||||
protected:
|
||||
Plugin *m_plugin;
|
||||
plugin *m_plugin;
|
||||
float m_inputSampleRate;
|
||||
size_t m_stepSize;
|
||||
size_t m_blockSize;
|
||||
|
||||
SegmentBoundaries m_boundaries;
|
||||
|
||||
typedef vector<float> ValueList;
|
||||
typedef std::vector<float> ValueList;
|
||||
|
||||
struct Result { // smaller than Feature
|
||||
RealTime time;
|
||||
RealTime duration;
|
||||
real_time time;
|
||||
real_time duration;
|
||||
ValueList values; // bin number -> value
|
||||
};
|
||||
|
||||
typedef vector<Result> ResultList;
|
||||
typedef std::vector<Result> ResultList;
|
||||
|
||||
struct OutputAccumulator {
|
||||
int bins;
|
||||
@ -60,14 +52,14 @@ protected:
|
||||
OutputAccumulator() : bins(0) { }
|
||||
};
|
||||
|
||||
typedef map<int, OutputAccumulator> OutputAccumulatorMap;
|
||||
typedef std::map<int, OutputAccumulator> OutputAccumulatorMap;
|
||||
OutputAccumulatorMap m_accumulators; // output number -> accumulator
|
||||
|
||||
typedef map<RealTime, OutputAccumulator> SegmentAccumulatorMap;
|
||||
typedef map<int, SegmentAccumulatorMap> OutputSegmentAccumulatorMap;
|
||||
typedef std::map<real_time, OutputAccumulator> SegmentAccumulatorMap;
|
||||
typedef std::map<int, SegmentAccumulatorMap> OutputSegmentAccumulatorMap;
|
||||
OutputSegmentAccumulatorMap m_segmentedAccumulators; // output -> segmented
|
||||
|
||||
typedef map<int, RealTime> OutputTimestampMap;
|
||||
typedef std::map<int, real_time> OutputTimestampMap;
|
||||
OutputTimestampMap m_prevTimestamps; // output number -> timestamp
|
||||
OutputTimestampMap m_prevDurations; // output number -> durations
|
||||
|
||||
@ -92,31 +84,30 @@ protected:
|
||||
double variance_c;
|
||||
};
|
||||
|
||||
typedef map<int, OutputBinSummary> OutputSummary;
|
||||
typedef map<RealTime, OutputSummary> SummarySegmentMap;
|
||||
typedef map<int, SummarySegmentMap> OutputSummarySegmentMap;
|
||||
typedef std::map<int, OutputBinSummary> OutputSummary;
|
||||
typedef std::map<real_time, OutputSummary> SummarySegmentMap;
|
||||
typedef std::map<int, SummarySegmentMap> OutputSummarySegmentMap;
|
||||
|
||||
OutputSummarySegmentMap m_summaries;
|
||||
|
||||
bool m_reduced;
|
||||
RealTime m_endTime;
|
||||
real_time m_endTime;
|
||||
|
||||
void accumulate(const FeatureSet &fs, RealTime, bool final);
|
||||
void accumulate(int output, const Feature &f, RealTime, bool final);
|
||||
void accumulate(const FeatureSet &fs, real_time, bool final);
|
||||
void accumulate(int output, const Feature &f, real_time, bool final);
|
||||
void accumulateFinalDurations();
|
||||
void findSegmentBounds(RealTime t, RealTime &start, RealTime &end);
|
||||
void findSegmentBounds(real_time t, real_time &start, real_time &end);
|
||||
void segment();
|
||||
void reduce();
|
||||
|
||||
string getSummaryLabel(SummaryType type, AveragingMethod avg);
|
||||
std::string getSummaryLabel(SummaryType type, AveragingMethod avg);
|
||||
};
|
||||
|
||||
static RealTime INVALID_DURATION(INT_MIN, INT_MIN);
|
||||
static real_time INVALID_DURATION(INT_MIN, INT_MIN);
|
||||
|
||||
PluginSummarisingAdapter::PluginSummarisingAdapter(Plugin *plugin) :
|
||||
PluginWrapper(plugin)
|
||||
PluginSummarisingAdapter::PluginSummarisingAdapter(plugin* p) : PluginWrapper(p)
|
||||
{
|
||||
m_impl = new Impl(plugin, m_inputSampleRate);
|
||||
m_impl = new Impl(p, m_inputSampleRate);
|
||||
}
|
||||
|
||||
PluginSummarisingAdapter::~PluginSummarisingAdapter()
|
||||
@ -139,13 +130,13 @@ PluginSummarisingAdapter::reset()
|
||||
m_impl->reset();
|
||||
}
|
||||
|
||||
Plugin::FeatureSet
|
||||
PluginSummarisingAdapter::process(const float *const *inputBuffers, RealTime timestamp)
|
||||
plugin::FeatureSet
|
||||
PluginSummarisingAdapter::process(const float *const *inputBuffers, real_time timestamp)
|
||||
{
|
||||
return m_impl->process(inputBuffers, timestamp);
|
||||
}
|
||||
|
||||
Plugin::FeatureSet
|
||||
plugin::FeatureSet
|
||||
PluginSummarisingAdapter::getRemainingFeatures()
|
||||
{
|
||||
return m_impl->getRemainingFeatures();
|
||||
@ -157,25 +148,18 @@ PluginSummarisingAdapter::setSummarySegmentBoundaries(const SegmentBoundaries &b
|
||||
m_impl->setSummarySegmentBoundaries(b);
|
||||
}
|
||||
|
||||
Plugin::FeatureList
|
||||
PluginSummarisingAdapter::getSummaryForOutput(int output,
|
||||
SummaryType type,
|
||||
AveragingMethod avg)
|
||||
plugin::FeatureList
|
||||
PluginSummarisingAdapter::getSummaryForOutput(int output, SummaryType type, AveragingMethod avg)
|
||||
{
|
||||
return m_impl->getSummaryForOutput(output, type, avg);
|
||||
}
|
||||
|
||||
Plugin::FeatureSet
|
||||
PluginSummarisingAdapter::getSummaryForAllOutputs(SummaryType type,
|
||||
AveragingMethod avg)
|
||||
plugin::FeatureSet PluginSummarisingAdapter::getSummaryForAllOutputs(SummaryType type, AveragingMethod avg)
|
||||
{
|
||||
return m_impl->getSummaryForAllOutputs(type, avg);
|
||||
}
|
||||
|
||||
PluginSummarisingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
|
||||
m_plugin(plugin),
|
||||
m_inputSampleRate(inputSampleRate),
|
||||
m_reduced(false)
|
||||
PluginSummarisingAdapter::Impl::Impl(plugin* p, float inputSampleRate) : m_plugin(p), m_inputSampleRate(inputSampleRate), m_reduced(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -183,16 +167,14 @@ PluginSummarisingAdapter::Impl::~Impl()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
PluginSummarisingAdapter::Impl::initialise(size_t, size_t stepSize, size_t blockSize)
|
||||
bool PluginSummarisingAdapter::Impl::initialise(size_t, size_t stepSize, size_t blockSize)
|
||||
{
|
||||
m_stepSize = stepSize;
|
||||
m_blockSize = blockSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PluginSummarisingAdapter::Impl::reset()
|
||||
void PluginSummarisingAdapter::Impl::reset()
|
||||
{
|
||||
m_accumulators.clear();
|
||||
m_segmentedAccumulators.clear();
|
||||
@ -200,33 +182,25 @@ PluginSummarisingAdapter::Impl::reset()
|
||||
m_prevDurations.clear();
|
||||
m_summaries.clear();
|
||||
m_reduced = false;
|
||||
m_endTime = RealTime();
|
||||
m_endTime = real_time();
|
||||
m_plugin->reset();
|
||||
}
|
||||
|
||||
Plugin::FeatureSet
|
||||
PluginSummarisingAdapter::Impl::process(const float *const *inputBuffers,
|
||||
RealTime timestamp)
|
||||
plugin::FeatureSet PluginSummarisingAdapter::Impl::process(const float *const *inputBuffers, real_time timestamp)
|
||||
{
|
||||
if (m_reduced) {
|
||||
cerr << "WARNING: Cannot call PluginSummarisingAdapter::process() or getRemainingFeatures() after one of the getSummary methods" << endl;
|
||||
std::cerr << "WARNING: Cannot call PluginSummarisingAdapter::process() or getRemainingFeatures() after one of the getSummary methods" << std::endl;
|
||||
}
|
||||
FeatureSet fs = m_plugin->process(inputBuffers, timestamp);
|
||||
accumulate(fs, timestamp, false);
|
||||
m_endTime = timestamp +
|
||||
RealTime::frame2RealTime(m_stepSize, int(m_inputSampleRate + 0.5));
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
|
||||
cerr << "timestamp = " << timestamp << ", end time becomes " << m_endTime
|
||||
<< endl;
|
||||
#endif
|
||||
m_endTime = timestamp + real_time::f2rt(m_stepSize, int(m_inputSampleRate + 0.5));
|
||||
return fs;
|
||||
}
|
||||
|
||||
Plugin::FeatureSet
|
||||
PluginSummarisingAdapter::Impl::getRemainingFeatures()
|
||||
plugin::FeatureSet PluginSummarisingAdapter::Impl::getRemainingFeatures()
|
||||
{
|
||||
if (m_reduced) {
|
||||
cerr << "WARNING: Cannot call PluginSummarisingAdapter::process() or getRemainingFeatures() after one of the getSummary methods" << endl;
|
||||
std::cerr << "WARNING: Cannot call PluginSummarisingAdapter::process() or getRemainingFeatures() after one of the getSummary methods" << std::endl;
|
||||
}
|
||||
FeatureSet fs = m_plugin->getRemainingFeatures();
|
||||
accumulate(fs, m_endTime, true);
|
||||
@ -247,7 +221,7 @@ PluginSummarisingAdapter::Impl::setSummarySegmentBoundaries(const SegmentBoundar
|
||||
#endif
|
||||
}
|
||||
|
||||
Plugin::FeatureList
|
||||
plugin::FeatureList
|
||||
PluginSummarisingAdapter::Impl::getSummaryForOutput(int output,
|
||||
SummaryType type,
|
||||
AveragingMethod avg)
|
||||
@ -351,7 +325,7 @@ PluginSummarisingAdapter::Impl::getSummaryForOutput(int output,
|
||||
return fl;
|
||||
}
|
||||
|
||||
Plugin::FeatureSet
|
||||
plugin::FeatureSet
|
||||
PluginSummarisingAdapter::Impl::getSummaryForAllOutputs(SummaryType type,
|
||||
AveragingMethod avg)
|
||||
{
|
||||
@ -372,7 +346,7 @@ PluginSummarisingAdapter::Impl::getSummaryForAllOutputs(SummaryType type,
|
||||
|
||||
void
|
||||
PluginSummarisingAdapter::Impl::accumulate(const FeatureSet &fs,
|
||||
RealTime timestamp,
|
||||
real_time timestamp,
|
||||
bool final)
|
||||
{
|
||||
for (FeatureSet::const_iterator i = fs.begin(); i != fs.end(); ++i) {
|
||||
@ -388,12 +362,12 @@ PluginSummarisingAdapter::Impl::accumulate(const FeatureSet &fs,
|
||||
}
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
PluginSummarisingAdapter::Impl::getSummaryLabel(SummaryType type,
|
||||
AveragingMethod avg)
|
||||
{
|
||||
string label;
|
||||
string avglabel;
|
||||
std::string label;
|
||||
std::string avglabel;
|
||||
|
||||
if (avg == SampleAverage) avglabel = ", sample average";
|
||||
else avglabel = ", continuous-time average";
|
||||
@ -415,59 +389,11 @@ PluginSummarisingAdapter::Impl::getSummaryLabel(SummaryType type,
|
||||
}
|
||||
|
||||
void
|
||||
PluginSummarisingAdapter::Impl::accumulate(int output,
|
||||
const Feature &f,
|
||||
RealTime timestamp,
|
||||
bool
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
|
||||
final
|
||||
#endif
|
||||
)
|
||||
PluginSummarisingAdapter::Impl::accumulate(int output, const Feature &f, real_time timestamp, bool)
|
||||
{
|
||||
// What should happen if a feature's duration spans a segment
|
||||
// boundary? I think we probably want to chop it, and pretend
|
||||
// that it appears in both. A very long feature (e.g. key, if the
|
||||
// whole audio is in a single key) might span many or all
|
||||
// segments, and we want that to be reflected in the results
|
||||
// (e.g. it is the modal key in all of those segments, not just
|
||||
// the first). This is actually quite complicated to do.
|
||||
|
||||
// If features spanning a boundary should be chopped, then we need
|
||||
// to have per-segment accumulators (and the feature value goes
|
||||
// into both -- with a separate phase to split the accumulator up
|
||||
// into segments).
|
||||
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
|
||||
cerr << "output " << output << ": timestamp " << timestamp << ", prev timestamp " << m_prevTimestamps[output] << ", final " << final << endl;
|
||||
#endif
|
||||
|
||||
// At each process step, accumulate() is called once for each
|
||||
// feature on each output within that process's returned feature
|
||||
// list, and with the timestamp passed in being that of the start
|
||||
// of the process block.
|
||||
|
||||
// At the end (in getRemainingFeatures), accumulate() is called
|
||||
// once for each feature on each output within the feature list
|
||||
// returned by getRemainingFeatures, and with the timestamp being
|
||||
// the same as the last process block and final set to true.
|
||||
|
||||
// (What if getRemainingFeatures doesn't return any features? We
|
||||
// still need to ensure that the final duration is written. Need
|
||||
// a separate function to close the durations.)
|
||||
|
||||
// At each call, we pull out the value for the feature and stuff
|
||||
// it into the accumulator's appropriate values array; and we
|
||||
// calculate the duration for the _previous_ feature, or pull it
|
||||
// from the prevDurations array if the previous feature had a
|
||||
// duration in its structure, and stuff that into the
|
||||
// accumulator's appropriate durations array.
|
||||
|
||||
if (m_prevDurations.find(output) != m_prevDurations.end()) {
|
||||
|
||||
// Not the first time accumulate has been called for this
|
||||
// output -- there has been a previous feature
|
||||
|
||||
RealTime prevDuration;
|
||||
real_time prevDuration;
|
||||
|
||||
// Note that m_prevDurations[output] only contains the
|
||||
// duration field that was contained in the previous feature.
|
||||
@ -478,21 +404,10 @@ PluginSummarisingAdapter::Impl::accumulate(int output,
|
||||
|
||||
if (m_prevDurations[output] != INVALID_DURATION) {
|
||||
prevDuration = m_prevDurations[output];
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
|
||||
cerr << "Previous duration from previous feature: " << prevDuration << endl;
|
||||
#endif
|
||||
} else {
|
||||
prevDuration = timestamp - m_prevTimestamps[output];
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
|
||||
cerr << "Previous duration from diff: " << timestamp << " - "
|
||||
<< m_prevTimestamps[output] << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
|
||||
cerr << "output " << output << ": ";
|
||||
cerr << "Pushing previous duration as " << prevDuration << endl;
|
||||
#endif
|
||||
|
||||
m_accumulators[output].results
|
||||
[m_accumulators[output].results.size() - 1]
|
||||
@ -505,12 +420,9 @@ PluginSummarisingAdapter::Impl::accumulate(int output,
|
||||
m_prevTimestamps[output] = timestamp;
|
||||
|
||||
if (f.hasDuration) {
|
||||
RealTime et = timestamp;
|
||||
real_time et = timestamp;
|
||||
et = et + f.duration;
|
||||
if (et > m_endTime) m_endTime = et;
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
|
||||
cerr << "feature has duration, updating end time to " << m_endTime << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
Result result;
|
||||
@ -540,51 +452,32 @@ PluginSummarisingAdapter::Impl::accumulateFinalDurations()
|
||||
|
||||
if (acount == 0) continue;
|
||||
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
|
||||
cerr << "output " << output << ": ";
|
||||
#endif
|
||||
|
||||
if (m_prevDurations.find(output) != m_prevDurations.end() &&
|
||||
m_prevDurations[output] != INVALID_DURATION) {
|
||||
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
|
||||
cerr << "Pushing final duration from feature as " << m_prevDurations[output] << endl;
|
||||
#endif
|
||||
|
||||
m_accumulators[output].results[acount - 1].duration =
|
||||
m_prevDurations[output];
|
||||
|
||||
} else {
|
||||
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
|
||||
cerr << "Pushing final duration from diff as " << m_endTime << " - " << m_prevTimestamps[output] << endl;
|
||||
#endif
|
||||
|
||||
m_accumulators[output].results[acount - 1].duration =
|
||||
m_endTime - m_prevTimestamps[output];
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
|
||||
cerr << "so duration for result no " << acount-1 << " is "
|
||||
<< m_accumulators[output].results[acount-1].duration
|
||||
<< endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginSummarisingAdapter::Impl::findSegmentBounds(RealTime t,
|
||||
RealTime &start,
|
||||
RealTime &end)
|
||||
PluginSummarisingAdapter::Impl::findSegmentBounds(real_time t,
|
||||
real_time &start,
|
||||
real_time &end)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
|
||||
cerr << "findSegmentBounds: t = " << t << endl;
|
||||
#endif
|
||||
|
||||
SegmentBoundaries::const_iterator i = upper_bound
|
||||
(m_boundaries.begin(), m_boundaries.end(), t);
|
||||
SegmentBoundaries::const_iterator i = std::upper_bound(m_boundaries.begin(), m_boundaries.end(), t);
|
||||
|
||||
start = RealTime::zeroTime;
|
||||
start = real_time::zero_time;
|
||||
end = m_endTime;
|
||||
|
||||
if (i != m_boundaries.end()) {
|
||||
@ -594,18 +487,11 @@ PluginSummarisingAdapter::Impl::findSegmentBounds(RealTime t,
|
||||
if (i != m_boundaries.begin()) {
|
||||
start = *--i;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
|
||||
cerr << "findSegmentBounds: " << t << " is in segment " << start << " -> " << end << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
PluginSummarisingAdapter::Impl::segment()
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
|
||||
cerr << "segment: starting" << endl;
|
||||
#endif
|
||||
|
||||
for (OutputAccumulatorMap::iterator i = m_accumulators.begin();
|
||||
i != m_accumulators.end(); ++i) {
|
||||
@ -613,55 +499,28 @@ PluginSummarisingAdapter::Impl::segment()
|
||||
int output = i->first;
|
||||
OutputAccumulator &source = i->second;
|
||||
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
|
||||
cerr << "segment: total results for output " << output << " = "
|
||||
<< source.results.size() << endl;
|
||||
#endif
|
||||
|
||||
// This is basically nonsense if the results have no values
|
||||
// (i.e. their times and counts are the only things of
|
||||
// interest)... but perhaps it's the user's problem if they
|
||||
// ask for segmentation (or any summary at all) in that case
|
||||
|
||||
for (int n = 0; n < int(source.results.size()); ++n) {
|
||||
real_time resultStart = source.results[n].time;
|
||||
real_time resultEnd = resultStart + source.results[n].duration;
|
||||
|
||||
// This result spans source.results[n].time to
|
||||
// source.results[n].time + source.results[n].duration.
|
||||
// We need to dispose it into segments appropriately
|
||||
real_time segmentStart = real_time::zero_time;
|
||||
real_time segmentEnd = resultEnd - real_time(1, 0);
|
||||
|
||||
RealTime resultStart = source.results[n].time;
|
||||
RealTime resultEnd = resultStart + source.results[n].duration;
|
||||
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
|
||||
cerr << "output: " << output << ", result start = " << resultStart << ", end = " << resultEnd << endl;
|
||||
#endif
|
||||
|
||||
RealTime segmentStart = RealTime::zeroTime;
|
||||
RealTime segmentEnd = resultEnd - RealTime(1, 0);
|
||||
|
||||
RealTime prevSegmentStart = segmentStart - RealTime(1, 0);
|
||||
real_time prevSegmentStart = segmentStart - real_time(1, 0);
|
||||
|
||||
while (segmentEnd < resultEnd) {
|
||||
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
|
||||
cerr << "segment end " << segmentEnd << " < result end "
|
||||
<< resultEnd << " (with result start " << resultStart << ")" << endl;
|
||||
#endif
|
||||
|
||||
findSegmentBounds(resultStart, segmentStart, segmentEnd);
|
||||
|
||||
if (segmentStart == prevSegmentStart) {
|
||||
// This can happen when we reach the end of the
|
||||
// input, if a feature's end time overruns the
|
||||
// input audio end time
|
||||
break;
|
||||
}
|
||||
prevSegmentStart = segmentStart;
|
||||
|
||||
RealTime chunkStart = resultStart;
|
||||
real_time chunkStart = resultStart;
|
||||
if (chunkStart < segmentStart) chunkStart = segmentStart;
|
||||
|
||||
RealTime chunkEnd = resultEnd;
|
||||
real_time chunkEnd = resultEnd;
|
||||
if (chunkEnd > segmentEnd) chunkEnd = segmentEnd;
|
||||
|
||||
m_segmentedAccumulators[output][segmentStart].bins = source.bins;
|
||||
@ -671,12 +530,7 @@ PluginSummarisingAdapter::Impl::segment()
|
||||
chunk.duration = chunkEnd - chunkStart;
|
||||
chunk.values = source.results[n].values;
|
||||
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER_SEGMENT
|
||||
cerr << "chunk for segment " << segmentStart << ": from " << chunk.time << ", duration " << chunk.duration << endl;
|
||||
#endif
|
||||
|
||||
m_segmentedAccumulators[output][segmentStart].results
|
||||
.push_back(chunk);
|
||||
m_segmentedAccumulators[output][segmentStart].results.push_back(chunk);
|
||||
|
||||
resultStart = chunkEnd;
|
||||
}
|
||||
@ -701,7 +555,7 @@ struct ValueDurationFloatPair
|
||||
}
|
||||
};
|
||||
|
||||
static double toSec(const RealTime &r)
|
||||
static double toSec(const real_time &r)
|
||||
{
|
||||
return r.sec + double(r.nsec) / 1000000000.0;
|
||||
}
|
||||
@ -719,7 +573,7 @@ PluginSummarisingAdapter::Impl::reduce()
|
||||
for (SegmentAccumulatorMap::iterator j = segments.begin();
|
||||
j != segments.end(); ++j) {
|
||||
|
||||
RealTime segmentStart = j->first;
|
||||
real_time segmentStart = j->first;
|
||||
OutputAccumulator &accumulator = j->second;
|
||||
|
||||
int sz = int(accumulator.results.size());
|
||||
@ -770,7 +624,7 @@ PluginSummarisingAdapter::Impl::reduce()
|
||||
|
||||
if (sz == 0) continue;
|
||||
|
||||
vector<ValueDurationFloatPair> valvec;
|
||||
std::vector<ValueDurationFloatPair> valvec;
|
||||
|
||||
for (int k = 0; k < sz; ++k) {
|
||||
while (int(accumulator.results[k].values.size()) <
|
||||
@ -828,7 +682,7 @@ PluginSummarisingAdapter::Impl::reduce()
|
||||
cerr << "median = " << summary.median << endl;
|
||||
#endif
|
||||
|
||||
map<float, int> distribution;
|
||||
std::map<float, int> distribution;
|
||||
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
|
||||
cerr << "summing (discrete): ";
|
||||
@ -846,7 +700,7 @@ PluginSummarisingAdapter::Impl::reduce()
|
||||
|
||||
int md = 0;
|
||||
|
||||
for (map<float, int>::iterator di = distribution.begin();
|
||||
for (std::map<float, int>::iterator di = distribution.begin();
|
||||
di != distribution.end(); ++di) {
|
||||
if (di->second > md) {
|
||||
md = di->second;
|
||||
@ -856,7 +710,7 @@ PluginSummarisingAdapter::Impl::reduce()
|
||||
|
||||
distribution.clear();
|
||||
|
||||
map<float, double> distribution_c;
|
||||
std::map<float, double> distribution_c;
|
||||
|
||||
for (int k = 0; k < sz; ++k) {
|
||||
distribution_c[accumulator.results[k].values[bin]]
|
||||
@ -865,7 +719,7 @@ PluginSummarisingAdapter::Impl::reduce()
|
||||
|
||||
double mrd = 0.0;
|
||||
|
||||
for (map<float, double>::iterator di = distribution_c.begin();
|
||||
for (std::map<float, double>::iterator di = distribution_c.begin();
|
||||
di != distribution_c.end(); ++di) {
|
||||
if (di->second > mrd) {
|
||||
#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
|
||||
@ -941,8 +795,4 @@ PluginSummarisingAdapter::Impl::reduce()
|
||||
m_segmentedAccumulators.clear();
|
||||
m_accumulators.clear();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,77 +4,23 @@
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace Vamp {
|
||||
namespace HostExt {
|
||||
|
||||
/**
|
||||
* \class PluginSummarisingAdapter PluginSummarisingAdapter.h <vamp-hostsdk/PluginSummarisingAdapter.h>
|
||||
*
|
||||
* PluginSummarisingAdapter is a Vamp plugin adapter that provides
|
||||
* summarisation methods such as mean and median averages of output
|
||||
* features, for use in any context where an available plugin produces
|
||||
* individual values but the result that is actually needed is some
|
||||
* sort of aggregate.
|
||||
*
|
||||
* To make use of PluginSummarisingAdapter, the host should configure,
|
||||
* initialise and run the plugin through the adapter interface just as
|
||||
* normal. Then, after the process and getRemainingFeatures methods
|
||||
* have been properly called and processing is complete, the host may
|
||||
* call getSummaryForOutput or getSummaryForAllOutputs to obtain
|
||||
* summarised features: averages, maximum values, etc, depending on
|
||||
* the SummaryType passed to the function.
|
||||
*
|
||||
* By default PluginSummarisingAdapter calculates a single summary of
|
||||
* each output's feature across the whole duration of processed audio.
|
||||
* A host needing summaries of sub-segments of the whole audio may
|
||||
* call setSummarySegmentBoundaries before retrieving the summaries,
|
||||
* providing a list of times such that one summary will be provided
|
||||
* for each segment between two consecutive times.
|
||||
*
|
||||
* PluginSummarisingAdapter is straightforward rather than fast. It
|
||||
* calculates all of the summary types for all outputs always, and
|
||||
* then returns only the ones that are requested. It is designed on
|
||||
* the basis that, for most features, summarising and storing
|
||||
* summarised results is far cheaper than calculating the results in
|
||||
* the first place. If this is not true for your particular feature,
|
||||
* PluginSummarisingAdapter may not be the best approach for you.
|
||||
*
|
||||
* \note This class was introduced in version 2.0 of the Vamp plugin SDK.
|
||||
*/
|
||||
|
||||
namespace vamp::host
|
||||
{
|
||||
class PluginSummarisingAdapter : public PluginWrapper
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Construct a PluginSummarisingAdapter wrapping the given plugin.
|
||||
* The adapter takes ownership of the plugin, which will be
|
||||
* deleted when the adapter is deleted.
|
||||
*/
|
||||
PluginSummarisingAdapter(Plugin *plugin);
|
||||
PluginSummarisingAdapter(plugin* p);
|
||||
virtual ~PluginSummarisingAdapter();
|
||||
|
||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||
|
||||
void reset();
|
||||
|
||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
||||
FeatureSet process(const float *const *inputBuffers, real_time timestamp);
|
||||
FeatureSet getRemainingFeatures();
|
||||
|
||||
typedef std::set<RealTime> SegmentBoundaries;
|
||||
typedef std::set<real_time> SegmentBoundaries;
|
||||
|
||||
/**
|
||||
* Specify a series of segment boundaries, such that one summary
|
||||
* will be returned for each of the contiguous intra-boundary
|
||||
* segments. This function must be called before
|
||||
* getSummaryForOutput or getSummaryForAllOutputs.
|
||||
*
|
||||
* Note that you cannot retrieve results with multiple different
|
||||
* segmentations by repeatedly calling this function followed by
|
||||
* one of the getSummary functions. The summaries are all
|
||||
* calculated at the first call to any getSummary function, and
|
||||
* once the summaries have been calculated, they remain
|
||||
* calculated.
|
||||
*/
|
||||
void setSummarySegmentBoundaries(const SegmentBoundaries &);
|
||||
|
||||
enum SummaryType {
|
||||
@ -91,62 +37,17 @@ public:
|
||||
UnknownSummaryType = 999
|
||||
};
|
||||
|
||||
/**
|
||||
* AveragingMethod indicates how the adapter should handle
|
||||
* average-based summaries of features whose results are not
|
||||
* equally spaced in time.
|
||||
*
|
||||
* If SampleAverage is specified, summary types based on averages
|
||||
* will be calculated by treating each result individually without
|
||||
* regard to its time: for example, the mean will be the sum of
|
||||
* all values divided by the number of values.
|
||||
*
|
||||
* If ContinuousTimeAverage is specified, each feature will be
|
||||
* considered to have a duration, either as specified in the
|
||||
* feature's duration field, or until the following feature: thus,
|
||||
* for example, the mean will be the sum of the products of values
|
||||
* and durations, divided by the total duration.
|
||||
*
|
||||
* Although SampleAverage is useful for many types of feature,
|
||||
* ContinuousTimeAverage is essential for some situations, for
|
||||
* example finding the result that spans the largest proportion of
|
||||
* the input given a feature that emits a new result only when the
|
||||
* value changes (the modal value integrated over time).
|
||||
*/
|
||||
enum AveragingMethod {
|
||||
enum AveragingMethod
|
||||
{
|
||||
SampleAverage = 0,
|
||||
ContinuousTimeAverage = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* Return summaries of the features that were returned on the
|
||||
* given output, using the given SummaryType and AveragingMethod.
|
||||
*
|
||||
* The plugin must have been fully run (process() and
|
||||
* getRemainingFeatures() calls all made as appropriate) before
|
||||
* this function is called.
|
||||
*/
|
||||
FeatureList getSummaryForOutput(int output,
|
||||
SummaryType type,
|
||||
AveragingMethod method = SampleAverage);
|
||||
|
||||
/**
|
||||
* Return summaries of the features that were returned on all of
|
||||
* the plugin's outputs, using the given SummaryType and
|
||||
* AveragingMethod.
|
||||
*
|
||||
* The plugin must have been fully run (process() and
|
||||
* getRemainingFeatures() calls all made as appropriate) before
|
||||
* this function is called.
|
||||
*/
|
||||
FeatureSet getSummaryForAllOutputs(SummaryType type,
|
||||
AveragingMethod method = SampleAverage);
|
||||
FeatureList getSummaryForOutput(int output, SummaryType type, AveragingMethod method = SampleAverage);
|
||||
FeatureSet getSummaryForAllOutputs(SummaryType type, AveragingMethod method = SampleAverage);
|
||||
|
||||
protected:
|
||||
class Impl;
|
||||
Impl *m_impl;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,12 +1,8 @@
|
||||
#include "vamp-hostsdk/PluginWrapper.h"
|
||||
|
||||
namespace Vamp {
|
||||
|
||||
namespace HostExt {
|
||||
|
||||
PluginWrapper::PluginWrapper(Plugin *plugin) :
|
||||
Plugin(plugin->getInputSampleRate()),
|
||||
m_plugin(plugin)
|
||||
namespace vamp::host
|
||||
{
|
||||
PluginWrapper::PluginWrapper(plugin* p) : plugin(p->getInputSampleRate()), m_plugin(p)
|
||||
{
|
||||
}
|
||||
|
||||
@ -15,116 +11,82 @@ PluginWrapper::~PluginWrapper()
|
||||
delete m_plugin;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginWrapper::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
||||
bool PluginWrapper::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
||||
{
|
||||
return m_plugin->initialise(channels, stepSize, blockSize);
|
||||
}
|
||||
|
||||
void
|
||||
PluginWrapper::reset()
|
||||
void PluginWrapper::reset()
|
||||
{
|
||||
m_plugin->reset();
|
||||
}
|
||||
|
||||
Plugin::InputDomain
|
||||
PluginWrapper::getInputDomain() const
|
||||
plugin::InputDomain PluginWrapper::getInputDomain() const
|
||||
{
|
||||
return m_plugin->getInputDomain();
|
||||
}
|
||||
|
||||
unsigned int
|
||||
PluginWrapper::getVampApiVersion() const
|
||||
std::string PluginWrapper::get_identifier() const
|
||||
{
|
||||
return m_plugin->getVampApiVersion();
|
||||
return m_plugin->get_identifier();
|
||||
}
|
||||
|
||||
std::string
|
||||
PluginWrapper::getIdentifier() const
|
||||
std::string PluginWrapper::get_name() const
|
||||
{
|
||||
return m_plugin->getIdentifier();
|
||||
return m_plugin->get_name();
|
||||
}
|
||||
|
||||
std::string
|
||||
PluginWrapper::getName() const
|
||||
std::string PluginWrapper::get_description() const
|
||||
{
|
||||
return m_plugin->getName();
|
||||
return m_plugin->get_description();
|
||||
}
|
||||
|
||||
std::string
|
||||
PluginWrapper::getDescription() const
|
||||
std::string PluginWrapper::get_maker() const
|
||||
{
|
||||
return m_plugin->getDescription();
|
||||
return m_plugin->get_maker();
|
||||
}
|
||||
|
||||
std::string
|
||||
PluginWrapper::getMaker() const
|
||||
plugin::parameter_descriptors PluginWrapper::get_parameter_descriptors() const
|
||||
{
|
||||
return m_plugin->getMaker();
|
||||
return m_plugin->get_parameter_descriptors();
|
||||
}
|
||||
|
||||
int
|
||||
PluginWrapper::getPluginVersion() const
|
||||
float PluginWrapper::get_parameter(std::string parameter) const
|
||||
{
|
||||
return m_plugin->getPluginVersion();
|
||||
return m_plugin->get_parameter(parameter);
|
||||
}
|
||||
|
||||
std::string
|
||||
PluginWrapper::getCopyright() const
|
||||
void PluginWrapper::set_parameter(std::string parameter, float value)
|
||||
{
|
||||
return m_plugin->getCopyright();
|
||||
m_plugin->set_parameter(parameter, value);
|
||||
}
|
||||
|
||||
PluginBase::ParameterList
|
||||
PluginWrapper::getParameterDescriptors() const
|
||||
plugin::programs PluginWrapper::get_programs() const
|
||||
{
|
||||
return m_plugin->getParameterDescriptors();
|
||||
return m_plugin->get_programs();
|
||||
}
|
||||
|
||||
float
|
||||
PluginWrapper::getParameter(std::string parameter) const
|
||||
std::string PluginWrapper::get_current_program() const
|
||||
{
|
||||
return m_plugin->getParameter(parameter);
|
||||
return m_plugin->get_current_program();
|
||||
}
|
||||
|
||||
void
|
||||
PluginWrapper::setParameter(std::string parameter, float value)
|
||||
void PluginWrapper::select_program(std::string program)
|
||||
{
|
||||
m_plugin->setParameter(parameter, value);
|
||||
m_plugin->select_program(program);
|
||||
}
|
||||
|
||||
PluginBase::ProgramList
|
||||
PluginWrapper::getPrograms() const
|
||||
{
|
||||
return m_plugin->getPrograms();
|
||||
}
|
||||
|
||||
std::string
|
||||
PluginWrapper::getCurrentProgram() const
|
||||
{
|
||||
return m_plugin->getCurrentProgram();
|
||||
}
|
||||
|
||||
void
|
||||
PluginWrapper::selectProgram(std::string program)
|
||||
{
|
||||
m_plugin->selectProgram(program);
|
||||
}
|
||||
|
||||
size_t
|
||||
PluginWrapper::getPreferredStepSize() const
|
||||
size_t PluginWrapper::getPreferredStepSize() const
|
||||
{
|
||||
return m_plugin->getPreferredStepSize();
|
||||
}
|
||||
|
||||
size_t
|
||||
PluginWrapper::getPreferredBlockSize() const
|
||||
size_t PluginWrapper::getPreferredBlockSize() const
|
||||
{
|
||||
return m_plugin->getPreferredBlockSize();
|
||||
}
|
||||
|
||||
size_t
|
||||
PluginWrapper::getMinChannelCount() const
|
||||
size_t PluginWrapper::getMinChannelCount() const
|
||||
{
|
||||
return m_plugin->getMinChannelCount();
|
||||
}
|
||||
@ -134,24 +96,18 @@ size_t PluginWrapper::getMaxChannelCount() const
|
||||
return m_plugin->getMaxChannelCount();
|
||||
}
|
||||
|
||||
Plugin::OutputList
|
||||
PluginWrapper::getOutputDescriptors() const
|
||||
plugin::OutputList PluginWrapper::getOutputDescriptors() const
|
||||
{
|
||||
return m_plugin->getOutputDescriptors();
|
||||
}
|
||||
|
||||
Plugin::FeatureSet
|
||||
PluginWrapper::process(const float *const *inputBuffers, RealTime timestamp)
|
||||
plugin::FeatureSet PluginWrapper::process(const float *const *inputBuffers, real_time timestamp)
|
||||
{
|
||||
return m_plugin->process(inputBuffers, timestamp);
|
||||
}
|
||||
|
||||
Plugin::FeatureSet
|
||||
PluginWrapper::getRemainingFeatures()
|
||||
plugin::FeatureSet PluginWrapper::getRemainingFeatures()
|
||||
{
|
||||
return m_plugin->getRemainingFeatures();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,76 +2,46 @@
|
||||
|
||||
#include "vamp-sdk/Plugin.h"
|
||||
|
||||
namespace Vamp::HostExt {
|
||||
|
||||
/**
|
||||
* \class PluginWrapper PluginWrapper.h <vamp-hostsdk/PluginWrapper.h>
|
||||
*
|
||||
* PluginWrapper is a simple base class for adapter plugins. It takes
|
||||
* a pointer to a "to be wrapped" Vamp plugin on construction, and
|
||||
* provides implementations of all the Vamp plugin methods that simply
|
||||
* delegate through to the wrapped plugin. A subclass can therefore
|
||||
* override only the methods that are meaningful for the particular
|
||||
* adapter.
|
||||
*
|
||||
* \note This class was introduced in version 1.1 of the Vamp plugin SDK.
|
||||
*/
|
||||
|
||||
class PluginWrapper : public Plugin
|
||||
namespace vamp::host
|
||||
{
|
||||
class PluginWrapper : public plugin
|
||||
{
|
||||
public:
|
||||
virtual ~PluginWrapper();
|
||||
|
||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||
void reset();
|
||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize) override;
|
||||
void reset() override;
|
||||
|
||||
InputDomain getInputDomain() const;
|
||||
InputDomain getInputDomain() const override;
|
||||
|
||||
unsigned int getVampApiVersion() const;
|
||||
std::string getIdentifier() const;
|
||||
std::string getName() const;
|
||||
std::string getDescription() const;
|
||||
std::string getMaker() const;
|
||||
int getPluginVersion() const;
|
||||
std::string getCopyright() const;
|
||||
std::string get_identifier() const override;
|
||||
std::string get_name() const override;
|
||||
std::string get_description() const override;
|
||||
std::string get_maker() const override;
|
||||
|
||||
ParameterList getParameterDescriptors() const;
|
||||
float getParameter(std::string) const;
|
||||
void setParameter(std::string, float);
|
||||
parameter_descriptors get_parameter_descriptors() const override;
|
||||
float get_parameter(std::string) const override;
|
||||
void set_parameter(std::string, float) override;
|
||||
|
||||
ProgramList getPrograms() const;
|
||||
std::string getCurrentProgram() const;
|
||||
void selectProgram(std::string);
|
||||
programs get_programs() const override;
|
||||
std::string get_current_program() const override;
|
||||
void select_program(std::string) override;
|
||||
|
||||
size_t getPreferredStepSize() const;
|
||||
size_t getPreferredBlockSize() const;
|
||||
size_t getPreferredStepSize() const override;
|
||||
size_t getPreferredBlockSize() const override;
|
||||
|
||||
size_t getMinChannelCount() const;
|
||||
size_t getMaxChannelCount() const;
|
||||
size_t getMinChannelCount() const override;
|
||||
size_t getMaxChannelCount() const override;
|
||||
|
||||
OutputList getOutputDescriptors() const;
|
||||
OutputList getOutputDescriptors() const override;
|
||||
|
||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
||||
FeatureSet process(const float *const *inputBuffers, real_time timestamp) override;
|
||||
|
||||
FeatureSet getRemainingFeatures();
|
||||
FeatureSet getRemainingFeatures() override;
|
||||
|
||||
/**
|
||||
* Return a pointer to the plugin wrapper of type WrapperType
|
||||
* surrounding this wrapper's plugin, if present.
|
||||
*
|
||||
* This is useful in situations where a plugin is wrapped by
|
||||
* multiple different wrappers (one inside another) and the host
|
||||
* wants to call some wrapper-specific function on one of the
|
||||
* layers without having to care about the order in which they are
|
||||
* wrapped. For example, the plugin returned by
|
||||
* PluginLoader::loadPlugin may have more than one wrapper; if the
|
||||
* host wanted to query or fine-tune some property of one of them,
|
||||
* it would be hard to do so without knowing the order of the
|
||||
* wrappers. This function therefore gives direct access to the
|
||||
* wrapper of a particular type.
|
||||
*/
|
||||
template <typename WrapperType>
|
||||
WrapperType *getWrapper() {
|
||||
WrapperType* getWrapper()
|
||||
{
|
||||
WrapperType *w = dynamic_cast<WrapperType *>(this);
|
||||
if (w) return w;
|
||||
PluginWrapper *pw = dynamic_cast<PluginWrapper *>(m_plugin);
|
||||
@ -80,8 +50,8 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
PluginWrapper(Plugin *plugin); // I take ownership of plugin
|
||||
Plugin *m_plugin;
|
||||
PluginWrapper(plugin* p);
|
||||
plugin* m_plugin;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,16 +0,0 @@
|
||||
/* These stubs are provided so that autoconf can check library
|
||||
* versions using C symbols only */
|
||||
|
||||
extern void libvamphostsdk_v_2_9_present(void) { }
|
||||
extern void libvamphostsdk_v_2_8_present(void) { }
|
||||
extern void libvamphostsdk_v_2_7_1_present(void) { }
|
||||
extern void libvamphostsdk_v_2_7_present(void) { }
|
||||
extern void libvamphostsdk_v_2_6_present(void) { }
|
||||
extern void libvamphostsdk_v_2_5_present(void) { }
|
||||
extern void libvamphostsdk_v_2_4_present(void) { }
|
||||
extern void libvamphostsdk_v_2_3_1_present(void) { }
|
||||
extern void libvamphostsdk_v_2_3_present(void) { }
|
||||
extern void libvamphostsdk_v_2_2_1_present(void) { }
|
||||
extern void libvamphostsdk_v_2_2_present(void) { }
|
||||
extern void libvamphostsdk_v_2_1_present(void) { }
|
||||
extern void libvamphostsdk_v_2_0_present(void) { }
|
@ -6,10 +6,8 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
using namespace std;
|
||||
|
||||
static vector<string> files;
|
||||
static map<string, const char *> cnames;
|
||||
static std::vector<std::string> files;
|
||||
static std::map<std::string, const char *> cnames;
|
||||
static bool haveFiles = false;
|
||||
|
||||
struct vhLibrary_t {
|
||||
@ -63,7 +61,7 @@ vhLibrary vhLoadLibrary(int index)
|
||||
return 0;
|
||||
}
|
||||
|
||||
string fullPath = files[index];
|
||||
std::string fullPath = files[index];
|
||||
void *lib = Files::loadLibrary(fullPath);
|
||||
|
||||
if (!lib) return 0;
|
||||
@ -72,8 +70,8 @@ vhLibrary vhLoadLibrary(int index)
|
||||
(VampGetPluginDescriptorFunction)Files::lookupInLibrary
|
||||
(lib, "vampGetPluginDescriptor");
|
||||
if (!func) {
|
||||
cerr << "vhLoadLibrary: No vampGetPluginDescriptor function found in library \""
|
||||
<< fullPath << "\"" << endl;
|
||||
std::cerr << "vhLoadLibrary: No vampGetPluginDescriptor function found in library \""
|
||||
<< fullPath << "\"" << std::endl;
|
||||
Files::unloadLibrary(lib);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,53 +1,9 @@
|
||||
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
Vamp
|
||||
|
||||
An API for audio analysis and feature extraction plugins.
|
||||
|
||||
Centre for Digital Music, Queen Mary, University of London.
|
||||
Copyright 2006 Chris Cannam.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
||||
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the names of the Centre for
|
||||
Digital Music; Queen Mary, University of London; and Chris Cannam
|
||||
shall not be used in advertising or otherwise to promote the sale,
|
||||
use or other dealings in this Software without prior written
|
||||
authorization.
|
||||
*/
|
||||
|
||||
#ifndef _VAMP_HOSTSDK_SINGLE_INCLUDE_H_
|
||||
#define _VAMP_HOSTSDK_SINGLE_INCLUDE_H_
|
||||
|
||||
#include "PluginBase.h"
|
||||
#include "PluginBufferingAdapter.h"
|
||||
#include "PluginChannelAdapter.h"
|
||||
#include "Plugin.h"
|
||||
#include "PluginHostAdapter.h"
|
||||
#include "PluginInputDomainAdapter.h"
|
||||
#include "PluginLoader.h"
|
||||
#include "PluginSummarisingAdapter.h"
|
||||
#include "PluginWrapper.h"
|
||||
#include "RealTime.h"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -6,7 +6,8 @@
|
||||
#include "vamp-sdk/ext/vamp_kiss_fft.h"
|
||||
#include "vamp-sdk/ext/vamp_kiss_fftr.h"
|
||||
|
||||
namespace Vamp {
|
||||
namespace vamp
|
||||
{
|
||||
|
||||
void FFT::forward(unsigned int un, const double* ri, const double* ii, double* ro, double* io)
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
namespace Vamp {
|
||||
namespace vamp
|
||||
{
|
||||
|
||||
/**
|
||||
* A simple FFT implementation provided for convenience of plugin
|
||||
|
@ -4,282 +4,45 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "PluginBase.h"
|
||||
#include "RealTime.h"
|
||||
#include "real_time/real_time.hpp"
|
||||
|
||||
namespace Vamp {
|
||||
|
||||
/**
|
||||
* \class Plugin Plugin.h <vamp-sdk/Plugin.h>
|
||||
*
|
||||
* Vamp::Plugin is a base class for plugin instance classes
|
||||
* that provide feature extraction from audio or related data.
|
||||
*
|
||||
* In most cases, the input will be audio and the output will be a
|
||||
* stream of derived data at a lower sampling resolution than the
|
||||
* input.
|
||||
*
|
||||
* Note that this class inherits several abstract methods from
|
||||
* PluginBase. These must be implemented by the subclass.
|
||||
*
|
||||
*
|
||||
* PLUGIN LIFECYCLE
|
||||
*
|
||||
* Feature extraction plugins are managed differently from real-time
|
||||
* plugins (such as VST effects). The main difference is that the
|
||||
* parameters for a feature extraction plugin are configured before
|
||||
* the plugin is used, and do not change during use.
|
||||
*
|
||||
* 1. Host constructs the plugin, passing it the input sample rate.
|
||||
* The plugin may do basic initialisation, but should not do anything
|
||||
* computationally expensive at this point. You must make sure your
|
||||
* plugin is cheap to construct, otherwise you'll seriously affect the
|
||||
* startup performance of almost all hosts. If you have serious
|
||||
* initialisation to do, the proper place is in initialise() (step 5).
|
||||
*
|
||||
* 2. Host may query the plugin's available outputs.
|
||||
*
|
||||
* 3. Host queries programs and parameter descriptors, and may set
|
||||
* some or all of them. Parameters that are not explicitly set should
|
||||
* take their default values as specified in the parameter descriptor.
|
||||
* When a program is set, the parameter values may change and the host
|
||||
* will re-query them to check.
|
||||
*
|
||||
* 4. Host queries the preferred step size, block size and number of
|
||||
* channels. These may all vary depending on the parameter values.
|
||||
* (Note however that you cannot make the number of distinct outputs
|
||||
* dependent on parameter values.)
|
||||
*
|
||||
* 5. Plugin is properly initialised with a call to initialise. This
|
||||
* fixes the step size, block size, and number of channels, as well as
|
||||
* all of the parameter and program settings. If the values passed in
|
||||
* to initialise do not match the plugin's advertised preferred values
|
||||
* from step 4, the plugin may refuse to initialise and return false
|
||||
* (although if possible it should accept the new values). Any
|
||||
* computationally expensive setup code should take place here.
|
||||
*
|
||||
* 6. Host finally checks the number of values, resolution, extents
|
||||
* etc per output (which may vary depending on the number of channels,
|
||||
* step size and block size as well as the parameter values).
|
||||
*
|
||||
* 7. Host will repeatedly call the process method to pass in blocks
|
||||
* of input data. This method may return features extracted from that
|
||||
* data (if the plugin is causal).
|
||||
*
|
||||
* 8. Host will call getRemainingFeatures exactly once, after all the
|
||||
* input data has been processed. This may return any non-causal or
|
||||
* leftover features.
|
||||
*
|
||||
* 9. At any point after initialise was called, the host may
|
||||
* optionally call the reset method and restart processing. (This
|
||||
* does not mean it can change the parameters, which are fixed from
|
||||
* initialise until destruction.)
|
||||
*
|
||||
* A plugin does not need to handle the case where setParameter or
|
||||
* selectProgram is called after initialise has been called. It's the
|
||||
* host's responsibility not to do that. Similarly, the plugin may
|
||||
* safely assume that initialise is called no more than once.
|
||||
*/
|
||||
|
||||
class Plugin : public PluginBase
|
||||
namespace vamp
|
||||
{
|
||||
class plugin
|
||||
{
|
||||
public:
|
||||
virtual ~Plugin() { }
|
||||
|
||||
/**
|
||||
* Initialise a plugin to prepare it for use with the given number
|
||||
* of input channels, step size (window increment, in sample
|
||||
* frames) and block size (window size, in sample frames).
|
||||
*
|
||||
* The input sample rate should have been already specified at
|
||||
* construction time.
|
||||
*
|
||||
* Return true for successful initialisation, false if the number
|
||||
* of input channels, step size and/or block size cannot be
|
||||
* supported.
|
||||
*/
|
||||
virtual bool initialise(size_t inputChannels,
|
||||
size_t stepSize,
|
||||
size_t blockSize) = 0;
|
||||
|
||||
/**
|
||||
* Reset the plugin after use, to prepare it for another clean
|
||||
* run. Not called for the first initialisation (i.e. initialise
|
||||
* must also do a reset).
|
||||
*/
|
||||
virtual void reset() = 0;
|
||||
virtual ~plugin() { }
|
||||
|
||||
enum InputDomain { TimeDomain, FrequencyDomain };
|
||||
|
||||
/**
|
||||
* Get the plugin's required input domain.
|
||||
*
|
||||
* If this is TimeDomain, the samples provided to the process()
|
||||
* function (below) will be in the time domain, as for a
|
||||
* traditional audio processing plugin.
|
||||
*
|
||||
* If this is FrequencyDomain, the host will carry out a windowed
|
||||
* FFT of size equal to the negotiated block size on the data
|
||||
* before passing the frequency bin data in to process(). The
|
||||
* input data for the FFT will be rotated so as to place the
|
||||
* origin in the centre of the block.
|
||||
* The plugin does not get to choose the window type -- the host
|
||||
* will either let the user do so, or will use a Hanning window.
|
||||
*/
|
||||
virtual InputDomain getInputDomain() const = 0;
|
||||
|
||||
/**
|
||||
* Get the preferred block size (window size -- the number of
|
||||
* sample frames passed in each block to the process() function).
|
||||
* This should be called before initialise().
|
||||
*
|
||||
* A plugin that can handle any block size may return 0. The
|
||||
* final block size will be set in the initialise() call.
|
||||
*/
|
||||
virtual size_t getPreferredBlockSize() const { return 0; }
|
||||
|
||||
/**
|
||||
* Get the preferred step size (window increment -- the distance
|
||||
* in sample frames between the start frames of consecutive blocks
|
||||
* passed to the process() function) for the plugin. This should
|
||||
* be called before initialise().
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
virtual size_t getPreferredStepSize() const { return 0; }
|
||||
|
||||
/**
|
||||
* Get the minimum supported number of input channels.
|
||||
*/
|
||||
virtual size_t getMinChannelCount() const { return 1; }
|
||||
|
||||
/**
|
||||
* Get the maximum supported number of input channels.
|
||||
*/
|
||||
virtual size_t getMaxChannelCount() const { return 1; }
|
||||
|
||||
struct OutputDescriptor
|
||||
{
|
||||
/**
|
||||
* The name of the output, in computer-usable form. Should be
|
||||
* reasonably short and without whitespace or punctuation, using
|
||||
* the characters [a-zA-Z0-9_-] only.
|
||||
* Example: "zero_crossing_count"
|
||||
*/
|
||||
std::string identifier;
|
||||
|
||||
/**
|
||||
* The human-readable name of the output.
|
||||
* Example: "Zero Crossing Counts"
|
||||
*/
|
||||
std::string name;
|
||||
|
||||
/**
|
||||
* A human-readable short text describing the output. May be
|
||||
* empty if the name has said it all already.
|
||||
* Example: "The number of zero crossing points per processing block"
|
||||
*/
|
||||
std::string description;
|
||||
|
||||
/**
|
||||
* The unit of the output, in human-readable form.
|
||||
*/
|
||||
std::string unit;
|
||||
|
||||
/**
|
||||
* True if the output has the same number of values per sample
|
||||
* for every output sample. Outputs for which this is false
|
||||
* are unlikely to be very useful in a general-purpose host.
|
||||
*/
|
||||
bool hasFixedBinCount;
|
||||
|
||||
/**
|
||||
* The number of values per result of the output. Undefined
|
||||
* if hasFixedBinCount is false. If this is zero, the output
|
||||
* is point data (i.e. only the time of each output is of
|
||||
* interest, the value list will be empty).
|
||||
*/
|
||||
size_t binCount;
|
||||
|
||||
/**
|
||||
* The (human-readable) names of each of the bins, if
|
||||
* appropriate. This is always optional.
|
||||
*/
|
||||
std::vector<std::string> binNames;
|
||||
|
||||
/**
|
||||
* True if the results in each output bin fall within a fixed
|
||||
* numeric range (minimum and maximum values). Undefined if
|
||||
* binCount is zero.
|
||||
*/
|
||||
bool hasKnownExtents;
|
||||
|
||||
/**
|
||||
* Minimum value of the results in the output. Undefined if
|
||||
* hasKnownExtents is false or binCount is zero.
|
||||
*/
|
||||
float minValue;
|
||||
|
||||
/**
|
||||
* Maximum value of the results in the output. Undefined if
|
||||
* hasKnownExtents is false or binCount is zero.
|
||||
*/
|
||||
float maxValue;
|
||||
|
||||
/**
|
||||
* True if the output values are quantized to a particular
|
||||
* resolution. Undefined if binCount is zero.
|
||||
*/
|
||||
bool isQuantized;
|
||||
|
||||
/**
|
||||
* Quantization resolution of the output values (e.g. 1.0 if
|
||||
* they are all integers). Undefined if isQuantized is false
|
||||
* or binCount is zero.
|
||||
*/
|
||||
float quantizeStep;
|
||||
|
||||
enum SampleType {
|
||||
|
||||
/// Results from each process() align with that call's block start
|
||||
enum SampleType
|
||||
{
|
||||
OneSamplePerStep,
|
||||
|
||||
/// Results are evenly spaced in time (sampleRate specified below)
|
||||
FixedSampleRate,
|
||||
|
||||
/// Results are unevenly spaced and have individual timestamps
|
||||
VariableSampleRate
|
||||
};
|
||||
|
||||
/**
|
||||
* Positioning in time of the output results.
|
||||
*/
|
||||
SampleType sampleType;
|
||||
|
||||
/**
|
||||
* Sample rate of the output results, as samples per second.
|
||||
* Undefined if sampleType is OneSamplePerStep.
|
||||
*
|
||||
* If sampleType is VariableSampleRate and this value is
|
||||
* non-zero, then it may be used to calculate a resolution for
|
||||
* the output (i.e. the "duration" of each sample, in time,
|
||||
* will be 1/sampleRate seconds). It's recommended to set
|
||||
* this to zero if that behaviour is not desired.
|
||||
*/
|
||||
float sampleRate;
|
||||
|
||||
/**
|
||||
* True if the returned results for this output are known to
|
||||
* have a duration field.
|
||||
*/
|
||||
bool hasDuration;
|
||||
|
||||
OutputDescriptor() : // defaults for mandatory non-class-type members
|
||||
OutputDescriptor() :
|
||||
hasFixedBinCount(false),
|
||||
binCount(0),
|
||||
hasKnownExtents(false),
|
||||
@ -292,121 +55,69 @@ public:
|
||||
hasDuration(false) { }
|
||||
};
|
||||
|
||||
typedef std::vector<OutputDescriptor> OutputList;
|
||||
|
||||
/**
|
||||
* Get the outputs of this plugin. An output's index in this list
|
||||
* is used as its numeric index when looking it up in the
|
||||
* FeatureSet returned from the process() call.
|
||||
*/
|
||||
virtual OutputList getOutputDescriptors() const = 0;
|
||||
using OutputList = std::vector<OutputDescriptor>;
|
||||
|
||||
struct Feature
|
||||
{
|
||||
/**
|
||||
* True if an output feature has its own timestamp. This is
|
||||
* mandatory if the output has VariableSampleRate, optional if
|
||||
* the output has FixedSampleRate, and unused if the output
|
||||
* has OneSamplePerStep.
|
||||
*/
|
||||
bool hasTimestamp;
|
||||
|
||||
/**
|
||||
* Timestamp of the output feature. This is mandatory if the
|
||||
* output has VariableSampleRate or if the output has
|
||||
* FixedSampleRate and hasTimestamp is true, and unused
|
||||
* otherwise.
|
||||
*/
|
||||
RealTime timestamp;
|
||||
|
||||
/**
|
||||
* True if an output feature has a specified duration. This
|
||||
* is optional if the output has VariableSampleRate or
|
||||
* FixedSampleRate, and and unused if the output has
|
||||
* OneSamplePerStep.
|
||||
*/
|
||||
real_time timestamp;
|
||||
bool hasDuration;
|
||||
|
||||
/**
|
||||
* Duration of the output feature. This is mandatory if the
|
||||
* output has VariableSampleRate or FixedSampleRate and
|
||||
* hasDuration is true, and unused otherwise.
|
||||
*/
|
||||
RealTime duration;
|
||||
|
||||
/**
|
||||
* Results for a single sample of this feature. If the output
|
||||
* hasFixedBinCount, there must be the same number of values
|
||||
* as the output's binCount count.
|
||||
*/
|
||||
real_time duration;
|
||||
std::vector<float> values;
|
||||
|
||||
/**
|
||||
* Label for the sample of this feature.
|
||||
*/
|
||||
std::string label;
|
||||
|
||||
Feature() : // defaults for mandatory non-class-type members
|
||||
hasTimestamp(false), hasDuration(false) { }
|
||||
Feature() : hasTimestamp(false), hasDuration(false) { }
|
||||
};
|
||||
|
||||
typedef std::vector<Feature> FeatureList;
|
||||
using FeatureList = std::vector<Feature>;
|
||||
using FeatureSet = std::map<int, FeatureList>;
|
||||
|
||||
typedef std::map<int, FeatureList> FeatureSet; // key is output no
|
||||
|
||||
/**
|
||||
* Process a single block of input data.
|
||||
*
|
||||
* If the plugin's inputDomain is TimeDomain, inputBuffers will
|
||||
* point to one array of floats per input channel, and each of
|
||||
* these arrays will contain blockSize consecutive audio samples
|
||||
* (the host will zero-pad as necessary). The timestamp in this
|
||||
* case will be the real time in seconds of the start of the
|
||||
* supplied block of samples.
|
||||
*
|
||||
* If the plugin's inputDomain is FrequencyDomain, inputBuffers
|
||||
* will point to one array of floats per input channel, and each
|
||||
* of these arrays will contain blockSize/2+1 consecutive pairs of
|
||||
* real and imaginary component floats corresponding to bins
|
||||
* 0..(blockSize/2) of the FFT output. That is, bin 0 (the first
|
||||
* pair of floats) contains the DC output, up to bin blockSize/2
|
||||
* which contains the Nyquist-frequency output. There will
|
||||
* therefore be blockSize+2 floats per channel in total. The
|
||||
* timestamp will be the real time in seconds of the centre of the
|
||||
* FFT input window (i.e. the very first block passed to process
|
||||
* might contain the FFT of half a block of zero samples and the
|
||||
* first half-block of the actual data, with a timestamp of zero).
|
||||
*
|
||||
* Return any features that have become available after this
|
||||
* process call. (These do not necessarily have to fall within
|
||||
* the process block, except for OneSamplePerStep outputs.)
|
||||
*/
|
||||
virtual FeatureSet process(const float *const *inputBuffers,
|
||||
RealTime timestamp) = 0;
|
||||
|
||||
/**
|
||||
* After all blocks have been processed, calculate and return any
|
||||
* remaining features derived from the complete input.
|
||||
*/
|
||||
virtual OutputList getOutputDescriptors() const = 0;
|
||||
virtual bool initialise(size_t inputChannels, size_t stepSize, size_t blockSize) = 0;
|
||||
virtual void reset() = 0;
|
||||
virtual InputDomain getInputDomain() const = 0;
|
||||
virtual size_t getPreferredBlockSize() const { return 0; }
|
||||
virtual size_t getPreferredStepSize() const { return 0; }
|
||||
virtual size_t getMinChannelCount() const { return 1; }
|
||||
virtual size_t getMaxChannelCount() const { return 1; }
|
||||
virtual FeatureSet process(const float *const *inputBuffers, real_time timestamp) = 0;
|
||||
virtual FeatureSet getRemainingFeatures() = 0;
|
||||
virtual std::string get_type() const { return "Feature Extraction Plugin"; }
|
||||
|
||||
/**
|
||||
* Used to distinguish between Vamp::Plugin and other potential
|
||||
* sibling subclasses of PluginBase. Do not reimplement this
|
||||
* function in your subclass.
|
||||
*/
|
||||
virtual std::string getType() const { return "Feature Extraction Plugin"; }
|
||||
|
||||
/**
|
||||
* Retrieve the input sample rate set on construction.
|
||||
*/
|
||||
float getInputSampleRate() const { return m_inputSampleRate; }
|
||||
|
||||
protected:
|
||||
Plugin(float inputSampleRate) :
|
||||
m_inputSampleRate(inputSampleRate) { }
|
||||
|
||||
float m_inputSampleRate;
|
||||
struct parameter_descriptor
|
||||
{
|
||||
std::string identifier;
|
||||
std::string name;
|
||||
std::string description;
|
||||
std::string unit;
|
||||
float min_value { 0.f };
|
||||
float max_value { 0.f };
|
||||
float default_value { 0.f };
|
||||
bool is_quantized { false };
|
||||
float quantize_step { 0.f };
|
||||
std::vector<std::string> value_names;
|
||||
};
|
||||
|
||||
using parameter_descriptors = std::vector<parameter_descriptor>;
|
||||
using programs = std::vector<std::string>;
|
||||
|
||||
public:
|
||||
virtual std::string get_identifier() const = 0;
|
||||
virtual std::string get_name() const = 0;
|
||||
virtual std::string get_description() const = 0;
|
||||
virtual std::string get_maker() const = 0;
|
||||
virtual float get_parameter(std::string) const { return 0.f; }
|
||||
virtual std::string get_current_program() const { return ""; }
|
||||
virtual parameter_descriptors get_parameter_descriptors() const { return parameter_descriptors(); }
|
||||
virtual programs get_programs() const { return programs(); }
|
||||
|
||||
virtual void set_parameter(std::string, float) { }
|
||||
virtual void select_program(std::string) { }
|
||||
|
||||
protected:
|
||||
plugin(float inputSampleRate) : m_inputSampleRate(inputSampleRate) { }
|
||||
float m_inputSampleRate;
|
||||
};
|
||||
}
|
||||
|
@ -5,16 +5,8 @@
|
||||
|
||||
#include <mutex>
|
||||
|
||||
using std::map;
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::mutex;
|
||||
using std::lock_guard;
|
||||
|
||||
namespace Vamp {
|
||||
|
||||
namespace vamp
|
||||
{
|
||||
class PluginAdapterBase::Impl
|
||||
{
|
||||
public:
|
||||
@ -63,55 +55,44 @@ protected:
|
||||
|
||||
static void vampReleaseFeatureSet(VampFeatureList *fs);
|
||||
|
||||
void checkOutputMap(Plugin *plugin);
|
||||
void markOutputsChanged(Plugin *plugin);
|
||||
void checkOutputMap(plugin* p);
|
||||
void markOutputsChanged(plugin* p);
|
||||
|
||||
void cleanup(Plugin *plugin);
|
||||
unsigned int getOutputCount(Plugin *plugin);
|
||||
VampOutputDescriptor *getOutputDescriptor(Plugin *plugin, unsigned int i);
|
||||
VampFeatureList *process(Plugin *plugin,
|
||||
const float *const *inputBuffers,
|
||||
int sec, int nsec);
|
||||
VampFeatureList *getRemainingFeatures(Plugin *plugin);
|
||||
VampFeatureList *convertFeatures(Plugin *plugin,
|
||||
const Plugin::FeatureSet &features);
|
||||
void cleanup(plugin* p);
|
||||
unsigned int getOutputCount(plugin* p);
|
||||
VampOutputDescriptor *getOutputDescriptor(plugin* p, unsigned int i);
|
||||
VampFeatureList *process(plugin* p, const float *const *inputBuffers, int sec, int nsec);
|
||||
VampFeatureList *getRemainingFeatures(plugin* p);
|
||||
VampFeatureList *convertFeatures(plugin* p, const plugin::FeatureSet &features);
|
||||
|
||||
// maps both plugins and descriptors to adapters
|
||||
typedef map<const void *, Impl *> AdapterMap;
|
||||
typedef std::map<const void *, Impl *> AdapterMap;
|
||||
|
||||
static AdapterMap *m_adapterMap;
|
||||
|
||||
static mutex &adapterMapMutex() {
|
||||
// If this mutex was a global static, then it might be
|
||||
// destroyed before the last adapter, and we would end up
|
||||
// trying to lock an invalid mutex when removing an adapter
|
||||
// from the adapter map. To ensure it outlasts the adapters,
|
||||
// we need to ensure it is constructed before the construction
|
||||
// of any of them is complete, since destruction order is
|
||||
// reverse of construction. So we have to make sure this is
|
||||
// called from the PluginAdapterBase::Impl constructor below.
|
||||
static mutex m;
|
||||
static std::mutex &adapterMapMutex() {
|
||||
static std::mutex m;
|
||||
return m;
|
||||
}
|
||||
|
||||
static Impl *lookupAdapter(VampPluginHandle);
|
||||
|
||||
mutex m_mutex; // guards all of the below
|
||||
std::mutex m_mutex; // guards all of the below
|
||||
|
||||
bool m_populated;
|
||||
VampPluginDescriptor m_descriptor;
|
||||
Plugin::ParameterList m_parameters;
|
||||
Plugin::ProgramList m_programs;
|
||||
plugin::parameter_descriptors m_parameters;
|
||||
plugin::programs m_programs;
|
||||
|
||||
typedef map<Plugin *, Plugin::OutputList *> OutputMap;
|
||||
typedef std::map<plugin *, plugin::OutputList *> OutputMap;
|
||||
OutputMap m_pluginOutputs;
|
||||
|
||||
map<Plugin *, VampFeatureList *> m_fs;
|
||||
map<Plugin *, vector<size_t> > m_fsizes;
|
||||
map<Plugin *, vector<vector<size_t> > > m_fvsizes;
|
||||
void resizeFS(Plugin *plugin, int n);
|
||||
void resizeFL(Plugin *plugin, int n, size_t sz);
|
||||
void resizeFV(Plugin *plugin, int n, int j, size_t sz);
|
||||
std::map<plugin *, VampFeatureList *> m_fs;
|
||||
std::map<plugin *, std::vector<size_t> > m_fsizes;
|
||||
std::map<plugin *, std::vector<std::vector<size_t> > > m_fvsizes;
|
||||
void resizeFS(plugin* p, int n);
|
||||
void resizeFL(plugin* p, int n, size_t sz);
|
||||
void resizeFV(plugin* p, int n, int j, size_t sz);
|
||||
};
|
||||
|
||||
PluginAdapterBase::PluginAdapterBase()
|
||||
@ -134,9 +115,6 @@ PluginAdapterBase::Impl::Impl(PluginAdapterBase *base) :
|
||||
m_base(base),
|
||||
m_populated(false)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl[" << this << "]::Impl" << endl;
|
||||
#endif
|
||||
|
||||
(void)adapterMapMutex(); // see comment in adapterMapMutex function above
|
||||
}
|
||||
@ -144,44 +122,25 @@ PluginAdapterBase::Impl::Impl(PluginAdapterBase *base) :
|
||||
const VampPluginDescriptor *
|
||||
PluginAdapterBase::Impl::getDescriptor()
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl[" << this << "]::getDescriptor" << endl;
|
||||
#endif
|
||||
|
||||
lock_guard<mutex> guard(m_mutex);
|
||||
std::lock_guard<std::mutex> guard(m_mutex);
|
||||
|
||||
if (m_populated) return &m_descriptor;
|
||||
|
||||
Plugin *plugin = m_base->createPlugin(48000);
|
||||
plugin *p = m_base->createPlugin(48000);
|
||||
|
||||
if (!plugin) {
|
||||
cerr << "PluginAdapterBase::Impl::getDescriptor: Failed to create plugin" << endl;
|
||||
if (!p) {
|
||||
std::cerr << "PluginAdapterBase::Impl::getDescriptor: Failed to create plugin" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (plugin->getVampApiVersion() != VAMP_API_VERSION) {
|
||||
cerr << "Vamp::PluginAdapterBase::Impl::getDescriptor: ERROR: "
|
||||
<< "API version " << plugin->getVampApiVersion()
|
||||
<< " for\nplugin \"" << plugin->getIdentifier() << "\" "
|
||||
<< "differs from version "
|
||||
<< VAMP_API_VERSION << " for adapter.\n"
|
||||
<< "This plugin is probably linked against a different version of the Vamp SDK\n"
|
||||
<< "from the version it was compiled with. It will need to be re-linked correctly\n"
|
||||
<< "before it can be used." << endl;
|
||||
delete plugin;
|
||||
return 0;
|
||||
}
|
||||
m_parameters = p->get_parameter_descriptors();
|
||||
m_programs = p->get_programs();
|
||||
|
||||
m_parameters = plugin->getParameterDescriptors();
|
||||
m_programs = plugin->getPrograms();
|
||||
|
||||
m_descriptor.vampApiVersion = plugin->getVampApiVersion();
|
||||
m_descriptor.identifier = strdup(plugin->getIdentifier().c_str());
|
||||
m_descriptor.name = strdup(plugin->getName().c_str());
|
||||
m_descriptor.description = strdup(plugin->getDescription().c_str());
|
||||
m_descriptor.maker = strdup(plugin->getMaker().c_str());
|
||||
m_descriptor.pluginVersion = plugin->getPluginVersion();
|
||||
m_descriptor.copyright = strdup(plugin->getCopyright().c_str());
|
||||
m_descriptor.identifier = strdup(p->get_identifier().c_str());
|
||||
m_descriptor.name = strdup(p->get_name().c_str());
|
||||
m_descriptor.description = strdup(p->get_description().c_str());
|
||||
m_descriptor.maker = strdup(p->get_maker().c_str());
|
||||
|
||||
m_descriptor.parameterCount = m_parameters.size();
|
||||
m_descriptor.parameters = (const VampParameterDescriptor **)
|
||||
@ -196,19 +155,19 @@ PluginAdapterBase::Impl::getDescriptor()
|
||||
desc->name = strdup(m_parameters[i].name.c_str());
|
||||
desc->description = strdup(m_parameters[i].description.c_str());
|
||||
desc->unit = strdup(m_parameters[i].unit.c_str());
|
||||
desc->minValue = m_parameters[i].minValue;
|
||||
desc->maxValue = m_parameters[i].maxValue;
|
||||
desc->defaultValue = m_parameters[i].defaultValue;
|
||||
desc->isQuantized = m_parameters[i].isQuantized;
|
||||
desc->quantizeStep = m_parameters[i].quantizeStep;
|
||||
desc->minValue = m_parameters[i].min_value;
|
||||
desc->maxValue = m_parameters[i].max_value;
|
||||
desc->defaultValue = m_parameters[i].default_value;
|
||||
desc->isQuantized = m_parameters[i].is_quantized;
|
||||
desc->quantizeStep = m_parameters[i].quantize_step;
|
||||
desc->valueNames = 0;
|
||||
if (desc->isQuantized && !m_parameters[i].valueNames.empty()) {
|
||||
if (desc->isQuantized && !m_parameters[i].value_names.empty()) {
|
||||
desc->valueNames = (const char **)
|
||||
malloc((m_parameters[i].valueNames.size()+1) * sizeof(char *));
|
||||
for (unsigned int j = 0; j < m_parameters[i].valueNames.size(); ++j) {
|
||||
desc->valueNames[j] = strdup(m_parameters[i].valueNames[j].c_str());
|
||||
malloc((m_parameters[i].value_names.size()+1) * sizeof(char *));
|
||||
for (unsigned int j = 0; j < m_parameters[i].value_names.size(); ++j) {
|
||||
desc->valueNames[j] = strdup(m_parameters[i].value_names[j].c_str());
|
||||
}
|
||||
desc->valueNames[m_parameters[i].valueNames.size()] = 0;
|
||||
desc->valueNames[m_parameters[i].value_names.size()] = 0;
|
||||
}
|
||||
m_descriptor.parameters[i] = desc;
|
||||
}
|
||||
@ -221,7 +180,7 @@ PluginAdapterBase::Impl::getDescriptor()
|
||||
m_descriptor.programs[i] = strdup(m_programs[i].c_str());
|
||||
}
|
||||
|
||||
if (plugin->getInputDomain() == Plugin::FrequencyDomain) {
|
||||
if (p->getInputDomain() == plugin::FrequencyDomain) {
|
||||
m_descriptor.inputDomain = vampFrequencyDomain;
|
||||
} else {
|
||||
m_descriptor.inputDomain = vampTimeDomain;
|
||||
@ -246,14 +205,14 @@ PluginAdapterBase::Impl::getDescriptor()
|
||||
m_descriptor.getRemainingFeatures = vampGetRemainingFeatures;
|
||||
m_descriptor.releaseFeatureSet = vampReleaseFeatureSet;
|
||||
|
||||
lock_guard<mutex> adapterMapGuard(adapterMapMutex());
|
||||
std::lock_guard<std::mutex> adapterMapGuard(adapterMapMutex());
|
||||
|
||||
if (!m_adapterMap) {
|
||||
m_adapterMap = new AdapterMap;
|
||||
}
|
||||
(*m_adapterMap)[&m_descriptor] = this;
|
||||
|
||||
delete plugin;
|
||||
delete p;
|
||||
|
||||
m_populated = true;
|
||||
return &m_descriptor;
|
||||
@ -261,11 +220,7 @@ PluginAdapterBase::Impl::getDescriptor()
|
||||
|
||||
PluginAdapterBase::Impl::~Impl()
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl[" << this << "]::~Impl" << endl;
|
||||
#endif
|
||||
|
||||
lock_guard<mutex> guard(m_mutex);
|
||||
std::lock_guard<std::mutex> guard(m_mutex);
|
||||
|
||||
if (!m_populated) return;
|
||||
|
||||
@ -296,7 +251,7 @@ PluginAdapterBase::Impl::~Impl()
|
||||
}
|
||||
free((void *)m_descriptor.programs);
|
||||
|
||||
lock_guard<mutex> adapterMapGuard(adapterMapMutex());
|
||||
std::lock_guard<std::mutex> adapterMapGuard(adapterMapMutex());
|
||||
|
||||
if (m_adapterMap) {
|
||||
|
||||
@ -312,11 +267,7 @@ PluginAdapterBase::Impl::~Impl()
|
||||
PluginAdapterBase::Impl *
|
||||
PluginAdapterBase::Impl::lookupAdapter(VampPluginHandle handle)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::lookupAdapter(" << handle << ")" << endl;
|
||||
#endif
|
||||
|
||||
lock_guard<mutex> adapterMapGuard(adapterMapMutex());
|
||||
std::lock_guard<std::mutex> adapterMapGuard(adapterMapMutex());
|
||||
|
||||
if (!m_adapterMap) return 0;
|
||||
AdapterMap::const_iterator i = m_adapterMap->find(handle);
|
||||
@ -328,49 +279,37 @@ VampPluginHandle
|
||||
PluginAdapterBase::Impl::vampInstantiate(const VampPluginDescriptor *desc,
|
||||
float inputSampleRate)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << ")" << endl;
|
||||
#endif
|
||||
|
||||
lock_guard<mutex> adapterMapGuard(adapterMapMutex());
|
||||
std::lock_guard<std::mutex> adapterMapGuard(adapterMapMutex());
|
||||
|
||||
if (!m_adapterMap) {
|
||||
m_adapterMap = new AdapterMap();
|
||||
}
|
||||
|
||||
if (m_adapterMap->find(desc) == m_adapterMap->end()) {
|
||||
cerr << "WARNING: PluginAdapterBase::Impl::vampInstantiate: Descriptor " << desc << " not in adapter map" << endl;
|
||||
std::cerr << "WARNING: PluginAdapterBase::Impl::vampInstantiate: Descriptor " << desc << " not in adapter map" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Impl *adapter = (*m_adapterMap)[desc];
|
||||
if (desc != &adapter->m_descriptor) return 0;
|
||||
|
||||
Plugin *plugin = adapter->m_base->createPlugin(inputSampleRate);
|
||||
if (plugin) {
|
||||
(*m_adapterMap)[plugin] = adapter;
|
||||
plugin* p = adapter->m_base->createPlugin(inputSampleRate);
|
||||
if (p) {
|
||||
(*m_adapterMap)[p] = adapter;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << "): returning handle " << plugin << endl;
|
||||
#endif
|
||||
|
||||
return plugin;
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
PluginAdapterBase::Impl::vampCleanup(VampPluginHandle handle)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::vampCleanup(" << handle << ")" << endl;
|
||||
#endif
|
||||
|
||||
Impl *adapter = lookupAdapter(handle);
|
||||
if (!adapter) {
|
||||
delete ((Plugin *)handle);
|
||||
delete ((plugin*)handle);
|
||||
return;
|
||||
}
|
||||
adapter->cleanup(((Plugin *)handle));
|
||||
adapter->cleanup(((plugin*)handle));
|
||||
}
|
||||
|
||||
int
|
||||
@ -379,67 +318,48 @@ PluginAdapterBase::Impl::vampInitialise(VampPluginHandle handle,
|
||||
unsigned int stepSize,
|
||||
unsigned int blockSize)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::vampInitialise(" << handle << ", " << channels << ", " << stepSize << ", " << blockSize << ")" << endl;
|
||||
#endif
|
||||
|
||||
Impl *adapter = lookupAdapter(handle);
|
||||
if (!adapter) return 0;
|
||||
bool result = ((Plugin *)handle)->initialise(channels, stepSize, blockSize);
|
||||
adapter->markOutputsChanged((Plugin *)handle);
|
||||
bool result = ((plugin*)handle)->initialise(channels, stepSize, blockSize);
|
||||
adapter->markOutputsChanged((plugin*)handle);
|
||||
return result ? 1 : 0;
|
||||
}
|
||||
|
||||
void
|
||||
PluginAdapterBase::Impl::vampReset(VampPluginHandle handle)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::vampReset(" << handle << ")" << endl;
|
||||
#endif
|
||||
|
||||
((Plugin *)handle)->reset();
|
||||
((plugin *)handle)->reset();
|
||||
}
|
||||
|
||||
float
|
||||
PluginAdapterBase::Impl::vampGetParameter(VampPluginHandle handle,
|
||||
int param)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::vampGetParameter(" << handle << ", " << param << ")" << endl;
|
||||
#endif
|
||||
|
||||
Impl *adapter = lookupAdapter(handle);
|
||||
if (!adapter) return 0.0;
|
||||
Plugin::ParameterList &list = adapter->m_parameters;
|
||||
return ((Plugin *)handle)->getParameter(list[param].identifier);
|
||||
plugin::parameter_descriptors &list = adapter->m_parameters;
|
||||
return ((plugin *)handle)->get_parameter(list[param].identifier);
|
||||
}
|
||||
|
||||
void
|
||||
PluginAdapterBase::Impl::vampSetParameter(VampPluginHandle handle,
|
||||
int param, float value)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::vampSetParameter(" << handle << ", " << param << ", " << value << ")" << endl;
|
||||
#endif
|
||||
|
||||
Impl *adapter = lookupAdapter(handle);
|
||||
if (!adapter) return;
|
||||
Plugin::ParameterList &list = adapter->m_parameters;
|
||||
((Plugin *)handle)->setParameter(list[param].identifier, value);
|
||||
adapter->markOutputsChanged((Plugin *)handle);
|
||||
plugin::parameter_descriptors &list = adapter->m_parameters;
|
||||
((plugin *)handle)->set_parameter(list[param].identifier, value);
|
||||
adapter->markOutputsChanged((plugin *)handle);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
PluginAdapterBase::Impl::vampGetCurrentProgram(VampPluginHandle handle)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::vampGetCurrentProgram(" << handle << ")" << endl;
|
||||
#endif
|
||||
|
||||
Impl *adapter = lookupAdapter(handle);
|
||||
if (!adapter) return 0;
|
||||
Plugin::ProgramList &list = adapter->m_programs;
|
||||
string program = ((Plugin *)handle)->getCurrentProgram();
|
||||
plugin::programs &list = adapter->m_programs;
|
||||
std::string program = ((plugin *)handle)->get_current_program();
|
||||
for (unsigned int i = 0; i < list.size(); ++i) {
|
||||
if (list[i] == program) return i;
|
||||
}
|
||||
@ -457,90 +377,57 @@ PluginAdapterBase::Impl::vampSelectProgram(VampPluginHandle handle,
|
||||
Impl *adapter = lookupAdapter(handle);
|
||||
if (!adapter) return;
|
||||
|
||||
Plugin::ProgramList &list = adapter->m_programs;
|
||||
((Plugin *)handle)->selectProgram(list[program]);
|
||||
plugin::programs &list = adapter->m_programs;
|
||||
((plugin *)handle)->select_program(list[program]);
|
||||
|
||||
adapter->markOutputsChanged((Plugin *)handle);
|
||||
adapter->markOutputsChanged((plugin *)handle);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
PluginAdapterBase::Impl::vampGetPreferredStepSize(VampPluginHandle handle)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::vampGetPreferredStepSize(" << handle << ")" << endl;
|
||||
#endif
|
||||
|
||||
return ((Plugin *)handle)->getPreferredStepSize();
|
||||
return ((plugin *)handle)->getPreferredStepSize();
|
||||
}
|
||||
|
||||
unsigned int
|
||||
PluginAdapterBase::Impl::vampGetPreferredBlockSize(VampPluginHandle handle)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::vampGetPreferredBlockSize(" << handle << ")" << endl;
|
||||
#endif
|
||||
|
||||
return ((Plugin *)handle)->getPreferredBlockSize();
|
||||
return ((plugin *)handle)->getPreferredBlockSize();
|
||||
}
|
||||
|
||||
unsigned int
|
||||
PluginAdapterBase::Impl::vampGetMinChannelCount(VampPluginHandle handle)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::vampGetMinChannelCount(" << handle << ")" << endl;
|
||||
#endif
|
||||
|
||||
return ((Plugin *)handle)->getMinChannelCount();
|
||||
return ((plugin *)handle)->getMinChannelCount();
|
||||
}
|
||||
|
||||
unsigned int
|
||||
PluginAdapterBase::Impl::vampGetMaxChannelCount(VampPluginHandle handle)
|
||||
unsigned int PluginAdapterBase::Impl::vampGetMaxChannelCount(VampPluginHandle handle)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::vampGetMaxChannelCount(" << handle << ")" << endl;
|
||||
#endif
|
||||
|
||||
return ((Plugin *)handle)->getMaxChannelCount();
|
||||
return ((plugin *)handle)->getMaxChannelCount();
|
||||
}
|
||||
|
||||
unsigned int
|
||||
PluginAdapterBase::Impl::vampGetOutputCount(VampPluginHandle handle)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::vampGetOutputCount(" << handle << ")" << endl;
|
||||
#endif
|
||||
|
||||
Impl *adapter = lookupAdapter(handle);
|
||||
|
||||
// cerr << "vampGetOutputCount: handle " << handle << " -> adapter "<< adapter << endl;
|
||||
|
||||
if (!adapter) return 0;
|
||||
return adapter->getOutputCount((Plugin *)handle);
|
||||
return adapter->getOutputCount((plugin *)handle);
|
||||
}
|
||||
|
||||
VampOutputDescriptor *
|
||||
PluginAdapterBase::Impl::vampGetOutputDescriptor(VampPluginHandle handle,
|
||||
unsigned int i)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::vampGetOutputDescriptor(" << handle << ", " << i << ")" << endl;
|
||||
#endif
|
||||
|
||||
Impl *adapter = lookupAdapter(handle);
|
||||
|
||||
// cerr << "vampGetOutputDescriptor: handle " << handle << " -> adapter "<< adapter << endl;
|
||||
|
||||
if (!adapter) return 0;
|
||||
return adapter->getOutputDescriptor((Plugin *)handle, i);
|
||||
return adapter->getOutputDescriptor((plugin *)handle, i);
|
||||
}
|
||||
|
||||
void
|
||||
PluginAdapterBase::Impl::vampReleaseOutputDescriptor(VampOutputDescriptor *desc)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::vampReleaseOutputDescriptor(" << desc << ")" << endl;
|
||||
#endif
|
||||
|
||||
if (desc->identifier) free((void *)desc->identifier);
|
||||
if (desc->name) free((void *)desc->name);
|
||||
if (desc->description) free((void *)desc->description);
|
||||
@ -556,60 +443,44 @@ PluginAdapterBase::Impl::vampReleaseOutputDescriptor(VampOutputDescriptor *desc)
|
||||
free((void *)desc);
|
||||
}
|
||||
|
||||
VampFeatureList *
|
||||
PluginAdapterBase::Impl::vampProcess(VampPluginHandle handle,
|
||||
VampFeatureList * PluginAdapterBase::Impl::vampProcess(VampPluginHandle handle,
|
||||
const float *const *inputBuffers,
|
||||
int sec,
|
||||
int nsec)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::vampProcess(" << handle << ", " << sec << ", " << nsec << ")" << endl;
|
||||
#endif
|
||||
|
||||
Impl *adapter = lookupAdapter(handle);
|
||||
if (!adapter) return 0;
|
||||
return adapter->process((Plugin *)handle, inputBuffers, sec, nsec);
|
||||
return adapter->process((plugin *)handle, inputBuffers, sec, nsec);
|
||||
}
|
||||
|
||||
VampFeatureList *
|
||||
PluginAdapterBase::Impl::vampGetRemainingFeatures(VampPluginHandle handle)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::vampGetRemainingFeatures(" << handle << ")" << endl;
|
||||
#endif
|
||||
|
||||
Impl *adapter = lookupAdapter(handle);
|
||||
if (!adapter) return 0;
|
||||
return adapter->getRemainingFeatures((Plugin *)handle);
|
||||
return adapter->getRemainingFeatures((plugin *)handle);
|
||||
}
|
||||
|
||||
void
|
||||
PluginAdapterBase::Impl::vampReleaseFeatureSet(VampFeatureList *)
|
||||
{
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::vampReleaseFeatureSet" << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
PluginAdapterBase::Impl::cleanup(Plugin *plugin)
|
||||
PluginAdapterBase::Impl::cleanup(plugin* p)
|
||||
{
|
||||
// at this point no mutex is held
|
||||
|
||||
lock_guard<mutex> adapterMapGuard(adapterMapMutex());
|
||||
lock_guard<mutex> guard(m_mutex);
|
||||
std::lock_guard<std::mutex> adapterMapGuard(adapterMapMutex());
|
||||
std::lock_guard<std::mutex> guard(m_mutex);
|
||||
|
||||
if (m_fs.find(plugin) != m_fs.end()) {
|
||||
if (m_fs.find(p) != m_fs.end()) {
|
||||
size_t outputCount = 0;
|
||||
if (m_pluginOutputs[plugin]) {
|
||||
outputCount = m_pluginOutputs[plugin]->size();
|
||||
if (m_pluginOutputs[p]) {
|
||||
outputCount = m_pluginOutputs[p]->size();
|
||||
}
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::cleanup: " << outputCount << " output(s)" << endl;
|
||||
#endif
|
||||
VampFeatureList *list = m_fs[plugin];
|
||||
VampFeatureList *list = m_fs[p];
|
||||
for (unsigned int i = 0; i < outputCount; ++i) {
|
||||
for (unsigned int j = 0; j < m_fsizes[plugin][i]; ++j) {
|
||||
for (unsigned int j = 0; j < m_fsizes[p][i]; ++j) {
|
||||
if (list[i].features[j].v1.label) {
|
||||
free(list[i].features[j].v1.label);
|
||||
}
|
||||
@ -620,18 +491,18 @@ PluginAdapterBase::Impl::cleanup(Plugin *plugin)
|
||||
if (list[i].features) free(list[i].features);
|
||||
}
|
||||
if (list) free((void *)list);
|
||||
m_fs.erase(plugin);
|
||||
m_fsizes.erase(plugin);
|
||||
m_fvsizes.erase(plugin);
|
||||
m_fs.erase(p);
|
||||
m_fsizes.erase(p);
|
||||
m_fvsizes.erase(p);
|
||||
}
|
||||
|
||||
if (m_pluginOutputs.find(plugin) != m_pluginOutputs.end()) {
|
||||
delete m_pluginOutputs[plugin];
|
||||
m_pluginOutputs.erase(plugin);
|
||||
if (m_pluginOutputs.find(p) != m_pluginOutputs.end()) {
|
||||
delete m_pluginOutputs[p];
|
||||
m_pluginOutputs.erase(p);
|
||||
}
|
||||
|
||||
if (m_adapterMap) {
|
||||
m_adapterMap->erase(plugin);
|
||||
m_adapterMap->erase(p);
|
||||
|
||||
if (m_adapterMap->empty()) {
|
||||
delete m_adapterMap;
|
||||
@ -639,62 +510,55 @@ PluginAdapterBase::Impl::cleanup(Plugin *plugin)
|
||||
}
|
||||
}
|
||||
|
||||
delete ((Plugin *)plugin);
|
||||
delete ((plugin *)p);
|
||||
}
|
||||
|
||||
void
|
||||
PluginAdapterBase::Impl::checkOutputMap(Plugin *plugin)
|
||||
PluginAdapterBase::Impl::checkOutputMap(plugin* p)
|
||||
{
|
||||
// must be called with m_mutex held
|
||||
|
||||
OutputMap::iterator i = m_pluginOutputs.find(plugin);
|
||||
OutputMap::iterator i = m_pluginOutputs.find(p);
|
||||
|
||||
if (i == m_pluginOutputs.end() || !i->second) {
|
||||
|
||||
m_pluginOutputs[plugin] = new Plugin::OutputList
|
||||
(plugin->getOutputDescriptors());
|
||||
|
||||
// cerr << "PluginAdapterBase::Impl::checkOutputMap: Have " << m_pluginOutputs[plugin]->size() << " outputs for plugin " << plugin->getIdentifier() << endl;
|
||||
m_pluginOutputs[p] = new plugin::OutputList(p->getOutputDescriptors());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginAdapterBase::Impl::markOutputsChanged(Plugin *plugin)
|
||||
PluginAdapterBase::Impl::markOutputsChanged(plugin* p)
|
||||
{
|
||||
lock_guard<mutex> guard(m_mutex);
|
||||
std::lock_guard<std::mutex> guard(m_mutex);
|
||||
|
||||
OutputMap::iterator i = m_pluginOutputs.find(plugin);
|
||||
|
||||
// cerr << "PluginAdapterBase::Impl::markOutputsChanged" << endl;
|
||||
OutputMap::iterator i = m_pluginOutputs.find(p);
|
||||
|
||||
if (i != m_pluginOutputs.end()) {
|
||||
|
||||
Plugin::OutputList *list = i->second;
|
||||
plugin::OutputList *list = i->second;
|
||||
m_pluginOutputs.erase(i);
|
||||
delete list;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
PluginAdapterBase::Impl::getOutputCount(Plugin *plugin)
|
||||
PluginAdapterBase::Impl::getOutputCount(plugin* p)
|
||||
{
|
||||
lock_guard<mutex> guard(m_mutex);
|
||||
std::lock_guard<std::mutex> guard(m_mutex);
|
||||
|
||||
checkOutputMap(plugin);
|
||||
checkOutputMap(p);
|
||||
|
||||
return m_pluginOutputs[plugin]->size();
|
||||
return m_pluginOutputs[p]->size();
|
||||
}
|
||||
|
||||
VampOutputDescriptor *
|
||||
PluginAdapterBase::Impl::getOutputDescriptor(Plugin *plugin,
|
||||
unsigned int i)
|
||||
PluginAdapterBase::Impl::getOutputDescriptor(plugin* p, unsigned int i)
|
||||
{
|
||||
lock_guard<mutex> guard(m_mutex);
|
||||
std::lock_guard<std::mutex> guard(m_mutex);
|
||||
|
||||
checkOutputMap(plugin);
|
||||
checkOutputMap(p);
|
||||
|
||||
Plugin::OutputDescriptor &od =
|
||||
(*m_pluginOutputs[plugin])[i];
|
||||
plugin::OutputDescriptor &od = (*m_pluginOutputs[p])[i];
|
||||
|
||||
VampOutputDescriptor *desc = (VampOutputDescriptor *)
|
||||
malloc(sizeof(VampOutputDescriptor));
|
||||
@ -706,12 +570,8 @@ PluginAdapterBase::Impl::getOutputDescriptor(Plugin *plugin,
|
||||
desc->hasFixedBinCount = od.hasFixedBinCount;
|
||||
desc->binCount = od.binCount;
|
||||
|
||||
if (od.hasFixedBinCount && od.binCount > 0
|
||||
// We would like to do "&& !od.binNames.empty()" here -- but we
|
||||
// can't, because it will crash older versions of the host adapter
|
||||
// which try to copy the names across whenever the bin count is
|
||||
// non-zero, regardless of whether they exist or not
|
||||
) {
|
||||
if (od.hasFixedBinCount && od.binCount > 0)
|
||||
{
|
||||
desc->binNames = (const char **)
|
||||
malloc(od.binCount * sizeof(const char *));
|
||||
|
||||
@ -733,11 +593,11 @@ PluginAdapterBase::Impl::getOutputDescriptor(Plugin *plugin,
|
||||
desc->quantizeStep = od.quantizeStep;
|
||||
|
||||
switch (od.sampleType) {
|
||||
case Plugin::OutputDescriptor::OneSamplePerStep:
|
||||
case plugin::OutputDescriptor::OneSamplePerStep:
|
||||
desc->sampleType = vampOneSamplePerStep; break;
|
||||
case Plugin::OutputDescriptor::FixedSampleRate:
|
||||
case plugin::OutputDescriptor::FixedSampleRate:
|
||||
desc->sampleType = vampFixedSampleRate; break;
|
||||
case Plugin::OutputDescriptor::VariableSampleRate:
|
||||
case plugin::OutputDescriptor::VariableSampleRate:
|
||||
desc->sampleType = vampVariableSampleRate; break;
|
||||
}
|
||||
|
||||
@ -748,18 +608,18 @@ PluginAdapterBase::Impl::getOutputDescriptor(Plugin *plugin,
|
||||
}
|
||||
|
||||
VampFeatureList *
|
||||
PluginAdapterBase::Impl::process(Plugin *plugin,
|
||||
PluginAdapterBase::Impl::process(plugin *plugin,
|
||||
const float *const *inputBuffers,
|
||||
int sec, int nsec)
|
||||
{
|
||||
// cerr << "PluginAdapterBase::Impl::process" << endl;
|
||||
|
||||
RealTime rt(sec, nsec);
|
||||
real_time rt(sec, nsec);
|
||||
|
||||
// We don't want to hold the mutex during the actual process call,
|
||||
// only while looking up the associated metadata
|
||||
{
|
||||
lock_guard<mutex> guard(m_mutex);
|
||||
std::lock_guard<std::mutex> guard(m_mutex);
|
||||
checkOutputMap(plugin);
|
||||
}
|
||||
|
||||
@ -767,37 +627,32 @@ PluginAdapterBase::Impl::process(Plugin *plugin,
|
||||
}
|
||||
|
||||
VampFeatureList *
|
||||
PluginAdapterBase::Impl::getRemainingFeatures(Plugin *plugin)
|
||||
PluginAdapterBase::Impl::getRemainingFeatures(plugin* p)
|
||||
{
|
||||
// cerr << "PluginAdapterBase::Impl::getRemainingFeatures" << endl;
|
||||
|
||||
// We don't want to hold the mutex during the actual call, only
|
||||
// while looking up the associated metadata
|
||||
{
|
||||
lock_guard<mutex> guard(m_mutex);
|
||||
checkOutputMap(plugin);
|
||||
std::lock_guard<std::mutex> guard(m_mutex);
|
||||
checkOutputMap(p);
|
||||
}
|
||||
|
||||
return convertFeatures(plugin, plugin->getRemainingFeatures());
|
||||
return convertFeatures(p, p->getRemainingFeatures());
|
||||
}
|
||||
|
||||
VampFeatureList *
|
||||
PluginAdapterBase::Impl::convertFeatures(Plugin *plugin,
|
||||
const Plugin::FeatureSet &features)
|
||||
PluginAdapterBase::Impl::convertFeatures(plugin* p, const plugin::FeatureSet &features)
|
||||
{
|
||||
lock_guard<mutex> guard(m_mutex);
|
||||
std::lock_guard<std::mutex> guard(m_mutex);
|
||||
|
||||
int lastN = -1;
|
||||
|
||||
int outputCount = 0;
|
||||
if (m_pluginOutputs[plugin]) outputCount = m_pluginOutputs[plugin]->size();
|
||||
if (m_pluginOutputs[p]) outputCount = m_pluginOutputs[p]->size();
|
||||
|
||||
resizeFS(plugin, outputCount);
|
||||
VampFeatureList *fs = m_fs[plugin];
|
||||
resizeFS(p, outputCount);
|
||||
VampFeatureList *fs = m_fs[p];
|
||||
|
||||
// cerr << "PluginAdapter(v2)::convertFeatures: NOTE: sizeof(Feature) == " << sizeof(Plugin::Feature) << ", sizeof(VampFeature) == " << sizeof(VampFeature) << ", sizeof(VampFeatureList) == " << sizeof(VampFeatureList) << endl;
|
||||
|
||||
for (Plugin::FeatureSet::const_iterator fi = features.begin();
|
||||
for (plugin::FeatureSet::const_iterator fi = features.begin();
|
||||
fi != features.end(); ++fi) {
|
||||
|
||||
int n = fi->first;
|
||||
@ -805,7 +660,7 @@ PluginAdapterBase::Impl::convertFeatures(Plugin *plugin,
|
||||
// cerr << "PluginAdapterBase::Impl::convertFeatures: n = " << n << endl;
|
||||
|
||||
if (n >= int(outputCount)) {
|
||||
cerr << "WARNING: PluginAdapterBase::Impl::convertFeatures: Too many outputs from plugin (" << n+1 << ", only should be " << outputCount << ")" << endl;
|
||||
std::cerr << "WARNING: PluginAdapterBase::Impl::convertFeatures: Too many outputs from plugin (" << n+1 << ", only should be " << outputCount << ")" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -815,10 +670,10 @@ PluginAdapterBase::Impl::convertFeatures(Plugin *plugin,
|
||||
}
|
||||
}
|
||||
|
||||
const Plugin::FeatureList &fl = fi->second;
|
||||
const plugin::FeatureList &fl = fi->second;
|
||||
|
||||
size_t sz = fl.size();
|
||||
if (sz > m_fsizes[plugin][n]) resizeFL(plugin, n, sz);
|
||||
if (sz > m_fsizes[p][n]) resizeFL(p, n, sz);
|
||||
fs[n].featureCount = sz;
|
||||
|
||||
for (size_t j = 0; j < sz; ++j) {
|
||||
@ -846,8 +701,8 @@ PluginAdapterBase::Impl::convertFeatures(Plugin *plugin,
|
||||
feature->label = strdup(fl[j].label.c_str());
|
||||
}
|
||||
|
||||
if (feature->valueCount > m_fvsizes[plugin][n][j]) {
|
||||
resizeFV(plugin, n, j, feature->valueCount);
|
||||
if (feature->valueCount > m_fvsizes[p][n][j]) {
|
||||
resizeFV(p, n, j, feature->valueCount);
|
||||
}
|
||||
|
||||
for (unsigned int k = 0; k < feature->valueCount; ++k) {
|
||||
@ -867,98 +722,61 @@ PluginAdapterBase::Impl::convertFeatures(Plugin *plugin,
|
||||
}
|
||||
}
|
||||
|
||||
// cerr << "PluginAdapter(v2)::convertFeatures: NOTE: have " << outputCount << " outputs" << endl;
|
||||
// for (int i = 0; i < outputCount; ++i) {
|
||||
// cerr << "PluginAdapter(v2)::convertFeatures: NOTE: output " << i << " has " << fs[i].featureCount << " features" << endl;
|
||||
// }
|
||||
|
||||
|
||||
return fs;
|
||||
}
|
||||
|
||||
void
|
||||
PluginAdapterBase::Impl::resizeFS(Plugin *plugin, int n)
|
||||
PluginAdapterBase::Impl::resizeFS(plugin* p, int n)
|
||||
{
|
||||
// called with m_mutex held
|
||||
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::resizeFS(" << plugin << ", " << n << ")" << endl;
|
||||
#endif
|
||||
|
||||
int i = m_fsizes[plugin].size();
|
||||
int i = m_fsizes[p].size();
|
||||
if (i >= n) return;
|
||||
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "resizing from " << i << endl;
|
||||
#endif
|
||||
|
||||
m_fs[plugin] = (VampFeatureList *)realloc
|
||||
(m_fs[plugin], n * sizeof(VampFeatureList));
|
||||
m_fs[p] = (VampFeatureList *)realloc
|
||||
(m_fs[p], n * sizeof(VampFeatureList));
|
||||
|
||||
while (i < n) {
|
||||
m_fs[plugin][i].featureCount = 0;
|
||||
m_fs[plugin][i].features = 0;
|
||||
m_fsizes[plugin].push_back(0);
|
||||
m_fvsizes[plugin].push_back(vector<size_t>());
|
||||
m_fs[p][i].featureCount = 0;
|
||||
m_fs[p][i].features = 0;
|
||||
m_fsizes[p].push_back(0);
|
||||
m_fvsizes[p].push_back(std::vector<size_t>());
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginAdapterBase::Impl::resizeFL(Plugin *plugin, int n, size_t sz)
|
||||
PluginAdapterBase::Impl::resizeFL(plugin* p, int n, size_t sz)
|
||||
{
|
||||
// called with m_mutex held
|
||||
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::resizeFL(" << plugin << ", " << n << ", "
|
||||
<< sz << ")" << endl;
|
||||
#endif
|
||||
|
||||
size_t i = m_fsizes[plugin][n];
|
||||
size_t i = m_fsizes[p][n];
|
||||
if (i >= sz) return;
|
||||
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "resizing from " << i << endl;
|
||||
#endif
|
||||
m_fs[p][n].features = (VampFeatureUnion *)realloc
|
||||
(m_fs[p][n].features, 2 * sz * sizeof(VampFeatureUnion));
|
||||
|
||||
m_fs[plugin][n].features = (VampFeatureUnion *)realloc
|
||||
(m_fs[plugin][n].features, 2 * sz * sizeof(VampFeatureUnion));
|
||||
|
||||
while (m_fsizes[plugin][n] < sz) {
|
||||
m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.hasTimestamp = 0;
|
||||
m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.valueCount = 0;
|
||||
m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.values = 0;
|
||||
m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.label = 0;
|
||||
m_fs[plugin][n].features[m_fsizes[plugin][n] + sz].v2.hasDuration = 0;
|
||||
m_fvsizes[plugin][n].push_back(0);
|
||||
m_fsizes[plugin][n]++;
|
||||
while (m_fsizes[p][n] < sz) {
|
||||
m_fs[p][n].features[m_fsizes[p][n]].v1.hasTimestamp = 0;
|
||||
m_fs[p][n].features[m_fsizes[p][n]].v1.valueCount = 0;
|
||||
m_fs[p][n].features[m_fsizes[p][n]].v1.values = 0;
|
||||
m_fs[p][n].features[m_fsizes[p][n]].v1.label = 0;
|
||||
m_fs[p][n].features[m_fsizes[p][n] + sz].v2.hasDuration = 0;
|
||||
m_fvsizes[p][n].push_back(0);
|
||||
m_fsizes[p][n]++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginAdapterBase::Impl::resizeFV(Plugin *plugin, int n, int j, size_t sz)
|
||||
PluginAdapterBase::Impl::resizeFV(plugin* p, int n, int j, size_t sz)
|
||||
{
|
||||
// called with m_mutex held
|
||||
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "PluginAdapterBase::Impl::resizeFV(" << plugin << ", " << n << ", "
|
||||
<< j << ", " << sz << ")" << endl;
|
||||
#endif
|
||||
|
||||
size_t i = m_fvsizes[plugin][n][j];
|
||||
size_t i = m_fvsizes[p][n][j];
|
||||
if (i >= sz) return;
|
||||
|
||||
#ifdef DEBUG_PLUGIN_ADAPTER
|
||||
cerr << "resizing from " << i << endl;
|
||||
#endif
|
||||
m_fs[p][n].features[j].v1.values = (float *)realloc
|
||||
(m_fs[p][n].features[j].v1.values, sz * sizeof(float));
|
||||
|
||||
m_fs[plugin][n].features[j].v1.values = (float *)realloc
|
||||
(m_fs[plugin][n].features[j].v1.values, sz * sizeof(float));
|
||||
|
||||
m_fvsizes[plugin][n][j] = sz;
|
||||
m_fvsizes[p][n][j] = sz;
|
||||
}
|
||||
|
||||
PluginAdapterBase::Impl::AdapterMap *
|
||||
PluginAdapterBase::Impl::m_adapterMap = 0;
|
||||
|
||||
}
|
||||
|
@ -1,57 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include "vamp.h"
|
||||
|
||||
#include "vamp-sdk/Plugin.h"
|
||||
|
||||
namespace Vamp {
|
||||
|
||||
/**
|
||||
* \class PluginAdapterBase PluginAdapter.h <vamp-sdk/PluginAdapter.h>
|
||||
*
|
||||
* PluginAdapter and PluginAdapterBase provide a wrapper class that a
|
||||
* plugin library can use to make its C++ Vamp::Plugin objects
|
||||
* available through the Vamp C API.
|
||||
*
|
||||
* Almost all Vamp plugin libraries will want to make use of this. To
|
||||
* do so, all they need to do is declare a PluginAdapter<T> for each
|
||||
* plugin class T in their library. It's very simple, and you need to
|
||||
* know absolutely nothing about how it works in order to use it.
|
||||
* Just cut and paste from an existing plugin's discovery function.
|
||||
* \see vampGetPluginDescriptor
|
||||
*/
|
||||
|
||||
namespace vamp
|
||||
{
|
||||
class PluginAdapterBase
|
||||
{
|
||||
public:
|
||||
virtual ~PluginAdapterBase();
|
||||
|
||||
/**
|
||||
* Return a VampPluginDescriptor describing the plugin that is
|
||||
* wrapped by this adapter.
|
||||
*/
|
||||
const VampPluginDescriptor *getDescriptor();
|
||||
|
||||
protected:
|
||||
PluginAdapterBase();
|
||||
|
||||
virtual Plugin *createPlugin(float inputSampleRate) = 0;
|
||||
virtual plugin* createPlugin(float inputSampleRate) = 0;
|
||||
|
||||
class Impl;
|
||||
Impl* m_impl;
|
||||
};
|
||||
|
||||
/**
|
||||
* \class PluginAdapter PluginAdapter.h <vamp-sdk/PluginAdapter.h>
|
||||
*
|
||||
* PluginAdapter turns a PluginAdapterBase into a specific wrapper for
|
||||
* a particular plugin implementation.
|
||||
*
|
||||
* See PluginAdapterBase.
|
||||
*/
|
||||
|
||||
template <typename P>
|
||||
template <typename Plugin>
|
||||
class PluginAdapter : public PluginAdapterBase
|
||||
{
|
||||
public:
|
||||
@ -59,18 +28,17 @@ public:
|
||||
virtual ~PluginAdapter() { }
|
||||
|
||||
protected:
|
||||
Plugin *createPlugin(float inputSampleRate) {
|
||||
P *p = new P(inputSampleRate);
|
||||
Plugin *plugin = dynamic_cast<Plugin *>(p);
|
||||
if (!plugin) {
|
||||
plugin* createPlugin(float inputSampleRate) {
|
||||
Plugin* pl = new Plugin(inputSampleRate);
|
||||
plugin* p = dynamic_cast<plugin*>(pl);
|
||||
if (!p) {
|
||||
std::cerr << "ERROR: PluginAdapter::createPlugin: "
|
||||
<< "Template type is not a plugin!"
|
||||
<< std::endl;
|
||||
delete p;
|
||||
delete pl;
|
||||
return 0;
|
||||
}
|
||||
return plugin;
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,218 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Vamp {
|
||||
|
||||
/**
|
||||
* A base class for plugins with optional configurable parameters,
|
||||
* programs, etc. The Vamp::Plugin is derived from this, and
|
||||
* individual Vamp plugins should derive from that.
|
||||
*
|
||||
* This class does not provide the necessary interfaces to instantiate
|
||||
* or run a plugin. It only specifies an interface for retrieving
|
||||
* those controls that the host may wish to show to the user for
|
||||
* editing. It could meaningfully be subclassed by real-time plugins
|
||||
* or other sorts of plugin as well as Vamp plugins.
|
||||
*/
|
||||
|
||||
class PluginBase
|
||||
{
|
||||
public:
|
||||
virtual ~PluginBase() { }
|
||||
|
||||
/**
|
||||
* Get the Vamp API compatibility level of the plugin.
|
||||
*/
|
||||
virtual unsigned int getVampApiVersion() const { return 2; }
|
||||
|
||||
/**
|
||||
* Get the computer-usable name of the plugin. This should be
|
||||
* reasonably short and contain no whitespace or punctuation
|
||||
* characters. It may only contain the characters [a-zA-Z0-9_-].
|
||||
* This is the authoritative way for a program to identify a
|
||||
* plugin within a given library.
|
||||
*
|
||||
* This text may be visible to the user, but it should not be the
|
||||
* main text used to identify a plugin to the user (that will be
|
||||
* the name, below).
|
||||
*
|
||||
* Example: "zero_crossings"
|
||||
*/
|
||||
virtual std::string getIdentifier() const = 0;
|
||||
|
||||
/**
|
||||
* Get a human-readable name or title of the plugin. This
|
||||
* should be brief and self-contained, as it may be used to
|
||||
* identify the plugin to the user in isolation (i.e. without also
|
||||
* showing the plugin's "identifier").
|
||||
*
|
||||
* Example: "Zero Crossings"
|
||||
*/
|
||||
virtual std::string getName() const = 0;
|
||||
|
||||
/**
|
||||
* Get a human-readable description for the plugin, typically
|
||||
* a line of text that may optionally be displayed in addition
|
||||
* to the plugin's "name". May be empty if the name has said
|
||||
* it all already.
|
||||
*
|
||||
* Example: "Detect and count zero crossing points"
|
||||
*/
|
||||
virtual std::string getDescription() const = 0;
|
||||
|
||||
/**
|
||||
* Get the name of the author or vendor of the plugin in
|
||||
* human-readable form. This should be a short identifying text,
|
||||
* as it may be used to label plugins from the same source in a
|
||||
* menu or similar.
|
||||
*/
|
||||
virtual std::string getMaker() const = 0;
|
||||
|
||||
/**
|
||||
* Get the copyright statement or licensing summary for the
|
||||
* plugin. This can be an informative text, without the same
|
||||
* presentation constraints as mentioned for getMaker above.
|
||||
*/
|
||||
virtual std::string getCopyright() const = 0;
|
||||
|
||||
/**
|
||||
* Get the version number of the plugin.
|
||||
*/
|
||||
virtual int getPluginVersion() const = 0;
|
||||
|
||||
|
||||
struct ParameterDescriptor
|
||||
{
|
||||
/**
|
||||
* The name of the parameter, in computer-usable form. Should
|
||||
* be reasonably short, and may only contain the characters
|
||||
* [a-zA-Z0-9_-].
|
||||
*/
|
||||
std::string identifier;
|
||||
|
||||
/**
|
||||
* The human-readable name of the parameter.
|
||||
*/
|
||||
std::string name;
|
||||
|
||||
/**
|
||||
* A human-readable short text describing the parameter. May be
|
||||
* empty if the name has said it all already.
|
||||
*/
|
||||
std::string description;
|
||||
|
||||
/**
|
||||
* The unit of the parameter, in human-readable form.
|
||||
*/
|
||||
std::string unit;
|
||||
|
||||
/**
|
||||
* The minimum value of the parameter.
|
||||
*/
|
||||
float minValue;
|
||||
|
||||
/**
|
||||
* The maximum value of the parameter.
|
||||
*/
|
||||
float maxValue;
|
||||
|
||||
/**
|
||||
* The default value of the parameter. The plugin should
|
||||
* ensure that parameters have this value on initialisation
|
||||
* (i.e. the host is not required to explicitly set parameters
|
||||
* if it wants to use their default values).
|
||||
*/
|
||||
float defaultValue;
|
||||
|
||||
/**
|
||||
* True if the parameter values are quantized to a particular
|
||||
* resolution.
|
||||
*/
|
||||
bool isQuantized;
|
||||
|
||||
/**
|
||||
* Quantization resolution of the parameter values (e.g. 1.0
|
||||
* if they are all integers). Undefined if isQuantized is
|
||||
* false.
|
||||
*/
|
||||
float quantizeStep;
|
||||
|
||||
/**
|
||||
* Names for the quantized values. If isQuantized is true,
|
||||
* this may either be empty or contain one string for each of
|
||||
* the quantize steps from minValue up to maxValue inclusive.
|
||||
* Undefined if isQuantized is false.
|
||||
*
|
||||
* If these names are provided, they should be shown to the
|
||||
* user in preference to the values themselves. The user may
|
||||
* never see the actual numeric values unless they are also
|
||||
* encoded in the names.
|
||||
*/
|
||||
std::vector<std::string> valueNames;
|
||||
|
||||
ParameterDescriptor() : // the defaults are invalid: you must set them
|
||||
minValue(0),
|
||||
maxValue(0),
|
||||
defaultValue(0),
|
||||
isQuantized(false),
|
||||
quantizeStep(0) { }
|
||||
};
|
||||
|
||||
typedef std::vector<ParameterDescriptor> ParameterList;
|
||||
|
||||
/**
|
||||
* Get the controllable parameters of this plugin.
|
||||
*/
|
||||
virtual ParameterList getParameterDescriptors() const {
|
||||
return ParameterList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of a named parameter. The argument is the identifier
|
||||
* field from that parameter's descriptor.
|
||||
*/
|
||||
virtual float getParameter(std::string) const { return 0.0; }
|
||||
|
||||
/**
|
||||
* Set a named parameter. The first argument is the identifier field
|
||||
* from that parameter's descriptor.
|
||||
*/
|
||||
virtual void setParameter(std::string, float) { }
|
||||
|
||||
|
||||
typedef std::vector<std::string> ProgramList;
|
||||
|
||||
/**
|
||||
* Get the program settings available in this plugin. A program
|
||||
* is a named shorthand for a set of parameter values; changing
|
||||
* the program may cause the plugin to alter the values of its
|
||||
* published parameters (and/or non-public internal processing
|
||||
* parameters). The host should re-read the plugin's parameter
|
||||
* values after setting a new program.
|
||||
*
|
||||
* The programs must have unique names.
|
||||
*/
|
||||
virtual ProgramList getPrograms() const { return ProgramList(); }
|
||||
|
||||
/**
|
||||
* Get the current program.
|
||||
*/
|
||||
virtual std::string getCurrentProgram() const { return ""; }
|
||||
|
||||
/**
|
||||
* Select a program. (If the given program name is not one of the
|
||||
* available programs, do nothing.)
|
||||
*/
|
||||
virtual void selectProgram(std::string) { }
|
||||
|
||||
/**
|
||||
* Get the type of plugin. This is to be implemented by the
|
||||
* immediate subclass, not by actual plugins. Do not attempt to
|
||||
* implement this in plugin code.
|
||||
*/
|
||||
virtual std::string getType() const = 0;
|
||||
};
|
||||
|
||||
}
|
@ -1,199 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <limits.h>
|
||||
|
||||
#if (defined(__GNUC__)) && (__GNUC__ < 3)
|
||||
#include <strstream>
|
||||
#define stringstream strstream
|
||||
#else
|
||||
#include <sstream>
|
||||
#endif
|
||||
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "vamp-sdk/RealTime.h"
|
||||
|
||||
namespace Vamp {
|
||||
|
||||
// A RealTime consists of two ints that must be at least 32 bits each.
|
||||
// A signed 32-bit int can store values exceeding +/- 2 billion. This
|
||||
// means we can safely use our lower int for nanoseconds, as there are
|
||||
// 1 billion nanoseconds in a second and we need to handle double that
|
||||
// because of the implementations of addition etc that we use.
|
||||
//
|
||||
// The maximum valid RealTime on a 32-bit system is somewhere around
|
||||
// 68 years: 999999999 nanoseconds longer than the classic Unix epoch.
|
||||
|
||||
#define ONE_BILLION 1000000000
|
||||
|
||||
RealTime::RealTime(int s, int n) :
|
||||
sec(s), nsec(n)
|
||||
{
|
||||
while (nsec <= -ONE_BILLION && sec > INT_MIN) { nsec += ONE_BILLION; --sec; }
|
||||
while (nsec >= ONE_BILLION && sec < INT_MAX) { nsec -= ONE_BILLION; ++sec; }
|
||||
while (nsec > 0 && sec < 0) { nsec -= ONE_BILLION; ++sec; }
|
||||
while (nsec < 0 && sec > 0) { nsec += ONE_BILLION; --sec; }
|
||||
}
|
||||
|
||||
RealTime
|
||||
RealTime::fromSeconds(double sec)
|
||||
{
|
||||
if (sec != sec) { // NaN
|
||||
cerr << "ERROR: NaN/Inf passed to Vamp::RealTime::fromSeconds" << endl;
|
||||
return RealTime::zeroTime;
|
||||
} else if (sec >= 0) {
|
||||
return RealTime(int(sec), int((sec - int(sec)) * ONE_BILLION + 0.5));
|
||||
} else {
|
||||
return -fromSeconds(-sec);
|
||||
}
|
||||
}
|
||||
|
||||
RealTime
|
||||
RealTime::fromMilliseconds(int msec)
|
||||
{
|
||||
return RealTime(msec / 1000, (msec % 1000) * 1000000);
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
RealTime
|
||||
RealTime::fromTimeval(const struct timeval &tv)
|
||||
{
|
||||
return RealTime(int(tv.tv_sec), int(tv.tv_usec * 1000));
|
||||
}
|
||||
#endif
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const RealTime &rt)
|
||||
{
|
||||
if (rt < RealTime::zeroTime) {
|
||||
out << "-";
|
||||
} else {
|
||||
out << " ";
|
||||
}
|
||||
|
||||
int s = (rt.sec < 0 ? -rt.sec : rt.sec);
|
||||
int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec);
|
||||
|
||||
out << s << ".";
|
||||
|
||||
int nn(n);
|
||||
if (nn == 0) out << "00000000";
|
||||
else while (nn < (ONE_BILLION / 10)) {
|
||||
out << "0";
|
||||
nn *= 10;
|
||||
}
|
||||
|
||||
out << n << "R";
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string
|
||||
RealTime::toString() const
|
||||
{
|
||||
std::stringstream out;
|
||||
out << *this;
|
||||
|
||||
std::string s = out.str();
|
||||
|
||||
// remove trailing R
|
||||
return s.substr(0, s.length() - 1);
|
||||
}
|
||||
|
||||
std::string
|
||||
RealTime::toText(bool fixedDp) const
|
||||
{
|
||||
if (*this < RealTime::zeroTime) return "-" + (-*this).toText(fixedDp);
|
||||
|
||||
std::stringstream out;
|
||||
|
||||
if (sec >= 3600) {
|
||||
out << (sec / 3600) << ":";
|
||||
}
|
||||
|
||||
if (sec >= 60) {
|
||||
int minutes = (sec % 3600) / 60;
|
||||
if (sec >= 3600 && minutes < 10) out << "0";
|
||||
out << minutes << ":";
|
||||
}
|
||||
|
||||
if (sec >= 10) {
|
||||
out << ((sec % 60) / 10);
|
||||
}
|
||||
|
||||
out << (sec % 10);
|
||||
|
||||
int ms = msec();
|
||||
|
||||
if (ms != 0) {
|
||||
out << ".";
|
||||
out << (ms / 100);
|
||||
ms = ms % 100;
|
||||
if (ms != 0) {
|
||||
out << (ms / 10);
|
||||
ms = ms % 10;
|
||||
} else if (fixedDp) {
|
||||
out << "0";
|
||||
}
|
||||
if (ms != 0) {
|
||||
out << ms;
|
||||
} else if (fixedDp) {
|
||||
out << "0";
|
||||
}
|
||||
} else if (fixedDp) {
|
||||
out << ".000";
|
||||
}
|
||||
|
||||
std::string s = out.str();
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
RealTime
|
||||
RealTime::operator/(int d) const
|
||||
{
|
||||
int secdiv = sec / d;
|
||||
int secrem = sec % d;
|
||||
|
||||
double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d;
|
||||
|
||||
return RealTime(secdiv, int(nsecdiv + 0.5));
|
||||
}
|
||||
|
||||
double
|
||||
RealTime::operator/(const RealTime &r) const
|
||||
{
|
||||
double lTotal = double(sec) * ONE_BILLION + double(nsec);
|
||||
double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec);
|
||||
|
||||
if (rTotal == 0) return 0.0;
|
||||
else return lTotal/rTotal;
|
||||
}
|
||||
|
||||
long
|
||||
RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate)
|
||||
{
|
||||
if (time < zeroTime) return -realTime2Frame(-time, sampleRate);
|
||||
double s = time.sec + double(time.nsec) / ONE_BILLION;
|
||||
return long(s * sampleRate + 0.5);
|
||||
}
|
||||
|
||||
RealTime
|
||||
RealTime::frame2RealTime(long frame, unsigned int sampleRate)
|
||||
{
|
||||
if (frame < 0) return -frame2RealTime(-frame, sampleRate);
|
||||
|
||||
int sec = int(frame / long(sampleRate));
|
||||
frame -= sec * long(sampleRate);
|
||||
int nsec = (int)((double(frame) / double(sampleRate)) * ONE_BILLION + 0.5);
|
||||
// Use ctor here instead of setting data members directly to
|
||||
// ensure nsec > ONE_BILLION is handled properly. It's extremely
|
||||
// unlikely, but not impossible.
|
||||
return RealTime(sec, nsec);
|
||||
}
|
||||
|
||||
const RealTime RealTime::zeroTime(0,0);
|
||||
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
struct timeval;
|
||||
|
||||
namespace Vamp {
|
||||
|
||||
/**
|
||||
* \class RealTime RealTime.h <vamp-sdk/RealTime.h>
|
||||
*
|
||||
* RealTime represents time values to nanosecond precision
|
||||
* with accurate arithmetic and frame-rate conversion functions.
|
||||
*/
|
||||
|
||||
struct RealTime
|
||||
{
|
||||
int sec;
|
||||
int nsec;
|
||||
|
||||
int usec() const { return nsec / 1000; }
|
||||
int msec() const { return nsec / 1000000; }
|
||||
|
||||
RealTime(): sec(0), nsec(0) {}
|
||||
RealTime(int s, int n);
|
||||
|
||||
RealTime(const RealTime &r) :
|
||||
sec(r.sec), nsec(r.nsec) { }
|
||||
|
||||
static RealTime fromSeconds(double sec);
|
||||
static RealTime fromMilliseconds(int msec);
|
||||
|
||||
#ifndef _WIN32
|
||||
static RealTime fromTimeval(const struct timeval &);
|
||||
#endif
|
||||
|
||||
RealTime &operator=(const RealTime &r) {
|
||||
sec = r.sec; nsec = r.nsec; return *this;
|
||||
}
|
||||
|
||||
RealTime operator+(const RealTime &r) const {
|
||||
return RealTime(sec + r.sec, nsec + r.nsec);
|
||||
}
|
||||
RealTime operator-(const RealTime &r) const {
|
||||
return RealTime(sec - r.sec, nsec - r.nsec);
|
||||
}
|
||||
RealTime operator-() const {
|
||||
return RealTime(-sec, -nsec);
|
||||
}
|
||||
|
||||
bool operator <(const RealTime &r) const {
|
||||
if (sec == r.sec) return nsec < r.nsec;
|
||||
else return sec < r.sec;
|
||||
}
|
||||
|
||||
bool operator >(const RealTime &r) const {
|
||||
if (sec == r.sec) return nsec > r.nsec;
|
||||
else return sec > r.sec;
|
||||
}
|
||||
|
||||
bool operator==(const RealTime &r) const {
|
||||
return (sec == r.sec && nsec == r.nsec);
|
||||
}
|
||||
|
||||
bool operator!=(const RealTime &r) const {
|
||||
return !(r == *this);
|
||||
}
|
||||
|
||||
bool operator>=(const RealTime &r) const {
|
||||
if (sec == r.sec) return nsec >= r.nsec;
|
||||
else return sec >= r.sec;
|
||||
}
|
||||
|
||||
bool operator<=(const RealTime &r) const {
|
||||
if (sec == r.sec) return nsec <= r.nsec;
|
||||
else return sec <= r.sec;
|
||||
}
|
||||
|
||||
RealTime operator/(int d) const;
|
||||
|
||||
/**
|
||||
* Return the ratio of two times.
|
||||
*/
|
||||
double operator/(const RealTime &r) const;
|
||||
|
||||
/**
|
||||
* Return a human-readable debug-type string to full precision
|
||||
* (probably not a format to show to a user directly)
|
||||
*/
|
||||
std::string toString() const;
|
||||
|
||||
/**
|
||||
* Return a user-readable string to the nearest millisecond
|
||||
* in a form like HH:MM:SS.mmm
|
||||
*/
|
||||
std::string toText(bool fixedDp = false) const;
|
||||
|
||||
/**
|
||||
* Convert a RealTime into a sample frame at the given sample rate.
|
||||
*/
|
||||
static long realTime2Frame(const RealTime &r, unsigned int sampleRate);
|
||||
|
||||
/**
|
||||
* Convert a sample frame at the given sample rate into a RealTime.
|
||||
*/
|
||||
static RealTime frame2RealTime(long frame, unsigned int sampleRate);
|
||||
|
||||
static const RealTime zeroTime;
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const RealTime &rt);
|
||||
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
/* These stubs are provided so that autoconf can check library
|
||||
* versions using C symbols only */
|
||||
|
||||
extern void libvampsdk_v_2_9_present(void) { }
|
||||
extern void libvampsdk_v_2_8_present(void) { }
|
||||
extern void libvampsdk_v_2_7_1_present(void) { }
|
||||
extern void libvampsdk_v_2_7_present(void) { }
|
||||
extern void libvampsdk_v_2_6_present(void) { }
|
||||
extern void libvampsdk_v_2_5_present(void) { }
|
||||
extern void libvampsdk_v_2_4_present(void) { }
|
||||
extern void libvampsdk_v_2_3_1_present(void) { }
|
||||
extern void libvampsdk_v_2_3_present(void) { }
|
||||
extern void libvampsdk_v_2_2_1_present(void) { }
|
||||
extern void libvampsdk_v_2_2_present(void) { }
|
||||
extern void libvampsdk_v_2_1_present(void) { }
|
||||
extern void libvampsdk_v_2_0_present(void) { }
|
46
src/vamp-sdk/base_plugin.hpp
Normal file
46
src/vamp-sdk/base_plugin.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace vamp
|
||||
{
|
||||
class base_plugin
|
||||
{
|
||||
public:
|
||||
base_plugin() = default;
|
||||
virtual ~base_plugin();
|
||||
|
||||
public:
|
||||
struct parameter_descriptor
|
||||
{
|
||||
std::string identifier;
|
||||
std::string name;
|
||||
std::string description;
|
||||
std::string unit;
|
||||
float min_value { 0.f };
|
||||
float max_value { 0.f };
|
||||
float default_value { 0.f };
|
||||
bool is_quantized { false };
|
||||
float quantize_step { 0.f };
|
||||
std::vector<std::string> value_names;
|
||||
};
|
||||
|
||||
using parameter_descriptors = std::vector<parameter_descriptor>;
|
||||
using programs = std::vector<std::string>;
|
||||
|
||||
public:
|
||||
virtual std::string get_identifier() const = 0;
|
||||
virtual std::string get_name() const = 0;
|
||||
virtual std::string get_description() const = 0;
|
||||
virtual std::string get_maker() const = 0;
|
||||
virtual float get_parameter(std::string) const { return 0.f; }
|
||||
virtual std::string get_current_program() const { return ""; }
|
||||
virtual std::string get_type() const = 0;
|
||||
virtual parameter_descriptors get_parameter_descriptors() const { return parameter_descriptors(); }
|
||||
virtual programs get_programs() const { return programs(); }
|
||||
|
||||
virtual void set_parameter(std::string, float) { }
|
||||
virtual void select_program(std::string) { }
|
||||
};
|
||||
}
|
160
src/vamp-sdk/real_time/real_time.cpp
Normal file
160
src/vamp-sdk/real_time/real_time.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
#include "real_time.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <sys/time.h>
|
||||
|
||||
namespace vamp
|
||||
{
|
||||
const real_time real_time::zero_time{ 0, 0 };
|
||||
|
||||
real_time::real_time(int s, int n) : sec{ s }, nsec{ n }
|
||||
{
|
||||
while (nsec <= -ONE_BILLION && sec > std::numeric_limits<int>().max()) { nsec += ONE_BILLION; --sec; }
|
||||
while (nsec >= ONE_BILLION && sec < std::numeric_limits<int>().max()) { nsec -= ONE_BILLION; ++sec; }
|
||||
while (nsec > 0 && sec < 0) { nsec -= ONE_BILLION; ++sec; }
|
||||
while (nsec < 0 && sec > 0) { nsec += ONE_BILLION; --sec; }
|
||||
}
|
||||
|
||||
real_time real_time::from_seconds(double sec)
|
||||
{
|
||||
if (sec != sec)
|
||||
return real_time::zero_time;
|
||||
else if (sec >= 0)
|
||||
return real_time{ static_cast<int>(sec), static_cast<int>((sec - int(sec)) * ONE_BILLION + 0.5) };
|
||||
else
|
||||
return -from_seconds(-sec);
|
||||
}
|
||||
|
||||
real_time real_time::from_milliseconds(int msec)
|
||||
{
|
||||
return real_time{ msec / 1'000, (msec % 1'000) * 1'000'000 };
|
||||
}
|
||||
|
||||
real_time real_time::from_timeval(const struct timeval& tv)
|
||||
{
|
||||
return real_time{ int(tv.tv_sec), int(tv.tv_usec * 1000) };
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const real_time& rt)
|
||||
{
|
||||
if (rt < real_time::zero_time)
|
||||
out << "-";
|
||||
else
|
||||
out << " ";
|
||||
|
||||
int s = (rt.sec < 0 ? -rt.sec : rt.sec);
|
||||
int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec);
|
||||
|
||||
out << s << ".";
|
||||
|
||||
int nn{ n };
|
||||
if (nn == 0) out << "00000000";
|
||||
else while (nn < (ONE_BILLION / 10))
|
||||
{
|
||||
out << "0";
|
||||
nn *= 10;
|
||||
}
|
||||
|
||||
out << n << "R";
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string real_time::to_string() const
|
||||
{
|
||||
std::stringstream out;
|
||||
out << *this;
|
||||
std::string s = out.str();
|
||||
|
||||
// remove trailing R
|
||||
return s.substr(0, s.length() - 1);
|
||||
}
|
||||
|
||||
std::string real_time::to_text(bool fixed_dp) const
|
||||
{
|
||||
if (*this < real_time::zero_time) return "-" + (-*this).to_text(fixed_dp);
|
||||
|
||||
std::stringstream out;
|
||||
|
||||
if (sec >= 3'600) out << (sec / 3'600) << ":";
|
||||
|
||||
if (sec >= 60)
|
||||
{
|
||||
int minutes = (sec % 3'600) / 60;
|
||||
if (sec >= 3'600 && minutes < 10) out << "0";
|
||||
out << minutes << ":";
|
||||
}
|
||||
|
||||
if (sec >= 10) out << ((sec % 60) / 10);
|
||||
|
||||
out << (sec % 10);
|
||||
|
||||
int ms = msec();
|
||||
|
||||
if (ms != 0)
|
||||
{
|
||||
out << ".";
|
||||
out << (ms / 100);
|
||||
ms = ms % 100;
|
||||
if (ms != 0)
|
||||
{
|
||||
out << (ms / 10);
|
||||
ms = ms % 10;
|
||||
}
|
||||
else if (fixed_dp)
|
||||
{
|
||||
out << "0";
|
||||
}
|
||||
if (ms != 0)
|
||||
{
|
||||
out << ms;
|
||||
}
|
||||
else if (fixed_dp)
|
||||
{
|
||||
out << "0";
|
||||
}
|
||||
}
|
||||
else if (fixed_dp)
|
||||
{
|
||||
out << ".000";
|
||||
}
|
||||
|
||||
std::string s = out.str();
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
real_time real_time::operator/(int d) const
|
||||
{
|
||||
int secdiv = sec / d;
|
||||
int secrem = sec % d;
|
||||
double nsecdiv = (static_cast<double>(nsec) + ONE_BILLION * static_cast<double>(secrem)) / d;
|
||||
return real_time{ secdiv, static_cast<int>(nsecdiv + 0.5) };
|
||||
}
|
||||
|
||||
double real_time::operator/(const real_time& r) const
|
||||
{
|
||||
double l_total = static_cast<double>(sec) * ONE_BILLION + static_cast<double>(nsec);
|
||||
double r_total = static_cast<double>(r.sec) * ONE_BILLION + static_cast<double>(r.nsec);
|
||||
if (r_total == 0) return 0.0;
|
||||
else return l_total / r_total;
|
||||
}
|
||||
|
||||
long real_time::rt2f(const real_time& time, unsigned int sample_rate)
|
||||
{
|
||||
if (time < real_time::zero_time) return -rt2f(-time, sample_rate);
|
||||
double s = time.sec + static_cast<double>(time.nsec) / ONE_BILLION;
|
||||
return static_cast<long>(s * sample_rate + 0.5);
|
||||
}
|
||||
|
||||
real_time real_time::f2rt(long frame, unsigned int sample_rate)
|
||||
{
|
||||
if (frame < 0) return -f2rt(-frame, sample_rate);
|
||||
|
||||
int sec = static_cast<int>(frame / static_cast<long>(sample_rate));
|
||||
frame -= sec * static_cast<long>(sample_rate);
|
||||
int nsec = static_cast<int>((static_cast<double>(frame) / static_cast<double>(sample_rate)) * ONE_BILLION + 0.5);
|
||||
return real_time{ sec, nsec };
|
||||
}
|
||||
}
|
99
src/vamp-sdk/real_time/real_time.hpp
Normal file
99
src/vamp-sdk/real_time/real_time.hpp
Normal file
@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#define ONE_BILLION 1'000'000'000
|
||||
struct timeval;
|
||||
|
||||
namespace vamp
|
||||
{
|
||||
struct real_time
|
||||
{
|
||||
public:
|
||||
real_time() = default;
|
||||
real_time(int s, int n);
|
||||
real_time(const real_time& r) : sec{ r.sec }, nsec{ r.nsec } { }
|
||||
|
||||
public:
|
||||
int sec { 0 };
|
||||
int nsec { 0 };
|
||||
|
||||
public:
|
||||
static real_time from_seconds(double sec);
|
||||
static real_time from_milliseconds(int msec);
|
||||
static real_time from_timeval(const struct timeval &);
|
||||
// real_time to frame
|
||||
static long rt2f(const real_time &r, unsigned int sample_rate);
|
||||
// frame to real_time
|
||||
static real_time f2rt(long frame, unsigned int sample_rate);
|
||||
static const real_time zero_time;
|
||||
|
||||
public:
|
||||
int usec() const { return nsec / 1000; }
|
||||
int msec() const { return nsec / 1000000; }
|
||||
|
||||
std::string to_string() const;
|
||||
std::string to_text(bool fixed_dp = false) const;
|
||||
|
||||
public:
|
||||
real_time &operator=(const real_time &r)
|
||||
{
|
||||
sec = r.sec; nsec = r.nsec; return *this;
|
||||
}
|
||||
|
||||
real_time operator+(const real_time &r) const
|
||||
{
|
||||
return real_time(sec + r.sec, nsec + r.nsec);
|
||||
}
|
||||
|
||||
real_time operator-(const real_time &r) const
|
||||
{
|
||||
return real_time(sec - r.sec, nsec - r.nsec);
|
||||
}
|
||||
|
||||
real_time operator-() const
|
||||
{
|
||||
return real_time(-sec, -nsec);
|
||||
}
|
||||
|
||||
bool operator <(const real_time &r) const
|
||||
{
|
||||
if (sec == r.sec) return nsec < r.nsec;
|
||||
else return sec < r.sec;
|
||||
}
|
||||
|
||||
bool operator >(const real_time &r) const
|
||||
{
|
||||
if (sec == r.sec) return nsec > r.nsec;
|
||||
else return sec > r.sec;
|
||||
}
|
||||
|
||||
bool operator==(const real_time &r) const
|
||||
{
|
||||
return (sec == r.sec && nsec == r.nsec);
|
||||
}
|
||||
|
||||
bool operator!=(const real_time &r) const
|
||||
{
|
||||
return !(r == *this);
|
||||
}
|
||||
|
||||
bool operator>=(const real_time &r) const
|
||||
{
|
||||
if (sec == r.sec) return nsec >= r.nsec;
|
||||
else return sec >= r.sec;
|
||||
}
|
||||
|
||||
bool operator<=(const real_time &r) const
|
||||
{
|
||||
if (sec == r.sec) return nsec <= r.nsec;
|
||||
else return sec <= r.sec;
|
||||
}
|
||||
|
||||
real_time operator/(int d) const;
|
||||
double operator/(const real_time &r) const;
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &out, const real_time &rt);
|
||||
};
|
||||
}
|
102
test/main.cpp
102
test/main.cpp
@ -1,49 +1,45 @@
|
||||
#include "hack/logger/logger.hpp"
|
||||
|
||||
#include "vamp-sdk/Plugin.h"
|
||||
#include "vamp-hostsdk/PluginInputDomainAdapter.h"
|
||||
#include "vamp-hostsdk/PluginBufferingAdapter.h"
|
||||
#include "vamp-sdk/Plugin.h"
|
||||
|
||||
|
||||
class MyPlugin : public Vamp::Plugin
|
||||
class MyPlugin : public vamp::plugin
|
||||
{
|
||||
public:
|
||||
MyPlugin(float inputSampleRate);
|
||||
virtual ~MyPlugin();
|
||||
|
||||
std::string getIdentifier() const;
|
||||
std::string getName() const;
|
||||
std::string getDescription() const;
|
||||
std::string getMaker() const;
|
||||
int getPluginVersion() const;
|
||||
std::string getCopyright() const;
|
||||
std::string get_identifier() const override;
|
||||
std::string get_name() const override;
|
||||
std::string get_description() const override;
|
||||
std::string get_maker() const override;
|
||||
|
||||
InputDomain getInputDomain() const;
|
||||
size_t getPreferredBlockSize() const;
|
||||
size_t getPreferredStepSize() const;
|
||||
size_t getMinChannelCount() const;
|
||||
size_t getMaxChannelCount() const;
|
||||
InputDomain getInputDomain() const override;
|
||||
size_t getPreferredBlockSize() const override;
|
||||
size_t getPreferredStepSize() const override;
|
||||
size_t getMinChannelCount() const override;
|
||||
size_t getMaxChannelCount() const override;
|
||||
|
||||
ParameterList getParameterDescriptors() const;
|
||||
float getParameter(std::string identifier) const;
|
||||
void setParameter(std::string identifier, float value);
|
||||
parameter_descriptors get_parameter_descriptors() const override;
|
||||
float get_parameter(std::string identifier) const override;
|
||||
void set_parameter(std::string identifier, float value) override;
|
||||
|
||||
ProgramList getPrograms() const;
|
||||
std::string getCurrentProgram() const;
|
||||
void selectProgram(std::string name);
|
||||
programs get_programs() const override;
|
||||
std::string get_current_program() const override;
|
||||
void select_program(std::string name) override;
|
||||
|
||||
OutputList getOutputDescriptors() const;
|
||||
OutputList getOutputDescriptors() const override;
|
||||
|
||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||
void reset();
|
||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize) override;
|
||||
void reset() override;
|
||||
|
||||
FeatureSet process(const float *const *inputBuffers,
|
||||
Vamp::RealTime timestamp);
|
||||
|
||||
FeatureSet getRemainingFeatures();
|
||||
FeatureSet process(const float *const *inputBuffers, vamp::real_time timestamp) override;
|
||||
FeatureSet getRemainingFeatures() override;
|
||||
};
|
||||
|
||||
MyPlugin::MyPlugin(float inputSampleRate) : Plugin(inputSampleRate)
|
||||
MyPlugin::MyPlugin(float inputSampleRate) : plugin(inputSampleRate)
|
||||
{
|
||||
}
|
||||
|
||||
@ -51,32 +47,22 @@ MyPlugin::~MyPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
std::string MyPlugin::getIdentifier() const
|
||||
std::string MyPlugin::get_identifier() const
|
||||
{
|
||||
return "myplugin";
|
||||
}
|
||||
|
||||
std::string MyPlugin::getName() const
|
||||
std::string MyPlugin::get_name() const
|
||||
{
|
||||
return "My Plugin";
|
||||
}
|
||||
|
||||
std::string MyPlugin::getDescription() const
|
||||
std::string MyPlugin::get_description() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string MyPlugin::getMaker() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int MyPlugin::getPluginVersion() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string MyPlugin::getCopyright() const
|
||||
std::string MyPlugin::get_maker() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
@ -106,48 +92,48 @@ size_t MyPlugin::getMaxChannelCount() const
|
||||
return 1;
|
||||
}
|
||||
|
||||
MyPlugin::ParameterList MyPlugin::getParameterDescriptors() const
|
||||
MyPlugin::parameter_descriptors MyPlugin::get_parameter_descriptors() const
|
||||
{
|
||||
ParameterList list;
|
||||
ParameterDescriptor d;
|
||||
parameter_descriptors list;
|
||||
parameter_descriptor d;
|
||||
d.identifier = "parameter";
|
||||
d.name = "Some Parameter";
|
||||
d.description = "";
|
||||
d.unit = "";
|
||||
d.minValue = 0;
|
||||
d.maxValue = 10;
|
||||
d.defaultValue = 5;
|
||||
d.isQuantized = false;
|
||||
d.min_value = 0;
|
||||
d.max_value = 10;
|
||||
d.default_value = 5;
|
||||
d.is_quantized = false;
|
||||
list.push_back(d);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
float MyPlugin::getParameter(std::string identifier) const
|
||||
float MyPlugin::get_parameter(std::string identifier) const
|
||||
{
|
||||
if (identifier == "parameter")
|
||||
return 5;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MyPlugin::setParameter(std::string identifier, float value)
|
||||
void MyPlugin::set_parameter(std::string identifier, float value)
|
||||
{
|
||||
if (identifier == "parameter") {
|
||||
}
|
||||
}
|
||||
|
||||
MyPlugin::ProgramList MyPlugin::getPrograms() const
|
||||
MyPlugin::programs MyPlugin::get_programs() const
|
||||
{
|
||||
ProgramList list;
|
||||
programs list;
|
||||
return list;
|
||||
}
|
||||
|
||||
std::string MyPlugin::getCurrentProgram() const
|
||||
std::string MyPlugin::get_current_program() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void MyPlugin::selectProgram(std::string name)
|
||||
void MyPlugin::select_program(std::string name)
|
||||
{
|
||||
}
|
||||
|
||||
@ -181,7 +167,7 @@ void MyPlugin::reset()
|
||||
{
|
||||
}
|
||||
|
||||
MyPlugin::FeatureSet MyPlugin::process(const float *const *inputBuffers, Vamp::RealTime timestamp)
|
||||
MyPlugin::FeatureSet MyPlugin::process(const float *const *inputBuffers, vamp::real_time timestamp)
|
||||
{
|
||||
return FeatureSet();
|
||||
}
|
||||
@ -195,10 +181,10 @@ auto main() -> int
|
||||
{
|
||||
float samplerate = 10.f;
|
||||
MyPlugin* ch = new MyPlugin(samplerate);
|
||||
Vamp::HostExt::PluginInputDomainAdapter* ia = new Vamp::HostExt::PluginInputDomainAdapter(ch);
|
||||
ia->setProcessTimestampMethod(Vamp::HostExt::PluginInputDomainAdapter::ShiftData);
|
||||
vamp::host::PluginInputDomainAdapter* ia = new vamp::host::PluginInputDomainAdapter(ch);
|
||||
ia->setProcessTimestampMethod(vamp::host::PluginInputDomainAdapter::ShiftData);
|
||||
|
||||
Vamp::HostExt::PluginBufferingAdapter* adapter = new Vamp::HostExt::PluginBufferingAdapter(ia);
|
||||
vamp::host::PluginBufferingAdapter* adapter = new vamp::host::PluginBufferingAdapter(ia);
|
||||
|
||||
int blocksize = adapter->getPreferredBlockSize();
|
||||
if (!adapter->initialise(1, blocksize, blocksize))
|
||||
|
Loading…
Reference in New Issue
Block a user