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('.')
|
inc += include_directories('.')
|
||||||
|
|
||||||
headers = [
|
headers = [
|
||||||
|
'vamp-sdk/real_time/real_time.hpp',
|
||||||
|
|
||||||
'vamp.h',
|
'vamp.h',
|
||||||
'vamp-hostsdk/Files.h',
|
'vamp-hostsdk/Files.h',
|
||||||
'vamp-hostsdk/host-c.h',
|
'vamp-hostsdk/host-c.h',
|
||||||
@ -17,17 +19,15 @@ headers = [
|
|||||||
'vamp-sdk/ext/vamp_kiss_fft.h',
|
'vamp-sdk/ext/vamp_kiss_fft.h',
|
||||||
'vamp-sdk/ext/vamp_kiss_fft_guts.h',
|
'vamp-sdk/ext/vamp_kiss_fft_guts.h',
|
||||||
'vamp-sdk/ext/vamp_kiss_fftr.h',
|
'vamp-sdk/ext/vamp_kiss_fftr.h',
|
||||||
|
|
||||||
'vamp-sdk/FFT.h',
|
'vamp-sdk/FFT.h',
|
||||||
'vamp-sdk/Plugin.h',
|
'vamp-sdk/Plugin.h',
|
||||||
'vamp-sdk/PluginAdapter.h',
|
'vamp-sdk/PluginAdapter.h',
|
||||||
'vamp-sdk/PluginBase.h',
|
|
||||||
'vamp-sdk/RealTime.h',
|
|
||||||
'vamp-sdk/vamp-sdk.h'
|
'vamp-sdk/vamp-sdk.h'
|
||||||
]
|
]
|
||||||
|
|
||||||
sources = [
|
sources = [
|
||||||
'vamp-hostsdk/acsymbols.cpp',
|
'vamp-sdk/real_time/real_time.cpp',
|
||||||
|
|
||||||
'vamp-hostsdk/Files.cpp',
|
'vamp-hostsdk/Files.cpp',
|
||||||
'vamp-hostsdk/host-c.cpp',
|
'vamp-hostsdk/host-c.cpp',
|
||||||
'vamp-hostsdk/PluginBufferingAdapter.cpp',
|
'vamp-hostsdk/PluginBufferingAdapter.cpp',
|
||||||
@ -38,10 +38,8 @@ sources = [
|
|||||||
'vamp-hostsdk/PluginSummarisingAdapter.cpp',
|
'vamp-hostsdk/PluginSummarisingAdapter.cpp',
|
||||||
'vamp-hostsdk/PluginWrapper.cpp',
|
'vamp-hostsdk/PluginWrapper.cpp',
|
||||||
|
|
||||||
'vamp-sdk/acsymbols.cpp',
|
|
||||||
'vamp-sdk/FFT.cpp',
|
'vamp-sdk/FFT.cpp',
|
||||||
'vamp-sdk/PluginAdapter.cpp',
|
'vamp-sdk/PluginAdapter.cpp',
|
||||||
'vamp-sdk/RealTime.cpp'
|
|
||||||
]
|
]
|
||||||
|
|
||||||
lib = library(
|
lib = library(
|
||||||
|
@ -18,7 +18,7 @@ std::vector<std::string> Files::listLibraryFiles()
|
|||||||
|
|
||||||
std::vector<std::string> Files::listLibraryFilesMatching(Filter filter)
|
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;
|
std::vector<std::string> libraryFiles;
|
||||||
|
|
||||||
// we match case-insensitively, but only with ascii range
|
// we match case-insensitively, but only with ascii range
|
||||||
|
@ -3,9 +3,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a private implementation class for the Vamp Host SDK.
|
|
||||||
*/
|
|
||||||
class Files
|
class Files
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -2,148 +2,35 @@
|
|||||||
|
|
||||||
#include "vamp-hostsdk/PluginWrapper.h"
|
#include "vamp-hostsdk/PluginWrapper.h"
|
||||||
|
|
||||||
namespace Vamp {
|
namespace vamp::host
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class PluginBufferingAdapter : public PluginWrapper
|
|
||||||
{
|
{
|
||||||
public:
|
class PluginBufferingAdapter : public PluginWrapper
|
||||||
/**
|
{
|
||||||
* Construct a PluginBufferingAdapter wrapping the given plugin.
|
public:
|
||||||
* The adapter takes ownership of the plugin, which will be
|
PluginBufferingAdapter(plugin* p);
|
||||||
* deleted when the adapter is deleted.
|
virtual ~PluginBufferingAdapter();
|
||||||
*/
|
size_t getPreferredStepSize() const;
|
||||||
PluginBufferingAdapter(Plugin *plugin);
|
size_t getPreferredBlockSize() const;
|
||||||
virtual ~PluginBufferingAdapter();
|
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||||
|
size_t getPluginPreferredStepSize() const;
|
||||||
|
size_t getPluginPreferredBlockSize() const;
|
||||||
|
void setPluginStepSize(size_t stepSize);
|
||||||
|
void setPluginBlockSize(size_t blockSize);
|
||||||
|
void getActualStepAndBlockSizes(size_t &stepSize, size_t &blockSize);
|
||||||
|
|
||||||
/**
|
void setParameter(std::string, float);
|
||||||
* Return the preferred step size for this adapter.
|
void selectProgram(std::string);
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
OutputList getOutputDescriptors() 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;
|
|
||||||
|
|
||||||
/**
|
void reset();
|
||||||
* 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);
|
|
||||||
void selectProgram(std::string);
|
|
||||||
|
|
||||||
OutputList getOutputDescriptors() const;
|
|
||||||
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
|
||||||
|
|
||||||
FeatureSet getRemainingFeatures();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class Impl;
|
|
||||||
Impl *m_impl;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
FeatureSet process(const float *const *inputBuffers, real_time timestamp);
|
||||||
|
|
||||||
|
FeatureSet getRemainingFeatures();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
class Impl;
|
||||||
|
Impl *m_impl;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,105 +1,102 @@
|
|||||||
#include "vamp-hostsdk/PluginChannelAdapter.h"
|
#include "vamp-hostsdk/PluginChannelAdapter.h"
|
||||||
|
|
||||||
namespace Vamp {
|
namespace vamp::host
|
||||||
|
|
||||||
namespace HostExt {
|
|
||||||
|
|
||||||
class PluginChannelAdapter::Impl
|
|
||||||
{
|
{
|
||||||
public:
|
class PluginChannelAdapter::Impl
|
||||||
Impl(Plugin *plugin);
|
{
|
||||||
~Impl();
|
public:
|
||||||
|
Impl(plugin* p);
|
||||||
|
~Impl();
|
||||||
|
|
||||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||||
|
|
||||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
FeatureSet process(const float *const *inputBuffers, real_time timestamp);
|
||||||
FeatureSet processInterleaved(const float *inputBuffers, RealTime timestamp);
|
FeatureSet processInterleaved(const float *inputBuffers, real_time timestamp);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Plugin *m_plugin;
|
plugin *m_plugin;
|
||||||
size_t m_blockSize;
|
size_t m_blockSize;
|
||||||
size_t m_inputChannels;
|
size_t m_inputChannels;
|
||||||
size_t m_pluginChannels;
|
size_t m_pluginChannels;
|
||||||
float **m_buffer;
|
float **m_buffer;
|
||||||
float **m_deinterleave;
|
float **m_deinterleave;
|
||||||
const float **m_forwardPtrs;
|
const float **m_forwardPtrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
PluginChannelAdapter::PluginChannelAdapter(Plugin *plugin) :
|
PluginChannelAdapter::PluginChannelAdapter(plugin* p) : PluginWrapper(p)
|
||||||
PluginWrapper(plugin)
|
{
|
||||||
{
|
m_impl = new Impl(p);
|
||||||
m_impl = new Impl(plugin);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
PluginChannelAdapter::~PluginChannelAdapter()
|
PluginChannelAdapter::~PluginChannelAdapter()
|
||||||
{
|
{
|
||||||
delete m_impl;
|
delete m_impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool PluginChannelAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
||||||
PluginChannelAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
{
|
||||||
{
|
|
||||||
return m_impl->initialise(channels, stepSize, blockSize);
|
return m_impl->initialise(channels, stepSize, blockSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginChannelAdapter::FeatureSet
|
PluginChannelAdapter::FeatureSet PluginChannelAdapter::process(const float *const *inputBuffers, real_time timestamp)
|
||||||
PluginChannelAdapter::process(const float *const *inputBuffers,
|
{
|
||||||
RealTime timestamp)
|
|
||||||
{
|
|
||||||
return m_impl->process(inputBuffers, timestamp);
|
return m_impl->process(inputBuffers, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginChannelAdapter::FeatureSet
|
PluginChannelAdapter::FeatureSet PluginChannelAdapter::processInterleaved(const float *inputBuffers, real_time timestamp)
|
||||||
PluginChannelAdapter::processInterleaved(const float *inputBuffers,
|
{
|
||||||
RealTime timestamp)
|
|
||||||
{
|
|
||||||
return m_impl->processInterleaved(inputBuffers, timestamp);
|
return m_impl->processInterleaved(inputBuffers, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginChannelAdapter::Impl::Impl(Plugin *plugin) :
|
PluginChannelAdapter::Impl::Impl(plugin* p) :
|
||||||
m_plugin(plugin),
|
m_plugin(p),
|
||||||
m_blockSize(0),
|
m_blockSize(0),
|
||||||
m_inputChannels(0),
|
m_inputChannels(0),
|
||||||
m_pluginChannels(0),
|
m_pluginChannels(0),
|
||||||
m_buffer(0),
|
m_buffer(0),
|
||||||
m_deinterleave(0),
|
m_deinterleave(0),
|
||||||
m_forwardPtrs(0)
|
m_forwardPtrs(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginChannelAdapter::Impl::~Impl()
|
PluginChannelAdapter::Impl::~Impl()
|
||||||
{
|
{
|
||||||
// the adapter will delete the plugin
|
if (m_buffer)
|
||||||
|
{
|
||||||
if (m_buffer) {
|
if (m_inputChannels > m_pluginChannels)
|
||||||
if (m_inputChannels > m_pluginChannels) {
|
{
|
||||||
delete[] m_buffer[0];
|
delete[] m_buffer[0];
|
||||||
} else {
|
}
|
||||||
for (size_t i = 0; i < m_pluginChannels - m_inputChannels; ++i) {
|
else
|
||||||
delete[] m_buffer[i];
|
{
|
||||||
}
|
for (size_t i = 0; i < m_pluginChannels - m_inputChannels; ++i)
|
||||||
|
{
|
||||||
|
delete[] m_buffer[i];
|
||||||
}
|
}
|
||||||
delete[] m_buffer;
|
}
|
||||||
m_buffer = 0;
|
delete[] m_buffer;
|
||||||
|
m_buffer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_deinterleave) {
|
if (m_deinterleave)
|
||||||
for (size_t i = 0; i < m_inputChannels; ++i) {
|
{
|
||||||
delete[] m_deinterleave[i];
|
for (size_t i = 0; i < m_inputChannels; ++i)
|
||||||
}
|
{
|
||||||
delete[] m_deinterleave;
|
delete[] m_deinterleave[i];
|
||||||
m_deinterleave = 0;
|
}
|
||||||
|
delete[] m_deinterleave;
|
||||||
|
m_deinterleave = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_forwardPtrs) {
|
if (m_forwardPtrs)
|
||||||
delete[] m_forwardPtrs;
|
{
|
||||||
m_forwardPtrs = 0;
|
delete[] m_forwardPtrs;
|
||||||
|
m_forwardPtrs = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool PluginChannelAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
||||||
PluginChannelAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
{
|
||||||
{
|
|
||||||
m_blockSize = blockSize;
|
m_blockSize = blockSize;
|
||||||
|
|
||||||
size_t minch = m_plugin->getMinChannelCount();
|
size_t minch = m_plugin->getMinChannelCount();
|
||||||
@ -107,122 +104,126 @@ PluginChannelAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t
|
|||||||
|
|
||||||
m_inputChannels = channels;
|
m_inputChannels = channels;
|
||||||
|
|
||||||
if (m_inputChannels < minch) {
|
if (m_inputChannels < minch)
|
||||||
|
{
|
||||||
|
m_forwardPtrs = new const float *[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
|
||||||
// We need a set of zero-valued buffers to add to the
|
// forwarded pointers
|
||||||
// forwarded pointers
|
m_buffer = new float*[minch - channels];
|
||||||
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];
|
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;
|
{
|
||||||
}
|
m_buffer[i][j] = 0.f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_pluginChannels = minch;
|
m_pluginChannels = minch;
|
||||||
|
|
||||||
// std::cerr << "PluginChannelAdapter::initialise: expanding " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl;
|
}
|
||||||
|
else if (m_inputChannels > maxch)
|
||||||
|
{
|
||||||
|
if (maxch == 1)
|
||||||
|
{
|
||||||
|
m_buffer = new float *[1];
|
||||||
|
m_buffer[0] = new float[blockSize];
|
||||||
|
}
|
||||||
|
|
||||||
} else if (m_inputChannels > maxch) {
|
m_pluginChannels = maxch;
|
||||||
|
|
||||||
// We only need m_buffer if we are mixing down to a single
|
}
|
||||||
// channel -- otherwise we can just forward the same float* as
|
else
|
||||||
// passed in to process(), expecting the excess to be ignored
|
{
|
||||||
|
m_pluginChannels = m_inputChannels;
|
||||||
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;
|
|
||||||
m_pluginChannels = m_inputChannels;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_plugin->initialise(m_pluginChannels, stepSize, blockSize);
|
return m_plugin->initialise(m_pluginChannels, stepSize, blockSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginChannelAdapter::FeatureSet
|
PluginChannelAdapter::FeatureSet PluginChannelAdapter::Impl::processInterleaved(const float *inputBuffers, real_time timestamp)
|
||||||
PluginChannelAdapter::Impl::processInterleaved(const float *inputBuffers,
|
{
|
||||||
RealTime timestamp)
|
if (!m_deinterleave)
|
||||||
{
|
{
|
||||||
if (!m_deinterleave) {
|
m_deinterleave = new float *[m_inputChannels];
|
||||||
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];
|
m_deinterleave[i] = new float[m_blockSize];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < m_inputChannels; ++i) {
|
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];
|
for (size_t j = 0; j < m_blockSize; ++j)
|
||||||
}
|
{
|
||||||
|
m_deinterleave[i][j] = inputBuffers[j * m_inputChannels + i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return process(m_deinterleave, timestamp);
|
return process(m_deinterleave, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginChannelAdapter::FeatureSet
|
PluginChannelAdapter::FeatureSet PluginChannelAdapter::Impl::process(const float *const *inputBuffers, real_time timestamp)
|
||||||
PluginChannelAdapter::Impl::process(const float *const *inputBuffers,
|
{
|
||||||
RealTime timestamp)
|
if (m_inputChannels < m_pluginChannels)
|
||||||
{
|
{
|
||||||
// std::cerr << "PluginChannelAdapter::process: " << m_inputChannels << " -> " << m_pluginChannels << " channels" << std::endl;
|
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)
|
||||||
|
{
|
||||||
|
m_forwardPtrs[i] = inputBuffers[i];
|
||||||
|
}
|
||||||
|
for (size_t i = m_inputChannels; i < m_pluginChannels; ++i)
|
||||||
|
{
|
||||||
|
m_forwardPtrs[i] = m_buffer[i - m_inputChannels];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_inputChannels < m_pluginChannels) {
|
return m_plugin->process(m_forwardPtrs, timestamp);
|
||||||
|
}
|
||||||
if (m_inputChannels == 1) {
|
else if (m_inputChannels > m_pluginChannels)
|
||||||
for (size_t i = 0; i < m_pluginChannels; ++i) {
|
{
|
||||||
m_forwardPtrs[i] = inputBuffers[0];
|
if (m_pluginChannels == 1)
|
||||||
}
|
{
|
||||||
} else {
|
for (size_t j = 0; j < m_blockSize; ++j)
|
||||||
for (size_t i = 0; i < m_inputChannels; ++i) {
|
{
|
||||||
m_forwardPtrs[i] = inputBuffers[i];
|
m_buffer[0][j] = inputBuffers[0][j];
|
||||||
}
|
|
||||||
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);
|
for (size_t i = 1; i < m_inputChannels; ++i)
|
||||||
|
{
|
||||||
} else if (m_inputChannels > m_pluginChannels) {
|
for (size_t j = 0; j < m_blockSize; ++j)
|
||||||
|
{
|
||||||
if (m_pluginChannels == 1) {
|
m_buffer[0][j] += inputBuffers[i][j];
|
||||||
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) {
|
|
||||||
m_buffer[0][j] += inputBuffers[i][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 {
|
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);
|
return m_plugin->process(inputBuffers, timestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return m_plugin->process(inputBuffers, timestamp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,104 +2,21 @@
|
|||||||
|
|
||||||
#include "vamp-hostsdk/PluginWrapper.h"
|
#include "vamp-hostsdk/PluginWrapper.h"
|
||||||
|
|
||||||
namespace Vamp {
|
namespace vamp::host
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class PluginChannelAdapter : public PluginWrapper
|
|
||||||
{
|
{
|
||||||
public:
|
class PluginChannelAdapter : public PluginWrapper
|
||||||
/**
|
{
|
||||||
* Construct a PluginChannelAdapter wrapping the given plugin.
|
public:
|
||||||
* The adapter takes ownership of the plugin, which will be
|
PluginChannelAdapter(plugin* p);
|
||||||
* deleted when the adapter is deleted.
|
virtual ~PluginChannelAdapter();
|
||||||
*/
|
|
||||||
PluginChannelAdapter(Plugin *plugin);
|
|
||||||
virtual ~PluginChannelAdapter();
|
|
||||||
|
|
||||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||||
|
|
||||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
FeatureSet process(const float *const *inputBuffers, real_time timestamp);
|
||||||
|
FeatureSet processInterleaved(const float *inputBuffer, real_time 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);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class Impl;
|
|
||||||
Impl *m_impl;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
class Impl;
|
||||||
|
Impl* m_impl;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -3,91 +3,60 @@
|
|||||||
|
|
||||||
#include "vamp-hostsdk/Files.h"
|
#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);
|
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()
|
PluginHostAdapter::~PluginHostAdapter()
|
||||||
{
|
{
|
||||||
// std::cerr << "PluginHostAdapter::~PluginHostAdapter (plugin = " << m_descriptor->name << ")" << std::endl;
|
|
||||||
if (m_handle) m_descriptor->cleanup(m_handle);
|
if (m_handle) m_descriptor->cleanup(m_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string>
|
std::vector<std::string> PluginHostAdapter::getPluginPath()
|
||||||
PluginHostAdapter::getPluginPath()
|
{
|
||||||
{
|
|
||||||
std::vector<std::string> path;
|
std::vector<std::string> path;
|
||||||
std::string envPath;
|
std::string envPath;
|
||||||
|
|
||||||
if (Files::isNonNative32Bit()) {
|
if (Files::isNonNative32Bit()) {
|
||||||
(void)Files::getEnvUtf8("VAMP_PATH_32", envPath);
|
(void)Files::getEnvUtf8("VAMP_PATH_32", envPath);
|
||||||
} else {
|
} else {
|
||||||
(void)Files::getEnvUtf8("VAMP_PATH", envPath);
|
(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"
|
#define DEFAULT_VAMP_PATH "$HOME/vamp:$HOME/.vamp:/usr/local/lib/vamp:/usr/lib/vamp"
|
||||||
#endif
|
#define PATH_SEPARATOR ':'
|
||||||
#endif
|
if (envPath == "")
|
||||||
|
{
|
||||||
if (envPath == "") {
|
envPath = DEFAULT_VAMP_PATH;
|
||||||
envPath = DEFAULT_VAMP_PATH;
|
std::string home;
|
||||||
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()) {
|
|
||||||
envPath.replace(f, 5, home);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef _WIN32
|
|
||||||
std::string pfiles;
|
|
||||||
if (!Files::getEnvUtf8("ProgramFiles", pfiles)) {
|
|
||||||
pfiles = "C:\\Program Files";
|
|
||||||
}
|
|
||||||
std::string::size_type f;
|
std::string::size_type f;
|
||||||
while ((f = envPath.find("%ProgramFiles%")) != std::string::npos &&
|
while ((f = envPath.find("$HOME")) != std::string::npos && f < envPath.length())
|
||||||
f < envPath.length()) {
|
{
|
||||||
envPath.replace(f, 14, pfiles);
|
envPath.replace(f, 5, home);
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string::size_type index = 0, newindex = 0;
|
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;
|
path.push_back(envPath.substr(index, newindex - index));
|
||||||
|
index = newindex + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
path.push_back(envPath.substr(index));
|
path.push_back(envPath.substr(index));
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool PluginHostAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
||||||
PluginHostAdapter::initialise(size_t channels,
|
{
|
||||||
size_t stepSize,
|
|
||||||
size_t blockSize)
|
|
||||||
{
|
|
||||||
if (!m_handle) return false;
|
if (!m_handle) return false;
|
||||||
return m_descriptor->initialise
|
return m_descriptor->initialise
|
||||||
(m_handle,
|
(m_handle,
|
||||||
@ -95,100 +64,72 @@ PluginHostAdapter::initialise(size_t channels,
|
|||||||
(unsigned int)stepSize,
|
(unsigned int)stepSize,
|
||||||
(unsigned int)blockSize) ?
|
(unsigned int)blockSize) ?
|
||||||
true : false;
|
true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void PluginHostAdapter::reset()
|
||||||
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);
|
m_descriptor->reset(m_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginHostAdapter::InputDomain
|
PluginHostAdapter::InputDomain PluginHostAdapter::getInputDomain() const
|
||||||
PluginHostAdapter::getInputDomain() const
|
{
|
||||||
{
|
if (m_descriptor->inputDomain == vampFrequencyDomain)
|
||||||
if (m_descriptor->inputDomain == vampFrequencyDomain) {
|
{
|
||||||
return FrequencyDomain;
|
return FrequencyDomain;
|
||||||
} else {
|
}
|
||||||
return TimeDomain;
|
else
|
||||||
|
{
|
||||||
|
return TimeDomain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
std::string PluginHostAdapter::get_identifier() const
|
||||||
PluginHostAdapter::getVampApiVersion() const
|
{
|
||||||
{
|
|
||||||
return m_descriptor->vampApiVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
|
||||||
PluginHostAdapter::getIdentifier() const
|
|
||||||
{
|
|
||||||
return m_descriptor->identifier;
|
return m_descriptor->identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string PluginHostAdapter::get_name() const
|
||||||
PluginHostAdapter::getName() const
|
{
|
||||||
{
|
|
||||||
return m_descriptor->name;
|
return m_descriptor->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string PluginHostAdapter::get_description() const
|
||||||
PluginHostAdapter::getDescription() const
|
{
|
||||||
{
|
|
||||||
return m_descriptor->description;
|
return m_descriptor->description;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string PluginHostAdapter::get_maker() const
|
||||||
PluginHostAdapter::getMaker() const
|
{
|
||||||
{
|
|
||||||
return m_descriptor->maker;
|
return m_descriptor->maker;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
PluginHostAdapter::parameter_descriptors PluginHostAdapter::get_parameter_descriptors() const
|
||||||
PluginHostAdapter::getPluginVersion() const
|
{
|
||||||
{
|
parameter_descriptors list;
|
||||||
return m_descriptor->pluginVersion;
|
for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
|
||||||
}
|
const VampParameterDescriptor *spd = m_descriptor->parameters[i];
|
||||||
|
parameter_descriptor pd;
|
||||||
|
pd.identifier = spd->identifier;
|
||||||
|
pd.name = spd->name;
|
||||||
|
pd.description = spd->description;
|
||||||
|
pd.unit = spd->unit;
|
||||||
|
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.value_names.push_back(spd->valueNames[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list.push_back(pd);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
std::string
|
float PluginHostAdapter::get_parameter(std::string param) const
|
||||||
PluginHostAdapter::getCopyright() const
|
{
|
||||||
{
|
|
||||||
return m_descriptor->copyright;
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginHostAdapter::ParameterList
|
|
||||||
PluginHostAdapter::getParameterDescriptors() const
|
|
||||||
{
|
|
||||||
ParameterList list;
|
|
||||||
for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
|
|
||||||
const VampParameterDescriptor *spd = m_descriptor->parameters[i];
|
|
||||||
ParameterDescriptor 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) {
|
|
||||||
for (unsigned int j = 0; spd->valueNames[j]; ++j) {
|
|
||||||
pd.valueNames.push_back(spd->valueNames[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list.push_back(pd);
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
float
|
|
||||||
PluginHostAdapter::getParameter(std::string param) const
|
|
||||||
{
|
|
||||||
if (!m_handle) return 0.0;
|
if (!m_handle) return 0.0;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
|
for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
|
||||||
@ -198,12 +139,10 @@ PluginHostAdapter::getParameter(std::string param) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void PluginHostAdapter::set_parameter(std::string param, float value)
|
||||||
PluginHostAdapter::setParameter(std::string param,
|
{
|
||||||
float value)
|
|
||||||
{
|
|
||||||
if (!m_handle) return;
|
if (!m_handle) return;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
|
for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
|
||||||
@ -212,213 +151,206 @@ PluginHostAdapter::setParameter(std::string param,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginHostAdapter::ProgramList
|
PluginHostAdapter::programs PluginHostAdapter::get_programs() const
|
||||||
PluginHostAdapter::getPrograms() const
|
{
|
||||||
{
|
programs list;
|
||||||
ProgramList list;
|
|
||||||
|
for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
|
||||||
for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
|
list.push_back(m_descriptor->programs[i]);
|
||||||
list.push_back(m_descriptor->programs[i]);
|
}
|
||||||
}
|
|
||||||
|
return list;
|
||||||
return list;
|
}
|
||||||
}
|
|
||||||
|
std::string PluginHostAdapter::get_current_program() const
|
||||||
std::string
|
{
|
||||||
PluginHostAdapter::getCurrentProgram() const
|
if (!m_handle) return "";
|
||||||
{
|
|
||||||
if (!m_handle) return "";
|
int pn = m_descriptor->getCurrentProgram(m_handle);
|
||||||
|
if (pn < (int)m_descriptor->programCount) {
|
||||||
int pn = m_descriptor->getCurrentProgram(m_handle);
|
return m_descriptor->programs[pn];
|
||||||
if (pn < (int)m_descriptor->programCount) {
|
} else {
|
||||||
return m_descriptor->programs[pn];
|
return "";
|
||||||
} else {
|
}
|
||||||
return "";
|
}
|
||||||
}
|
|
||||||
}
|
void PluginHostAdapter::select_program(std::string program)
|
||||||
|
{
|
||||||
void
|
if (!m_handle) return;
|
||||||
PluginHostAdapter::selectProgram(std::string program)
|
|
||||||
{
|
for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
|
||||||
if (!m_handle) return;
|
if (program == m_descriptor->programs[i]) {
|
||||||
|
m_descriptor->selectProgram(m_handle, i);
|
||||||
for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
|
return;
|
||||||
if (program == m_descriptor->programs[i]) {
|
}
|
||||||
m_descriptor->selectProgram(m_handle, i);
|
}
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
}
|
size_t PluginHostAdapter::getPreferredStepSize() const
|
||||||
}
|
{
|
||||||
|
if (!m_handle) return 0;
|
||||||
size_t
|
return m_descriptor->getPreferredStepSize(m_handle);
|
||||||
PluginHostAdapter::getPreferredStepSize() const
|
}
|
||||||
{
|
|
||||||
if (!m_handle) return 0;
|
size_t PluginHostAdapter::getPreferredBlockSize() const
|
||||||
return m_descriptor->getPreferredStepSize(m_handle);
|
{
|
||||||
}
|
if (!m_handle) return 0;
|
||||||
|
return m_descriptor->getPreferredBlockSize(m_handle);
|
||||||
size_t
|
}
|
||||||
PluginHostAdapter::getPreferredBlockSize() const
|
|
||||||
{
|
size_t PluginHostAdapter::getMinChannelCount() const
|
||||||
if (!m_handle) return 0;
|
{
|
||||||
return m_descriptor->getPreferredBlockSize(m_handle);
|
if (!m_handle) return 0;
|
||||||
}
|
return m_descriptor->getMinChannelCount(m_handle);
|
||||||
|
}
|
||||||
size_t
|
|
||||||
PluginHostAdapter::getMinChannelCount() const
|
size_t
|
||||||
{
|
PluginHostAdapter::getMaxChannelCount() const
|
||||||
if (!m_handle) return 0;
|
{
|
||||||
return m_descriptor->getMinChannelCount(m_handle);
|
if (!m_handle) return 0;
|
||||||
}
|
return m_descriptor->getMaxChannelCount(m_handle);
|
||||||
|
}
|
||||||
size_t
|
|
||||||
PluginHostAdapter::getMaxChannelCount() const
|
PluginHostAdapter::OutputList
|
||||||
{
|
PluginHostAdapter::getOutputDescriptors() const
|
||||||
if (!m_handle) return 0;
|
{
|
||||||
return m_descriptor->getMaxChannelCount(m_handle);
|
OutputList list;
|
||||||
}
|
if (!m_handle) {
|
||||||
|
// std::cerr << "PluginHostAdapter::getOutputDescriptors: no handle " << std::endl;
|
||||||
PluginHostAdapter::OutputList
|
return list;
|
||||||
PluginHostAdapter::getOutputDescriptors() const
|
}
|
||||||
{
|
|
||||||
OutputList list;
|
unsigned int count = m_descriptor->getOutputCount(m_handle);
|
||||||
if (!m_handle) {
|
|
||||||
// std::cerr << "PluginHostAdapter::getOutputDescriptors: no handle " << std::endl;
|
for (unsigned int i = 0; i < count; ++i) {
|
||||||
return list;
|
VampOutputDescriptor *sd = m_descriptor->getOutputDescriptor(m_handle, i);
|
||||||
}
|
OutputDescriptor d;
|
||||||
|
d.identifier = sd->identifier;
|
||||||
unsigned int count = m_descriptor->getOutputCount(m_handle);
|
d.name = sd->name;
|
||||||
|
d.description = sd->description;
|
||||||
for (unsigned int i = 0; i < count; ++i) {
|
d.unit = sd->unit;
|
||||||
VampOutputDescriptor *sd = m_descriptor->getOutputDescriptor(m_handle, i);
|
d.hasFixedBinCount = sd->hasFixedBinCount;
|
||||||
OutputDescriptor d;
|
d.binCount = sd->binCount;
|
||||||
d.identifier = sd->identifier;
|
if (d.hasFixedBinCount && sd->binNames) {
|
||||||
d.name = sd->name;
|
for (unsigned int j = 0; j < sd->binCount; ++j) {
|
||||||
d.description = sd->description;
|
d.binNames.push_back(sd->binNames[j] ? sd->binNames[j] : "");
|
||||||
d.unit = sd->unit;
|
}
|
||||||
d.hasFixedBinCount = sd->hasFixedBinCount;
|
}
|
||||||
d.binCount = sd->binCount;
|
d.hasKnownExtents = sd->hasKnownExtents;
|
||||||
if (d.hasFixedBinCount && sd->binNames) {
|
d.minValue = sd->minValue;
|
||||||
for (unsigned int j = 0; j < sd->binCount; ++j) {
|
d.maxValue = sd->maxValue;
|
||||||
d.binNames.push_back(sd->binNames[j] ? sd->binNames[j] : "");
|
d.isQuantized = sd->isQuantized;
|
||||||
}
|
d.quantizeStep = sd->quantizeStep;
|
||||||
}
|
|
||||||
d.hasKnownExtents = sd->hasKnownExtents;
|
switch (sd->sampleType) {
|
||||||
d.minValue = sd->minValue;
|
case vampOneSamplePerStep:
|
||||||
d.maxValue = sd->maxValue;
|
d.sampleType = OutputDescriptor::OneSamplePerStep; break;
|
||||||
d.isQuantized = sd->isQuantized;
|
case vampFixedSampleRate:
|
||||||
d.quantizeStep = sd->quantizeStep;
|
d.sampleType = OutputDescriptor::FixedSampleRate; break;
|
||||||
|
case vampVariableSampleRate:
|
||||||
switch (sd->sampleType) {
|
d.sampleType = OutputDescriptor::VariableSampleRate; break;
|
||||||
case vampOneSamplePerStep:
|
}
|
||||||
d.sampleType = OutputDescriptor::OneSamplePerStep; break;
|
|
||||||
case vampFixedSampleRate:
|
d.sampleRate = sd->sampleRate;
|
||||||
d.sampleType = OutputDescriptor::FixedSampleRate; break;
|
|
||||||
case vampVariableSampleRate:
|
if (m_descriptor->vampApiVersion >= 2) {
|
||||||
d.sampleType = OutputDescriptor::VariableSampleRate; break;
|
d.hasDuration = sd->hasDuration;
|
||||||
}
|
} else {
|
||||||
|
d.hasDuration = false;
|
||||||
d.sampleRate = sd->sampleRate;
|
}
|
||||||
|
|
||||||
if (m_descriptor->vampApiVersion >= 2) {
|
list.push_back(d);
|
||||||
d.hasDuration = sd->hasDuration;
|
|
||||||
} else {
|
m_descriptor->releaseOutputDescriptor(sd);
|
||||||
d.hasDuration = false;
|
}
|
||||||
}
|
|
||||||
|
return list;
|
||||||
list.push_back(d);
|
}
|
||||||
|
|
||||||
m_descriptor->releaseOutputDescriptor(sd);
|
PluginHostAdapter::FeatureSet
|
||||||
}
|
PluginHostAdapter::process(const float *const *inputBuffers,
|
||||||
|
real_time timestamp)
|
||||||
return list;
|
{
|
||||||
}
|
FeatureSet fs;
|
||||||
|
if (!m_handle) return fs;
|
||||||
PluginHostAdapter::FeatureSet
|
|
||||||
PluginHostAdapter::process(const float *const *inputBuffers,
|
int sec = timestamp.sec;
|
||||||
RealTime timestamp)
|
int nsec = timestamp.nsec;
|
||||||
{
|
|
||||||
FeatureSet fs;
|
VampFeatureList *features = m_descriptor->process(m_handle,
|
||||||
if (!m_handle) return fs;
|
inputBuffers,
|
||||||
|
sec, nsec);
|
||||||
int sec = timestamp.sec;
|
|
||||||
int nsec = timestamp.nsec;
|
convertFeatures(features, fs);
|
||||||
|
m_descriptor->releaseFeatureSet(features);
|
||||||
VampFeatureList *features = m_descriptor->process(m_handle,
|
return fs;
|
||||||
inputBuffers,
|
}
|
||||||
sec, nsec);
|
|
||||||
|
PluginHostAdapter::FeatureSet
|
||||||
convertFeatures(features, fs);
|
PluginHostAdapter::getRemainingFeatures()
|
||||||
m_descriptor->releaseFeatureSet(features);
|
{
|
||||||
return fs;
|
FeatureSet fs;
|
||||||
}
|
if (!m_handle) return fs;
|
||||||
|
|
||||||
PluginHostAdapter::FeatureSet
|
VampFeatureList *features = m_descriptor->getRemainingFeatures(m_handle);
|
||||||
PluginHostAdapter::getRemainingFeatures()
|
|
||||||
{
|
convertFeatures(features, fs);
|
||||||
FeatureSet fs;
|
m_descriptor->releaseFeatureSet(features);
|
||||||
if (!m_handle) return fs;
|
return fs;
|
||||||
|
}
|
||||||
VampFeatureList *features = m_descriptor->getRemainingFeatures(m_handle);
|
|
||||||
|
void
|
||||||
convertFeatures(features, fs);
|
PluginHostAdapter::convertFeatures(VampFeatureList *features,
|
||||||
m_descriptor->releaseFeatureSet(features);
|
FeatureSet &fs)
|
||||||
return fs;
|
{
|
||||||
}
|
if (!features) return;
|
||||||
|
|
||||||
void
|
unsigned int outputs = m_descriptor->getOutputCount(m_handle);
|
||||||
PluginHostAdapter::convertFeatures(VampFeatureList *features,
|
|
||||||
FeatureSet &fs)
|
for (unsigned int i = 0; i < outputs; ++i) {
|
||||||
{
|
|
||||||
if (!features) return;
|
VampFeatureList &list = features[i];
|
||||||
|
|
||||||
unsigned int outputs = m_descriptor->getOutputCount(m_handle);
|
if (list.featureCount > 0) {
|
||||||
|
|
||||||
for (unsigned int i = 0; i < outputs; ++i) {
|
Feature feature;
|
||||||
|
feature.values.reserve(list.features[0].v1.valueCount);
|
||||||
VampFeatureList &list = features[i];
|
|
||||||
|
for (unsigned int j = 0; j < list.featureCount; ++j) {
|
||||||
if (list.featureCount > 0) {
|
|
||||||
|
feature.hasTimestamp = list.features[j].v1.hasTimestamp;
|
||||||
Feature feature;
|
feature.timestamp = real_time(list.features[j].v1.sec,
|
||||||
feature.values.reserve(list.features[0].v1.valueCount);
|
list.features[j].v1.nsec);
|
||||||
|
feature.hasDuration = false;
|
||||||
for (unsigned int j = 0; j < list.featureCount; ++j) {
|
|
||||||
|
if (m_descriptor->vampApiVersion >= 2) {
|
||||||
feature.hasTimestamp = list.features[j].v1.hasTimestamp;
|
unsigned int j2 = j + list.featureCount;
|
||||||
feature.timestamp = RealTime(list.features[j].v1.sec,
|
feature.hasDuration = list.features[j2].v2.hasDuration;
|
||||||
list.features[j].v1.nsec);
|
feature.duration = real_time(list.features[j2].v2.durationSec,
|
||||||
feature.hasDuration = false;
|
list.features[j2].v2.durationNsec);
|
||||||
|
}
|
||||||
if (m_descriptor->vampApiVersion >= 2) {
|
|
||||||
unsigned int j2 = j + list.featureCount;
|
for (unsigned int k = 0; k < list.features[j].v1.valueCount; ++k) {
|
||||||
feature.hasDuration = list.features[j2].v2.hasDuration;
|
feature.values.push_back(list.features[j].v1.values[k]);
|
||||||
feature.duration = RealTime(list.features[j2].v2.durationSec,
|
}
|
||||||
list.features[j2].v2.durationNsec);
|
|
||||||
}
|
if (list.features[j].v1.label) {
|
||||||
|
feature.label = list.features[j].v1.label;
|
||||||
for (unsigned int k = 0; k < list.features[j].v1.valueCount; ++k) {
|
}
|
||||||
feature.values.push_back(list.features[j].v1.values[k]);
|
|
||||||
}
|
fs[i].push_back(feature);
|
||||||
|
|
||||||
if (list.features[j].v1.label) {
|
if (list.features[j].v1.valueCount > 0) {
|
||||||
feature.label = list.features[j].v1.label;
|
feature.values.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
fs[i].push_back(feature);
|
if (list.features[j].v1.label) {
|
||||||
|
feature.label = "";
|
||||||
if (list.features[j].v1.valueCount > 0) {
|
}
|
||||||
feature.values.clear();
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (list.features[j].v1.label) {
|
}
|
||||||
feature.label = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,72 +4,50 @@
|
|||||||
#include "vamp.h"
|
#include "vamp.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Vamp {
|
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
|
|
||||||
{
|
{
|
||||||
public:
|
class PluginHostAdapter : public plugin
|
||||||
PluginHostAdapter(const VampPluginDescriptor *descriptor,
|
{
|
||||||
float inputSampleRate);
|
public:
|
||||||
virtual ~PluginHostAdapter();
|
PluginHostAdapter(const VampPluginDescriptor* descriptor, float inputSampleRate);
|
||||||
|
virtual ~PluginHostAdapter();
|
||||||
static std::vector<std::string> getPluginPath();
|
|
||||||
|
static std::vector<std::string> getPluginPath();
|
||||||
|
|
||||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
bool initialise(size_t channels, size_t stepSize, size_t blockSize) override;
|
||||||
void reset();
|
void reset() override;
|
||||||
|
|
||||||
InputDomain getInputDomain() const;
|
InputDomain getInputDomain() const override;
|
||||||
|
|
||||||
unsigned int getVampApiVersion() const;
|
std::string get_identifier() const override;
|
||||||
std::string getIdentifier() const;
|
std::string get_name() const override;
|
||||||
std::string getName() const;
|
std::string get_description() const override;
|
||||||
std::string getDescription() const;
|
std::string get_maker() const override;
|
||||||
std::string getMaker() const;
|
|
||||||
int getPluginVersion() const;
|
|
||||||
std::string getCopyright() const;
|
|
||||||
|
|
||||||
ParameterList getParameterDescriptors() const;
|
parameter_descriptors get_parameter_descriptors() const override;
|
||||||
float getParameter(std::string) const;
|
float get_parameter(std::string) const override;
|
||||||
void setParameter(std::string, float);
|
void set_parameter(std::string, float) override;
|
||||||
|
|
||||||
ProgramList getPrograms() const;
|
programs get_programs() const override;
|
||||||
std::string getCurrentProgram() const;
|
std::string get_current_program() const override;
|
||||||
void selectProgram(std::string);
|
void select_program(std::string) override;
|
||||||
|
|
||||||
size_t getPreferredStepSize() const;
|
size_t getPreferredStepSize() const override;
|
||||||
size_t getPreferredBlockSize() const;
|
size_t getPreferredBlockSize() const override;
|
||||||
|
|
||||||
size_t getMinChannelCount() const;
|
size_t getMinChannelCount() const override;
|
||||||
size_t getMaxChannelCount() const;
|
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:
|
protected:
|
||||||
void convertFeatures(VampFeatureList *, FeatureSet &);
|
void convertFeatures(VampFeatureList *, FeatureSet &);
|
||||||
|
|
||||||
const VampPluginDescriptor *m_descriptor;
|
|
||||||
VampPluginHandle m_handle;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
const VampPluginDescriptor *m_descriptor;
|
||||||
|
VampPluginHandle m_handle;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,482 +1,472 @@
|
|||||||
#include "vamp-hostsdk/PluginInputDomainAdapter.h"
|
#include "vamp-hostsdk/PluginInputDomainAdapter.h"
|
||||||
|
#include "vamp-hostsdk/Window.h"
|
||||||
#include "vamp-sdk/ext/vamp_kiss_fft.h"
|
#include "vamp-sdk/ext/vamp_kiss_fft.h"
|
||||||
#include "vamp-sdk/ext/vamp_kiss_fftr.h"
|
#include "vamp-sdk/ext/vamp_kiss_fftr.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include "Window.h"
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
|
||||||
namespace Vamp {
|
namespace vamp::host
|
||||||
|
|
||||||
namespace HostExt {
|
|
||||||
|
|
||||||
class PluginInputDomainAdapter::Impl
|
|
||||||
{
|
{
|
||||||
public:
|
class PluginInputDomainAdapter::Impl
|
||||||
Impl(Plugin *plugin, float inputSampleRate);
|
{
|
||||||
~Impl();
|
public:
|
||||||
|
Impl(plugin* p, float inputSampleRate);
|
||||||
|
~Impl();
|
||||||
|
|
||||||
|
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
size_t getPreferredStepSize() const;
|
||||||
|
size_t getPreferredBlockSize() const;
|
||||||
|
|
||||||
|
FeatureSet process(const float *const *inputBuffers, real_time timestamp);
|
||||||
|
|
||||||
|
void setProcessTimestampMethod(ProcessTimestampMethod m);
|
||||||
|
ProcessTimestampMethod getProcessTimestampMethod() const;
|
||||||
|
|
||||||
|
real_time getTimestampAdjustment() const;
|
||||||
|
|
||||||
|
WindowType getWindowType() const;
|
||||||
|
void setWindowType(WindowType type);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
plugin* m_plugin;
|
||||||
|
float m_inputSampleRate;
|
||||||
|
int m_channels;
|
||||||
|
int m_stepSize;
|
||||||
|
int m_blockSize;
|
||||||
|
float **m_freqbuf;
|
||||||
|
vamp_kiss_fft_scalar *m_ri;
|
||||||
|
|
||||||
|
WindowType m_windowType;
|
||||||
|
typedef Window<vamp_kiss_fft_scalar> W;
|
||||||
|
W *m_window;
|
||||||
|
|
||||||
|
ProcessTimestampMethod m_method;
|
||||||
|
int m_processCount;
|
||||||
|
float **m_shiftBuffers;
|
||||||
|
|
||||||
|
vamp_kiss_fftr_cfg m_cfg;
|
||||||
|
vamp_kiss_fft_cpx *m_cbuf;
|
||||||
|
|
||||||
|
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* p) :
|
||||||
|
PluginWrapper(p)
|
||||||
|
{
|
||||||
|
m_impl = new Impl(p, m_inputSampleRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginInputDomainAdapter::~PluginInputDomainAdapter()
|
||||||
|
{
|
||||||
|
delete m_impl;
|
||||||
|
}
|
||||||
|
|
||||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
bool
|
||||||
void reset();
|
PluginInputDomainAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
||||||
|
{
|
||||||
|
return m_impl->initialise(channels, stepSize, blockSize);
|
||||||
|
}
|
||||||
|
|
||||||
size_t getPreferredStepSize() const;
|
void
|
||||||
size_t getPreferredBlockSize() const;
|
PluginInputDomainAdapter::reset()
|
||||||
|
{
|
||||||
|
m_impl->reset();
|
||||||
|
}
|
||||||
|
|
||||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
plugin::InputDomain PluginInputDomainAdapter::getInputDomain() const
|
||||||
|
{
|
||||||
|
return TimeDomain;
|
||||||
|
}
|
||||||
|
|
||||||
void setProcessTimestampMethod(ProcessTimestampMethod m);
|
size_t
|
||||||
ProcessTimestampMethod getProcessTimestampMethod() const;
|
PluginInputDomainAdapter::getPreferredStepSize() const
|
||||||
|
{
|
||||||
RealTime getTimestampAdjustment() const;
|
return m_impl->getPreferredStepSize();
|
||||||
|
}
|
||||||
|
|
||||||
WindowType getWindowType() const;
|
size_t
|
||||||
void setWindowType(WindowType type);
|
PluginInputDomainAdapter::getPreferredBlockSize() const
|
||||||
|
{
|
||||||
|
return m_impl->getPreferredBlockSize();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
plugin::FeatureSet
|
||||||
Plugin *m_plugin;
|
PluginInputDomainAdapter::process(const float *const *inputBuffers, real_time timestamp)
|
||||||
float m_inputSampleRate;
|
{
|
||||||
int m_channels;
|
return m_impl->process(inputBuffers, timestamp);
|
||||||
int m_stepSize;
|
}
|
||||||
int m_blockSize;
|
|
||||||
float **m_freqbuf;
|
|
||||||
vamp_kiss_fft_scalar *m_ri;
|
|
||||||
|
|
||||||
WindowType m_windowType;
|
void
|
||||||
typedef Window<vamp_kiss_fft_scalar> W;
|
PluginInputDomainAdapter::setProcessTimestampMethod(ProcessTimestampMethod m)
|
||||||
W *m_window;
|
{
|
||||||
|
m_impl->setProcessTimestampMethod(m);
|
||||||
|
}
|
||||||
|
|
||||||
ProcessTimestampMethod m_method;
|
PluginInputDomainAdapter::ProcessTimestampMethod
|
||||||
int m_processCount;
|
PluginInputDomainAdapter::getProcessTimestampMethod() const
|
||||||
float **m_shiftBuffers;
|
{
|
||||||
|
return m_impl->getProcessTimestampMethod();
|
||||||
|
}
|
||||||
|
|
||||||
vamp_kiss_fftr_cfg m_cfg;
|
real_time
|
||||||
vamp_kiss_fft_cpx *m_cbuf;
|
PluginInputDomainAdapter::getTimestampAdjustment() const
|
||||||
|
{
|
||||||
|
return m_impl->getTimestampAdjustment();
|
||||||
|
}
|
||||||
|
|
||||||
FeatureSet processShiftingTimestamp(const float *const *inputBuffers, RealTime timestamp);
|
PluginInputDomainAdapter::WindowType
|
||||||
FeatureSet processShiftingData(const float *const *inputBuffers, RealTime timestamp);
|
PluginInputDomainAdapter::getWindowType() const
|
||||||
|
{
|
||||||
|
return m_impl->getWindowType();
|
||||||
|
}
|
||||||
|
|
||||||
size_t makeBlockSizeAcceptable(size_t) const;
|
void
|
||||||
|
PluginInputDomainAdapter::setWindowType(WindowType w)
|
||||||
W::WindowType convertType(WindowType t) const;
|
{
|
||||||
};
|
m_impl->setWindowType(w);
|
||||||
|
}
|
||||||
PluginInputDomainAdapter::PluginInputDomainAdapter(Plugin *plugin) :
|
|
||||||
PluginWrapper(plugin)
|
|
||||||
{
|
|
||||||
m_impl = new Impl(plugin, m_inputSampleRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginInputDomainAdapter::~PluginInputDomainAdapter()
|
|
||||||
{
|
|
||||||
delete m_impl;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PluginInputDomainAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
|
||||||
{
|
|
||||||
return m_impl->initialise(channels, stepSize, blockSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PluginInputDomainAdapter::reset()
|
|
||||||
{
|
|
||||||
m_impl->reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
Plugin::InputDomain
|
|
||||||
PluginInputDomainAdapter::getInputDomain() const
|
|
||||||
{
|
|
||||||
return TimeDomain;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
|
||||||
PluginInputDomainAdapter::getPreferredStepSize() const
|
|
||||||
{
|
|
||||||
return m_impl->getPreferredStepSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
|
||||||
PluginInputDomainAdapter::getPreferredBlockSize() const
|
|
||||||
{
|
|
||||||
return m_impl->getPreferredBlockSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
Plugin::FeatureSet
|
|
||||||
PluginInputDomainAdapter::process(const float *const *inputBuffers, RealTime timestamp)
|
|
||||||
{
|
|
||||||
return m_impl->process(inputBuffers, timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PluginInputDomainAdapter::setProcessTimestampMethod(ProcessTimestampMethod m)
|
|
||||||
{
|
|
||||||
m_impl->setProcessTimestampMethod(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginInputDomainAdapter::ProcessTimestampMethod
|
|
||||||
PluginInputDomainAdapter::getProcessTimestampMethod() const
|
|
||||||
{
|
|
||||||
return m_impl->getProcessTimestampMethod();
|
|
||||||
}
|
|
||||||
|
|
||||||
RealTime
|
|
||||||
PluginInputDomainAdapter::getTimestampAdjustment() const
|
|
||||||
{
|
|
||||||
return m_impl->getTimestampAdjustment();
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginInputDomainAdapter::WindowType
|
|
||||||
PluginInputDomainAdapter::getWindowType() const
|
|
||||||
{
|
|
||||||
return m_impl->getWindowType();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PluginInputDomainAdapter::setWindowType(WindowType w)
|
|
||||||
{
|
|
||||||
m_impl->setWindowType(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PluginInputDomainAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
|
PluginInputDomainAdapter::Impl::Impl(plugin* p, float inputSampleRate) :
|
||||||
m_plugin(plugin),
|
m_plugin(p),
|
||||||
m_inputSampleRate(inputSampleRate),
|
m_inputSampleRate(inputSampleRate),
|
||||||
m_channels(0),
|
m_channels(0),
|
||||||
m_stepSize(0),
|
m_stepSize(0),
|
||||||
m_blockSize(0),
|
m_blockSize(0),
|
||||||
m_freqbuf(0),
|
m_freqbuf(0),
|
||||||
m_ri(0),
|
m_ri(0),
|
||||||
m_windowType(HanningWindow),
|
m_windowType(HanningWindow),
|
||||||
m_window(0),
|
m_window(0),
|
||||||
m_method(ShiftTimestamp),
|
m_method(ShiftTimestamp),
|
||||||
m_processCount(0),
|
m_processCount(0),
|
||||||
m_shiftBuffers(0),
|
m_shiftBuffers(0),
|
||||||
m_cfg(0),
|
m_cfg(0),
|
||||||
m_cbuf(0)
|
m_cbuf(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginInputDomainAdapter::Impl::~Impl()
|
PluginInputDomainAdapter::Impl::~Impl()
|
||||||
{
|
{
|
||||||
// the adapter will delete the plugin
|
// the adapter will delete the plugin
|
||||||
|
|
||||||
if (m_shiftBuffers) {
|
if (m_shiftBuffers) {
|
||||||
for (int c = 0; c < m_channels; ++c) {
|
for (int c = 0; c < m_channels; ++c) {
|
||||||
delete[] m_shiftBuffers[c];
|
delete[] m_shiftBuffers[c];
|
||||||
}
|
}
|
||||||
delete[] m_shiftBuffers;
|
delete[] m_shiftBuffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_channels > 0) {
|
if (m_channels > 0) {
|
||||||
for (int c = 0; c < m_channels; ++c) {
|
for (int c = 0; c < m_channels; ++c) {
|
||||||
delete[] m_freqbuf[c];
|
delete[] m_freqbuf[c];
|
||||||
}
|
}
|
||||||
delete[] m_freqbuf;
|
delete[] m_freqbuf;
|
||||||
delete[] m_ri;
|
delete[] m_ri;
|
||||||
if (m_cfg) {
|
if (m_cfg) {
|
||||||
vamp_kiss_fftr_free(m_cfg);
|
vamp_kiss_fftr_free(m_cfg);
|
||||||
m_cfg = 0;
|
m_cfg = 0;
|
||||||
delete[] m_cbuf;
|
delete[] m_cbuf;
|
||||||
m_cbuf = 0;
|
m_cbuf = 0;
|
||||||
}
|
}
|
||||||
delete m_window;
|
delete m_window;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// for some visual studii apparently
|
// for some visual studii apparently
|
||||||
#ifndef M_PI
|
#ifndef M_PI
|
||||||
#define M_PI 3.14159265358979232846
|
#define M_PI 3.14159265358979232846
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PluginInputDomainAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
PluginInputDomainAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
||||||
{
|
{
|
||||||
if (m_plugin->getInputDomain() == TimeDomain) {
|
if (m_plugin->getInputDomain() == TimeDomain) {
|
||||||
|
|
||||||
m_stepSize = int(stepSize);
|
m_stepSize = int(stepSize);
|
||||||
m_blockSize = int(blockSize);
|
m_blockSize = int(blockSize);
|
||||||
m_channels = int(channels);
|
m_channels = int(channels);
|
||||||
|
|
||||||
return m_plugin->initialise(channels, stepSize, blockSize);
|
return m_plugin->initialise(channels, stepSize, blockSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blockSize < 2) {
|
if (blockSize < 2) {
|
||||||
std::cerr << "ERROR: PluginInputDomainAdapter::initialise: blocksize < 2 not supported" << std::endl;
|
std::cerr << "ERROR: PluginInputDomainAdapter::initialise: blocksize < 2 not supported" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blockSize % 2) {
|
if (blockSize % 2) {
|
||||||
std::cerr << "ERROR: PluginInputDomainAdapter::initialise: odd blocksize " << blockSize << " not supported" << std::endl;
|
std::cerr << "ERROR: PluginInputDomainAdapter::initialise: odd blocksize " << blockSize << " not supported" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_channels > 0) {
|
if (m_channels > 0) {
|
||||||
for (int c = 0; c < m_channels; ++c) {
|
for (int c = 0; c < m_channels; ++c) {
|
||||||
delete[] m_freqbuf[c];
|
delete[] m_freqbuf[c];
|
||||||
}
|
}
|
||||||
delete[] m_freqbuf;
|
delete[] m_freqbuf;
|
||||||
delete[] m_ri;
|
delete[] m_ri;
|
||||||
if (m_cfg) {
|
if (m_cfg) {
|
||||||
vamp_kiss_fftr_free(m_cfg);
|
vamp_kiss_fftr_free(m_cfg);
|
||||||
m_cfg = 0;
|
m_cfg = 0;
|
||||||
delete[] m_cbuf;
|
delete[] m_cbuf;
|
||||||
m_cbuf = 0;
|
m_cbuf = 0;
|
||||||
}
|
}
|
||||||
delete m_window;
|
delete m_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_stepSize = int(stepSize);
|
m_stepSize = int(stepSize);
|
||||||
m_blockSize = int(blockSize);
|
m_blockSize = int(blockSize);
|
||||||
m_channels = int(channels);
|
m_channels = int(channels);
|
||||||
|
|
||||||
m_freqbuf = new float *[m_channels];
|
m_freqbuf = new float *[m_channels];
|
||||||
for (int c = 0; c < m_channels; ++c) {
|
for (int c = 0; c < m_channels; ++c) {
|
||||||
m_freqbuf[c] = new float[m_blockSize + 2];
|
m_freqbuf[c] = new float[m_blockSize + 2];
|
||||||
}
|
}
|
||||||
m_ri = new vamp_kiss_fft_scalar[m_blockSize];
|
m_ri = new vamp_kiss_fft_scalar[m_blockSize];
|
||||||
|
|
||||||
m_window = new W(convertType(m_windowType), m_blockSize);
|
m_window = new W(convertType(m_windowType), m_blockSize);
|
||||||
|
|
||||||
m_cfg = vamp_kiss_fftr_alloc(m_blockSize, false, 0, 0);
|
m_cfg = vamp_kiss_fftr_alloc(m_blockSize, false, 0, 0);
|
||||||
m_cbuf = new vamp_kiss_fft_cpx[m_blockSize/2+1];
|
m_cbuf = new vamp_kiss_fft_cpx[m_blockSize/2+1];
|
||||||
|
|
||||||
m_processCount = 0;
|
m_processCount = 0;
|
||||||
|
|
||||||
return m_plugin->initialise(channels, stepSize, m_blockSize);
|
return m_plugin->initialise(channels, stepSize, m_blockSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PluginInputDomainAdapter::Impl::reset()
|
PluginInputDomainAdapter::Impl::reset()
|
||||||
{
|
{
|
||||||
m_processCount = 0;
|
m_processCount = 0;
|
||||||
m_plugin->reset();
|
m_plugin->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
PluginInputDomainAdapter::Impl::getPreferredStepSize() const
|
PluginInputDomainAdapter::Impl::getPreferredStepSize() const
|
||||||
{
|
{
|
||||||
size_t step = m_plugin->getPreferredStepSize();
|
size_t step = m_plugin->getPreferredStepSize();
|
||||||
|
|
||||||
if (step == 0 && (m_plugin->getInputDomain() == FrequencyDomain)) {
|
if (step == 0 && (m_plugin->getInputDomain() == FrequencyDomain)) {
|
||||||
step = getPreferredBlockSize() / 2;
|
step = getPreferredBlockSize() / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return step;
|
return step;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
PluginInputDomainAdapter::Impl::getPreferredBlockSize() const
|
PluginInputDomainAdapter::Impl::getPreferredBlockSize() const
|
||||||
{
|
{
|
||||||
size_t block = m_plugin->getPreferredBlockSize();
|
size_t block = m_plugin->getPreferredBlockSize();
|
||||||
|
|
||||||
if (m_plugin->getInputDomain() == FrequencyDomain) {
|
if (m_plugin->getInputDomain() == FrequencyDomain) {
|
||||||
if (block == 0) {
|
if (block == 0) {
|
||||||
block = 1024;
|
block = 1024;
|
||||||
} else {
|
} else {
|
||||||
block = makeBlockSizeAcceptable(block);
|
block = makeBlockSizeAcceptable(block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
PluginInputDomainAdapter::Impl::makeBlockSizeAcceptable(size_t blockSize) const
|
PluginInputDomainAdapter::Impl::makeBlockSizeAcceptable(size_t blockSize) const
|
||||||
{
|
{
|
||||||
if (blockSize < 2) {
|
if (blockSize < 2) {
|
||||||
|
|
||||||
std::cerr << "WARNING: PluginInputDomainAdapter::initialise: blocksize < 2 not" << std::endl
|
std::cerr << "WARNING: PluginInputDomainAdapter::initialise: blocksize < 2 not" << std::endl
|
||||||
<< "supported, increasing from " << blockSize << " to 2" << std::endl;
|
<< "supported, increasing from " << blockSize << " to 2" << std::endl;
|
||||||
blockSize = 2;
|
blockSize = 2;
|
||||||
|
|
||||||
} else if (blockSize % 2) {
|
} else if (blockSize % 2) {
|
||||||
|
|
||||||
std::cerr << "WARNING: PluginInputDomainAdapter::initialise: odd blocksize not" << std::endl
|
std::cerr << "WARNING: PluginInputDomainAdapter::initialise: odd blocksize not" << std::endl
|
||||||
<< "supported, increasing from " << blockSize << " to " << (blockSize+1) << std::endl;
|
<< "supported, increasing from " << blockSize << " to " << (blockSize+1) << std::endl;
|
||||||
blockSize = blockSize+1;
|
blockSize = blockSize+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return blockSize;
|
return blockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
RealTime
|
real_time PluginInputDomainAdapter::Impl::getTimestampAdjustment() const
|
||||||
PluginInputDomainAdapter::Impl::getTimestampAdjustment() const
|
{
|
||||||
{
|
if (m_plugin->getInputDomain() == TimeDomain) {
|
||||||
if (m_plugin->getInputDomain() == TimeDomain) {
|
return real_time::zero_time;
|
||||||
return RealTime::zeroTime;
|
} else if (m_method == ShiftData || m_method == NoShift) {
|
||||||
} else if (m_method == ShiftData || m_method == NoShift) {
|
return real_time::zero_time;
|
||||||
return RealTime::zeroTime;
|
} else {
|
||||||
} else {
|
return real_time::f2rt(m_blockSize/2, int(m_inputSampleRate + 0.5));
|
||||||
return RealTime::frame2RealTime
|
}
|
||||||
(m_blockSize/2, int(m_inputSampleRate + 0.5));
|
}
|
||||||
}
|
|
||||||
}
|
void
|
||||||
|
PluginInputDomainAdapter::Impl::setProcessTimestampMethod(ProcessTimestampMethod m)
|
||||||
void
|
{
|
||||||
PluginInputDomainAdapter::Impl::setProcessTimestampMethod(ProcessTimestampMethod m)
|
m_method = m;
|
||||||
{
|
}
|
||||||
m_method = m;
|
|
||||||
}
|
PluginInputDomainAdapter::ProcessTimestampMethod
|
||||||
|
PluginInputDomainAdapter::Impl::getProcessTimestampMethod() const
|
||||||
PluginInputDomainAdapter::ProcessTimestampMethod
|
{
|
||||||
PluginInputDomainAdapter::Impl::getProcessTimestampMethod() const
|
return m_method;
|
||||||
{
|
}
|
||||||
return m_method;
|
|
||||||
}
|
void
|
||||||
|
PluginInputDomainAdapter::Impl::setWindowType(WindowType t)
|
||||||
void
|
{
|
||||||
PluginInputDomainAdapter::Impl::setWindowType(WindowType t)
|
if (m_windowType == t) return;
|
||||||
{
|
m_windowType = t;
|
||||||
if (m_windowType == t) return;
|
if (m_window) {
|
||||||
m_windowType = t;
|
delete m_window;
|
||||||
if (m_window) {
|
m_window = new W(convertType(m_windowType), m_blockSize);
|
||||||
delete m_window;
|
}
|
||||||
m_window = new W(convertType(m_windowType), m_blockSize);
|
}
|
||||||
}
|
|
||||||
}
|
PluginInputDomainAdapter::WindowType
|
||||||
|
PluginInputDomainAdapter::Impl::getWindowType() const
|
||||||
PluginInputDomainAdapter::WindowType
|
{
|
||||||
PluginInputDomainAdapter::Impl::getWindowType() const
|
return m_windowType;
|
||||||
{
|
}
|
||||||
return m_windowType;
|
|
||||||
}
|
PluginInputDomainAdapter::Impl::W::WindowType
|
||||||
|
PluginInputDomainAdapter::Impl::convertType(WindowType t) const
|
||||||
PluginInputDomainAdapter::Impl::W::WindowType
|
{
|
||||||
PluginInputDomainAdapter::Impl::convertType(WindowType t) const
|
switch (t) {
|
||||||
{
|
case RectangularWindow:
|
||||||
switch (t) {
|
return W::RectangularWindow;
|
||||||
case RectangularWindow:
|
case BartlettWindow:
|
||||||
return W::RectangularWindow;
|
return W::BartlettWindow;
|
||||||
case BartlettWindow:
|
case HammingWindow:
|
||||||
return W::BartlettWindow;
|
return W::HammingWindow;
|
||||||
case HammingWindow:
|
case HanningWindow:
|
||||||
return W::HammingWindow;
|
return W::HanningWindow;
|
||||||
case HanningWindow:
|
case BlackmanWindow:
|
||||||
return W::HanningWindow;
|
return W::BlackmanWindow;
|
||||||
case BlackmanWindow:
|
case NuttallWindow:
|
||||||
return W::BlackmanWindow;
|
return W::NuttallWindow;
|
||||||
case NuttallWindow:
|
case BlackmanHarrisWindow:
|
||||||
return W::NuttallWindow;
|
return W::BlackmanHarrisWindow;
|
||||||
case BlackmanHarrisWindow:
|
default:
|
||||||
return W::BlackmanHarrisWindow;
|
return W::HanningWindow;
|
||||||
default:
|
}
|
||||||
return W::HanningWindow;
|
}
|
||||||
}
|
|
||||||
}
|
plugin::FeatureSet
|
||||||
|
PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers,
|
||||||
Plugin::FeatureSet
|
real_time timestamp)
|
||||||
PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers,
|
{
|
||||||
RealTime timestamp)
|
if (m_plugin->getInputDomain() == TimeDomain) {
|
||||||
{
|
return m_plugin->process(inputBuffers, timestamp);
|
||||||
if (m_plugin->getInputDomain() == TimeDomain) {
|
}
|
||||||
return m_plugin->process(inputBuffers, timestamp);
|
|
||||||
}
|
if (m_method == ShiftTimestamp || m_method == NoShift) {
|
||||||
|
return processShiftingTimestamp(inputBuffers, timestamp);
|
||||||
if (m_method == ShiftTimestamp || m_method == NoShift) {
|
} else {
|
||||||
return processShiftingTimestamp(inputBuffers, timestamp);
|
return processShiftingData(inputBuffers, timestamp);
|
||||||
} else {
|
}
|
||||||
return processShiftingData(inputBuffers, timestamp);
|
}
|
||||||
}
|
|
||||||
}
|
plugin::FeatureSet
|
||||||
|
PluginInputDomainAdapter::Impl::processShiftingTimestamp(const float *const *inputBuffers,
|
||||||
Plugin::FeatureSet
|
real_time timestamp)
|
||||||
PluginInputDomainAdapter::Impl::processShiftingTimestamp(const float *const *inputBuffers,
|
{
|
||||||
RealTime timestamp)
|
unsigned int roundedRate = 1;
|
||||||
{
|
if (m_inputSampleRate > 0.f) {
|
||||||
unsigned int roundedRate = 1;
|
roundedRate = (unsigned int)round(m_inputSampleRate);
|
||||||
if (m_inputSampleRate > 0.f) {
|
}
|
||||||
roundedRate = (unsigned int)round(m_inputSampleRate);
|
|
||||||
}
|
if (m_method == ShiftTimestamp) {
|
||||||
|
// we may need to add one nsec if timestamp +
|
||||||
if (m_method == ShiftTimestamp) {
|
// getTimestampAdjustment() rounds down
|
||||||
// we may need to add one nsec if timestamp +
|
timestamp = timestamp + getTimestampAdjustment();
|
||||||
// getTimestampAdjustment() rounds down
|
real_time nsec(0, 1);
|
||||||
timestamp = timestamp + getTimestampAdjustment();
|
if (real_time::rt2f(timestamp, roundedRate) <
|
||||||
RealTime nsec(0, 1);
|
real_time::rt2f(timestamp + nsec, roundedRate)) {
|
||||||
if (RealTime::realTime2Frame(timestamp, roundedRate) <
|
timestamp = timestamp + nsec;
|
||||||
RealTime::realTime2Frame(timestamp + nsec, roundedRate)) {
|
}
|
||||||
timestamp = timestamp + nsec;
|
}
|
||||||
}
|
|
||||||
}
|
for (int c = 0; c < m_channels; ++c) {
|
||||||
|
|
||||||
for (int c = 0; c < m_channels; ++c) {
|
m_window->cut(inputBuffers[c], m_ri);
|
||||||
|
|
||||||
m_window->cut(inputBuffers[c], m_ri);
|
for (int i = 0; i < m_blockSize/2; ++i) {
|
||||||
|
// FFT shift
|
||||||
for (int i = 0; i < m_blockSize/2; ++i) {
|
vamp_kiss_fft_scalar value = m_ri[i];
|
||||||
// FFT shift
|
m_ri[i] = m_ri[i + m_blockSize/2];
|
||||||
vamp_kiss_fft_scalar value = m_ri[i];
|
m_ri[i + m_blockSize/2] = value;
|
||||||
m_ri[i] = m_ri[i + m_blockSize/2];
|
}
|
||||||
m_ri[i + m_blockSize/2] = value;
|
|
||||||
}
|
vamp_kiss_fftr(m_cfg, m_ri, m_cbuf);
|
||||||
|
|
||||||
vamp_kiss_fftr(m_cfg, m_ri, m_cbuf);
|
for (int i = 0; i <= m_blockSize/2; ++i) {
|
||||||
|
m_freqbuf[c][i * 2] = float(m_cbuf[i].r);
|
||||||
for (int i = 0; i <= m_blockSize/2; ++i) {
|
m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i].i);
|
||||||
m_freqbuf[c][i * 2] = float(m_cbuf[i].r);
|
}
|
||||||
m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i].i);
|
}
|
||||||
}
|
|
||||||
}
|
return m_plugin->process(m_freqbuf, timestamp);
|
||||||
|
}
|
||||||
return m_plugin->process(m_freqbuf, timestamp);
|
|
||||||
}
|
plugin::FeatureSet
|
||||||
|
PluginInputDomainAdapter::Impl::processShiftingData(const float *const *inputBuffers,
|
||||||
Plugin::FeatureSet
|
real_time timestamp)
|
||||||
PluginInputDomainAdapter::Impl::processShiftingData(const float *const *inputBuffers,
|
{
|
||||||
RealTime timestamp)
|
if (m_processCount == 0) {
|
||||||
{
|
if (!m_shiftBuffers) {
|
||||||
if (m_processCount == 0) {
|
m_shiftBuffers = new float *[m_channels];
|
||||||
if (!m_shiftBuffers) {
|
for (int c = 0; c < m_channels; ++c) {
|
||||||
m_shiftBuffers = new float *[m_channels];
|
m_shiftBuffers[c] = new float[m_blockSize + m_blockSize/2];
|
||||||
for (int c = 0; c < m_channels; ++c) {
|
}
|
||||||
m_shiftBuffers[c] = new float[m_blockSize + m_blockSize/2];
|
}
|
||||||
}
|
for (int c = 0; c < m_channels; ++c) {
|
||||||
}
|
for (int i = 0; i < m_blockSize + m_blockSize/2; ++i) {
|
||||||
for (int c = 0; c < m_channels; ++c) {
|
m_shiftBuffers[c][i] = 0.f;
|
||||||
for (int i = 0; i < m_blockSize + m_blockSize/2; ++i) {
|
}
|
||||||
m_shiftBuffers[c][i] = 0.f;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
for (int c = 0; c < m_channels; ++c) {
|
||||||
|
for (int i = m_stepSize; i < m_blockSize + m_blockSize/2; ++i) {
|
||||||
for (int c = 0; c < m_channels; ++c) {
|
m_shiftBuffers[c][i - m_stepSize] = m_shiftBuffers[c][i];
|
||||||
for (int i = m_stepSize; i < m_blockSize + m_blockSize/2; ++i) {
|
}
|
||||||
m_shiftBuffers[c][i - m_stepSize] = m_shiftBuffers[c][i];
|
for (int i = 0; i < m_blockSize; ++i) {
|
||||||
}
|
m_shiftBuffers[c][i + m_blockSize/2] = inputBuffers[c][i];
|
||||||
for (int i = 0; i < m_blockSize; ++i) {
|
}
|
||||||
m_shiftBuffers[c][i + m_blockSize/2] = inputBuffers[c][i];
|
}
|
||||||
}
|
|
||||||
}
|
for (int c = 0; c < m_channels; ++c) {
|
||||||
|
|
||||||
for (int c = 0; c < m_channels; ++c) {
|
m_window->cut(m_shiftBuffers[c], m_ri);
|
||||||
|
|
||||||
m_window->cut(m_shiftBuffers[c], m_ri);
|
for (int i = 0; i < m_blockSize/2; ++i) {
|
||||||
|
// FFT shift
|
||||||
for (int i = 0; i < m_blockSize/2; ++i) {
|
vamp_kiss_fft_scalar value = m_ri[i];
|
||||||
// FFT shift
|
m_ri[i] = m_ri[i + m_blockSize/2];
|
||||||
vamp_kiss_fft_scalar value = m_ri[i];
|
m_ri[i + m_blockSize/2] = value;
|
||||||
m_ri[i] = m_ri[i + m_blockSize/2];
|
}
|
||||||
m_ri[i + m_blockSize/2] = value;
|
|
||||||
}
|
vamp_kiss_fftr(m_cfg, m_ri, m_cbuf);
|
||||||
|
|
||||||
vamp_kiss_fftr(m_cfg, m_ri, m_cbuf);
|
for (int i = 0; i <= m_blockSize/2; ++i) {
|
||||||
|
m_freqbuf[c][i * 2] = float(m_cbuf[i].r);
|
||||||
for (int i = 0; i <= m_blockSize/2; ++i) {
|
m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i].i);
|
||||||
m_freqbuf[c][i * 2] = float(m_cbuf[i].r);
|
}
|
||||||
m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i].i);
|
}
|
||||||
}
|
|
||||||
}
|
++m_processCount;
|
||||||
|
|
||||||
++m_processCount;
|
return m_plugin->process(m_freqbuf, timestamp);
|
||||||
|
}
|
||||||
return m_plugin->process(m_freqbuf, timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,190 +2,58 @@
|
|||||||
|
|
||||||
#include "vamp-hostsdk/PluginWrapper.h"
|
#include "vamp-hostsdk/PluginWrapper.h"
|
||||||
|
|
||||||
namespace Vamp {
|
namespace vamp::host
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class PluginInputDomainAdapter : public PluginWrapper
|
|
||||||
{
|
{
|
||||||
public:
|
class PluginInputDomainAdapter : public PluginWrapper
|
||||||
/**
|
{
|
||||||
* Construct a PluginInputDomainAdapter wrapping the given plugin.
|
public:
|
||||||
* The adapter takes ownership of the plugin, which will be
|
PluginInputDomainAdapter(plugin* p);
|
||||||
* deleted when the adapter is deleted.
|
virtual ~PluginInputDomainAdapter();
|
||||||
*/
|
|
||||||
PluginInputDomainAdapter(Plugin *plugin);
|
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||||
virtual ~PluginInputDomainAdapter();
|
void reset();
|
||||||
|
|
||||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
InputDomain getInputDomain() const;
|
InputDomain getInputDomain() const;
|
||||||
|
|
||||||
size_t getPreferredStepSize() const;
|
size_t getPreferredStepSize() const;
|
||||||
size_t getPreferredBlockSize() const;
|
size_t getPreferredBlockSize() const;
|
||||||
|
|
||||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
FeatureSet process(const float *const *inputBuffers, real_time timestamp);
|
||||||
|
|
||||||
/**
|
enum ProcessTimestampMethod {
|
||||||
* ProcessTimestampMethod determines how the
|
ShiftTimestamp,
|
||||||
* PluginInputDomainAdapter handles timestamps for the data passed
|
ShiftData,
|
||||||
* to the process() function of the plugin it wraps, in the case
|
NoShift
|
||||||
* 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
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
void setProcessTimestampMethod(ProcessTimestampMethod);
|
||||||
* Set the method used for timestamp adjustment in plugins taking
|
ProcessTimestampMethod getProcessTimestampMethod() const;
|
||||||
* frequency-domain input. See the ProcessTimestampMethod
|
real_time getTimestampAdjustment() const;
|
||||||
* documentation for details.
|
|
||||||
*
|
|
||||||
* This function must be called before the first call to
|
|
||||||
* process().
|
|
||||||
*/
|
|
||||||
void setProcessTimestampMethod(ProcessTimestampMethod);
|
|
||||||
|
|
||||||
/**
|
enum WindowType {
|
||||||
* Retrieve the method used for timestamp adjustment in plugins
|
|
||||||
* taking frequency-domain input. See the ProcessTimestampMethod
|
|
||||||
* documentation for details.
|
|
||||||
*/
|
|
||||||
ProcessTimestampMethod getProcessTimestampMethod() const;
|
|
||||||
|
|
||||||
/**
|
RectangularWindow = 0,
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
BartlettWindow = 1, /// synonym for RectangularWindow
|
||||||
* The set of supported window shapes.
|
TriangularWindow = 1, /// synonym for BartlettWindow
|
||||||
*/
|
|
||||||
enum WindowType {
|
|
||||||
|
|
||||||
RectangularWindow = 0,
|
HammingWindow = 2,
|
||||||
|
|
||||||
BartlettWindow = 1, /// synonym for RectangularWindow
|
HanningWindow = 3, /// synonym for HannWindow
|
||||||
TriangularWindow = 1, /// synonym for BartlettWindow
|
HannWindow = 3, /// synonym for HanningWindow
|
||||||
|
|
||||||
HammingWindow = 2,
|
BlackmanWindow = 4,
|
||||||
|
|
||||||
HanningWindow = 3, /// synonym for HannWindow
|
NuttallWindow = 7,
|
||||||
HannWindow = 3, /// synonym for HanningWindow
|
|
||||||
|
|
||||||
BlackmanWindow = 4,
|
BlackmanHarrisWindow = 8
|
||||||
|
};
|
||||||
|
|
||||||
NuttallWindow = 7,
|
WindowType getWindowType() const;
|
||||||
|
void setWindowType(WindowType type);
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
protected:
|
||||||
|
class Impl;
|
||||||
|
Impl *m_impl;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,235 +1,52 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "vamp-sdk/Plugin.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "vamp-hostsdk/PluginWrapper.h"
|
namespace vamp::host
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class PluginLoader
|
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Obtain a pointer to the singleton instance of PluginLoader.
|
|
||||||
* Use this to obtain your loader object.
|
|
||||||
*/
|
|
||||||
static PluginLoader *getInstance();
|
|
||||||
|
|
||||||
/**
|
class PluginLoader
|
||||||
* PluginKey is a string type that is used to identify a plugin
|
{
|
||||||
* uniquely within the scope of "the current system". It consists
|
public:
|
||||||
* of the lower-cased base name of the plugin library, a colon
|
static PluginLoader *getInstance();
|
||||||
* separator, and the identifier string for the plugin. It is
|
typedef std::string PluginKey;
|
||||||
* only meaningful in the context of a given plugin path (the one
|
typedef std::vector<PluginKey> PluginKeyList;
|
||||||
* returned by PluginHostAdapter::getPluginPath()).
|
typedef std::vector<std::string> PluginCategoryHierarchy;
|
||||||
*
|
PluginKeyList listPlugins();
|
||||||
* 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 listPluginsIn(std::vector<std::string> libraryNames);
|
||||||
* PluginKeyList is a sequence of plugin keys, such as returned by
|
PluginKeyList listPluginsNotIn(std::vector<std::string> libraryNames);
|
||||||
* listPlugins().
|
enum AdapterFlags {
|
||||||
*/
|
|
||||||
typedef std::vector<PluginKey> PluginKeyList;
|
|
||||||
|
|
||||||
/**
|
ADAPT_INPUT_DOMAIN = 0x01,
|
||||||
* PluginCategoryHierarchy is a sequence of general->specific
|
ADAPT_CHANNEL_COUNT = 0x02,
|
||||||
* category names, as may be associated with a single plugin.
|
ADAPT_BUFFER_SIZE = 0x04,
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
ADAPT_ALL_SAFE = 0x03,
|
||||||
* Search for all available Vamp plugins, and return a list of
|
|
||||||
* them in the order in which they were found.
|
|
||||||
*/
|
|
||||||
PluginKeyList listPlugins();
|
|
||||||
|
|
||||||
/**
|
ADAPT_ALL = 0xff
|
||||||
* 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);
|
|
||||||
|
|
||||||
/**
|
plugin *loadPlugin(PluginKey key,
|
||||||
* Search for available Vamp plugins in libraries other than those
|
float inputSampleRate,
|
||||||
* with the given library names, and return a list of them in the
|
int adapterFlags = 0);
|
||||||
* order in which they were found. Do not attempt to load any of
|
|
||||||
* the libraries named.
|
PluginKey composePluginKey(std::string libraryName,
|
||||||
*
|
std::string identifier);
|
||||||
* 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);
|
|
||||||
|
|
||||||
/**
|
PluginCategoryHierarchy getPluginCategory(PluginKey plugin);
|
||||||
* AdapterFlags contains a set of values that may be OR'd together
|
std::string getLibraryPathForPlugin(PluginKey plugin);
|
||||||
* 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,
|
protected:
|
||||||
ADAPT_CHANNEL_COUNT = 0x02,
|
PluginLoader();
|
||||||
ADAPT_BUFFER_SIZE = 0x04,
|
virtual ~PluginLoader();
|
||||||
|
|
||||||
ADAPT_ALL_SAFE = 0x03,
|
class Impl;
|
||||||
|
Impl *m_impl;
|
||||||
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,
|
|
||||||
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:
|
|
||||||
PluginLoader();
|
|
||||||
virtual ~PluginLoader();
|
|
||||||
|
|
||||||
class Impl;
|
|
||||||
Impl *m_impl;
|
|
||||||
|
|
||||||
static PluginLoader *m_instance;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
static PluginLoader *m_instance;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -4,80 +4,26 @@
|
|||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
namespace Vamp {
|
namespace vamp::host
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class PluginSummarisingAdapter : public PluginWrapper
|
|
||||||
{
|
{
|
||||||
public:
|
class PluginSummarisingAdapter : public PluginWrapper
|
||||||
/**
|
{
|
||||||
* Construct a PluginSummarisingAdapter wrapping the given plugin.
|
public:
|
||||||
* The adapter takes ownership of the plugin, which will be
|
PluginSummarisingAdapter(plugin* p);
|
||||||
* deleted when the adapter is deleted.
|
virtual ~PluginSummarisingAdapter();
|
||||||
*/
|
|
||||||
PluginSummarisingAdapter(Plugin *plugin);
|
|
||||||
virtual ~PluginSummarisingAdapter();
|
|
||||||
|
|
||||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
FeatureSet process(const float *const *inputBuffers, real_time timestamp);
|
||||||
FeatureSet getRemainingFeatures();
|
FeatureSet getRemainingFeatures();
|
||||||
|
|
||||||
typedef std::set<RealTime> SegmentBoundaries;
|
typedef std::set<real_time> SegmentBoundaries;
|
||||||
|
|
||||||
/**
|
void setSummarySegmentBoundaries(const 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 {
|
enum SummaryType {
|
||||||
Minimum = 0,
|
Minimum = 0,
|
||||||
Maximum = 1,
|
Maximum = 1,
|
||||||
Mean = 2,
|
Mean = 2,
|
||||||
@ -89,64 +35,19 @@ public:
|
|||||||
Count = 8,
|
Count = 8,
|
||||||
|
|
||||||
UnknownSummaryType = 999
|
UnknownSummaryType = 999
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
enum AveragingMethod
|
||||||
* 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 {
|
|
||||||
SampleAverage = 0,
|
SampleAverage = 0,
|
||||||
ContinuousTimeAverage = 1
|
ContinuousTimeAverage = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
FeatureList getSummaryForOutput(int output, SummaryType type, AveragingMethod method = SampleAverage);
|
||||||
* Return summaries of the features that were returned on the
|
FeatureSet getSummaryForAllOutputs(SummaryType type, AveragingMethod method = SampleAverage);
|
||||||
* 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);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class Impl;
|
|
||||||
Impl *m_impl;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
class Impl;
|
||||||
|
Impl *m_impl;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,157 +1,113 @@
|
|||||||
#include "vamp-hostsdk/PluginWrapper.h"
|
#include "vamp-hostsdk/PluginWrapper.h"
|
||||||
|
|
||||||
namespace Vamp {
|
namespace vamp::host
|
||||||
|
|
||||||
namespace HostExt {
|
|
||||||
|
|
||||||
PluginWrapper::PluginWrapper(Plugin *plugin) :
|
|
||||||
Plugin(plugin->getInputSampleRate()),
|
|
||||||
m_plugin(plugin)
|
|
||||||
{
|
{
|
||||||
}
|
PluginWrapper::PluginWrapper(plugin* p) : plugin(p->getInputSampleRate()), m_plugin(p)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
PluginWrapper::~PluginWrapper()
|
PluginWrapper::~PluginWrapper()
|
||||||
{
|
{
|
||||||
delete m_plugin;
|
delete m_plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool PluginWrapper::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
||||||
PluginWrapper::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
{
|
||||||
{
|
|
||||||
return m_plugin->initialise(channels, stepSize, blockSize);
|
return m_plugin->initialise(channels, stepSize, blockSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void PluginWrapper::reset()
|
||||||
PluginWrapper::reset()
|
{
|
||||||
{
|
|
||||||
m_plugin->reset();
|
m_plugin->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
Plugin::InputDomain
|
plugin::InputDomain PluginWrapper::getInputDomain() const
|
||||||
PluginWrapper::getInputDomain() const
|
{
|
||||||
{
|
|
||||||
return m_plugin->getInputDomain();
|
return m_plugin->getInputDomain();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
std::string PluginWrapper::get_identifier() const
|
||||||
PluginWrapper::getVampApiVersion() const
|
{
|
||||||
{
|
return m_plugin->get_identifier();
|
||||||
return m_plugin->getVampApiVersion();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
std::string PluginWrapper::get_name() const
|
||||||
PluginWrapper::getIdentifier() const
|
{
|
||||||
{
|
return m_plugin->get_name();
|
||||||
return m_plugin->getIdentifier();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
std::string PluginWrapper::get_description() const
|
||||||
PluginWrapper::getName() const
|
{
|
||||||
{
|
return m_plugin->get_description();
|
||||||
return m_plugin->getName();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
std::string PluginWrapper::get_maker() const
|
||||||
PluginWrapper::getDescription() const
|
{
|
||||||
{
|
return m_plugin->get_maker();
|
||||||
return m_plugin->getDescription();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
plugin::parameter_descriptors PluginWrapper::get_parameter_descriptors() const
|
||||||
PluginWrapper::getMaker() const
|
{
|
||||||
{
|
return m_plugin->get_parameter_descriptors();
|
||||||
return m_plugin->getMaker();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int
|
float PluginWrapper::get_parameter(std::string parameter) const
|
||||||
PluginWrapper::getPluginVersion() const
|
{
|
||||||
{
|
return m_plugin->get_parameter(parameter);
|
||||||
return m_plugin->getPluginVersion();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
void PluginWrapper::set_parameter(std::string parameter, float value)
|
||||||
PluginWrapper::getCopyright() const
|
{
|
||||||
{
|
m_plugin->set_parameter(parameter, value);
|
||||||
return m_plugin->getCopyright();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
PluginBase::ParameterList
|
plugin::programs PluginWrapper::get_programs() const
|
||||||
PluginWrapper::getParameterDescriptors() const
|
{
|
||||||
{
|
return m_plugin->get_programs();
|
||||||
return m_plugin->getParameterDescriptors();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
float
|
std::string PluginWrapper::get_current_program() const
|
||||||
PluginWrapper::getParameter(std::string parameter) const
|
{
|
||||||
{
|
return m_plugin->get_current_program();
|
||||||
return m_plugin->getParameter(parameter);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void PluginWrapper::select_program(std::string program)
|
||||||
PluginWrapper::setParameter(std::string parameter, float value)
|
{
|
||||||
{
|
m_plugin->select_program(program);
|
||||||
m_plugin->setParameter(parameter, value);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
PluginBase::ProgramList
|
size_t PluginWrapper::getPreferredStepSize() const
|
||||||
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
|
|
||||||
{
|
|
||||||
return m_plugin->getPreferredStepSize();
|
return m_plugin->getPreferredStepSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t PluginWrapper::getPreferredBlockSize() const
|
||||||
PluginWrapper::getPreferredBlockSize() const
|
{
|
||||||
{
|
|
||||||
return m_plugin->getPreferredBlockSize();
|
return m_plugin->getPreferredBlockSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t PluginWrapper::getMinChannelCount() const
|
||||||
PluginWrapper::getMinChannelCount() const
|
{
|
||||||
{
|
|
||||||
return m_plugin->getMinChannelCount();
|
return m_plugin->getMinChannelCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t PluginWrapper::getMaxChannelCount() const
|
size_t PluginWrapper::getMaxChannelCount() const
|
||||||
{
|
{
|
||||||
return m_plugin->getMaxChannelCount();
|
return m_plugin->getMaxChannelCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
Plugin::OutputList
|
plugin::OutputList PluginWrapper::getOutputDescriptors() const
|
||||||
PluginWrapper::getOutputDescriptors() const
|
{
|
||||||
{
|
|
||||||
return m_plugin->getOutputDescriptors();
|
return m_plugin->getOutputDescriptors();
|
||||||
}
|
}
|
||||||
|
|
||||||
Plugin::FeatureSet
|
plugin::FeatureSet PluginWrapper::process(const float *const *inputBuffers, real_time timestamp)
|
||||||
PluginWrapper::process(const float *const *inputBuffers, RealTime timestamp)
|
{
|
||||||
{
|
|
||||||
return m_plugin->process(inputBuffers, timestamp);
|
return m_plugin->process(inputBuffers, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
Plugin::FeatureSet
|
plugin::FeatureSet PluginWrapper::getRemainingFeatures()
|
||||||
PluginWrapper::getRemainingFeatures()
|
{
|
||||||
{
|
|
||||||
return m_plugin->getRemainingFeatures();
|
return m_plugin->getRemainingFeatures();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,87 +2,57 @@
|
|||||||
|
|
||||||
#include "vamp-sdk/Plugin.h"
|
#include "vamp-sdk/Plugin.h"
|
||||||
|
|
||||||
namespace Vamp::HostExt {
|
namespace vamp::host
|
||||||
|
|
||||||
/**
|
|
||||||
* \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
|
|
||||||
{
|
{
|
||||||
public:
|
class PluginWrapper : public plugin
|
||||||
virtual ~PluginWrapper();
|
{
|
||||||
|
public:
|
||||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
virtual ~PluginWrapper();
|
||||||
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 get_identifier() const override;
|
||||||
std::string getIdentifier() const;
|
std::string get_name() const override;
|
||||||
std::string getName() const;
|
std::string get_description() const override;
|
||||||
std::string getDescription() const;
|
std::string get_maker() const override;
|
||||||
std::string getMaker() const;
|
|
||||||
int getPluginVersion() const;
|
|
||||||
std::string getCopyright() const;
|
|
||||||
|
|
||||||
ParameterList getParameterDescriptors() const;
|
parameter_descriptors get_parameter_descriptors() const override;
|
||||||
float getParameter(std::string) const;
|
float get_parameter(std::string) const override;
|
||||||
void setParameter(std::string, float);
|
void set_parameter(std::string, float) override;
|
||||||
|
|
||||||
ProgramList getPrograms() const;
|
programs get_programs() const override;
|
||||||
std::string getCurrentProgram() const;
|
std::string get_current_program() const override;
|
||||||
void selectProgram(std::string);
|
void select_program(std::string) override;
|
||||||
|
|
||||||
size_t getPreferredStepSize() const;
|
size_t getPreferredStepSize() const override;
|
||||||
size_t getPreferredBlockSize() const;
|
size_t getPreferredBlockSize() const override;
|
||||||
|
|
||||||
size_t getMinChannelCount() const;
|
size_t getMinChannelCount() const override;
|
||||||
size_t getMaxChannelCount() const;
|
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;
|
||||||
|
|
||||||
/**
|
template <typename WrapperType>
|
||||||
* Return a pointer to the plugin wrapper of type WrapperType
|
WrapperType* getWrapper()
|
||||||
* 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 *w = dynamic_cast<WrapperType *>(this);
|
WrapperType *w = dynamic_cast<WrapperType *>(this);
|
||||||
if (w) return w;
|
if (w) return w;
|
||||||
PluginWrapper *pw = dynamic_cast<PluginWrapper *>(m_plugin);
|
PluginWrapper *pw = dynamic_cast<PluginWrapper *>(m_plugin);
|
||||||
if (pw) return pw->getWrapper<WrapperType>();
|
if (pw) return pw->getWrapper<WrapperType>();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PluginWrapper(Plugin *plugin); // I take ownership of plugin
|
PluginWrapper(plugin* p);
|
||||||
Plugin *m_plugin;
|
plugin* m_plugin;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
class Window
|
class Window
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum WindowType {
|
enum WindowType {
|
||||||
RectangularWindow,
|
RectangularWindow,
|
||||||
BartlettWindow,
|
BartlettWindow,
|
||||||
@ -46,7 +46,7 @@ public:
|
|||||||
WindowType getType() const { return m_type; }
|
WindowType getType() const { return m_type; }
|
||||||
size_t getSize() const { return m_size; }
|
size_t getSize() const { return m_size; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
WindowType m_type;
|
WindowType m_type;
|
||||||
size_t m_size;
|
size_t m_size;
|
||||||
T *m_cache;
|
T *m_cache;
|
||||||
|
@ -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>
|
#include <cstring>
|
||||||
|
|
||||||
using namespace std;
|
static std::vector<std::string> files;
|
||||||
|
static std::map<std::string, const char *> cnames;
|
||||||
static vector<string> files;
|
|
||||||
static map<string, const char *> cnames;
|
|
||||||
static bool haveFiles = false;
|
static bool haveFiles = false;
|
||||||
|
|
||||||
struct vhLibrary_t {
|
struct vhLibrary_t {
|
||||||
@ -63,7 +61,7 @@ vhLibrary vhLoadLibrary(int index)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
string fullPath = files[index];
|
std::string fullPath = files[index];
|
||||||
void *lib = Files::loadLibrary(fullPath);
|
void *lib = Files::loadLibrary(fullPath);
|
||||||
|
|
||||||
if (!lib) return 0;
|
if (!lib) return 0;
|
||||||
@ -72,8 +70,8 @@ vhLibrary vhLoadLibrary(int index)
|
|||||||
(VampGetPluginDescriptorFunction)Files::lookupInLibrary
|
(VampGetPluginDescriptorFunction)Files::lookupInLibrary
|
||||||
(lib, "vampGetPluginDescriptor");
|
(lib, "vampGetPluginDescriptor");
|
||||||
if (!func) {
|
if (!func) {
|
||||||
cerr << "vhLoadLibrary: No vampGetPluginDescriptor function found in library \""
|
std::cerr << "vhLoadLibrary: No vampGetPluginDescriptor function found in library \""
|
||||||
<< fullPath << "\"" << endl;
|
<< fullPath << "\"" << std::endl;
|
||||||
Files::unloadLibrary(lib);
|
Files::unloadLibrary(lib);
|
||||||
return 0;
|
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 "PluginBufferingAdapter.h"
|
||||||
#include "PluginChannelAdapter.h"
|
#include "PluginChannelAdapter.h"
|
||||||
#include "Plugin.h"
|
|
||||||
#include "PluginHostAdapter.h"
|
#include "PluginHostAdapter.h"
|
||||||
#include "PluginInputDomainAdapter.h"
|
#include "PluginInputDomainAdapter.h"
|
||||||
#include "PluginLoader.h"
|
#include "PluginLoader.h"
|
||||||
#include "PluginSummarisingAdapter.h"
|
#include "PluginSummarisingAdapter.h"
|
||||||
#include "PluginWrapper.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_fft.h"
|
||||||
#include "vamp-sdk/ext/vamp_kiss_fftr.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)
|
void FFT::forward(unsigned int un, const double* ri, const double* ii, double* ro, double* io)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace Vamp {
|
namespace vamp
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple FFT implementation provided for convenience of plugin
|
* A simple FFT implementation provided for convenience of plugin
|
||||||
|
@ -4,409 +4,120 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "PluginBase.h"
|
#include "real_time/real_time.hpp"
|
||||||
#include "RealTime.h"
|
|
||||||
|
|
||||||
namespace Vamp {
|
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
|
|
||||||
{
|
{
|
||||||
public:
|
class plugin
|
||||||
virtual ~Plugin() { }
|
{
|
||||||
|
public:
|
||||||
|
virtual ~plugin() { }
|
||||||
|
|
||||||
/**
|
enum InputDomain { TimeDomain, FrequencyDomain };
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
struct OutputDescriptor
|
||||||
* Reset the plugin after use, to prepare it for another clean
|
{
|
||||||
* run. Not called for the first initialisation (i.e. initialise
|
std::string identifier;
|
||||||
* must also do a reset).
|
std::string name;
|
||||||
*/
|
std::string description;
|
||||||
virtual void reset() = 0;
|
std::string unit;
|
||||||
|
bool hasFixedBinCount;
|
||||||
|
size_t binCount;
|
||||||
|
std::vector<std::string> binNames;
|
||||||
|
bool hasKnownExtents;
|
||||||
|
float minValue;
|
||||||
|
float maxValue;
|
||||||
|
bool isQuantized;
|
||||||
|
float quantizeStep;
|
||||||
|
|
||||||
enum InputDomain { TimeDomain, FrequencyDomain };
|
enum SampleType
|
||||||
|
{
|
||||||
/**
|
OneSamplePerStep,
|
||||||
* Get the plugin's required input domain.
|
FixedSampleRate,
|
||||||
*
|
VariableSampleRate
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
SampleType sampleType;
|
||||||
* Get the preferred block size (window size -- the number of
|
float sampleRate;
|
||||||
* 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
|
|
||||||
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;
|
bool hasDuration;
|
||||||
|
|
||||||
OutputDescriptor() : // defaults for mandatory non-class-type members
|
OutputDescriptor() :
|
||||||
hasFixedBinCount(false),
|
hasFixedBinCount(false),
|
||||||
binCount(0),
|
binCount(0),
|
||||||
hasKnownExtents(false),
|
hasKnownExtents(false),
|
||||||
minValue(0),
|
minValue(0),
|
||||||
maxValue(0),
|
maxValue(0),
|
||||||
isQuantized(false),
|
isQuantized(false),
|
||||||
quantizeStep(0),
|
quantizeStep(0),
|
||||||
sampleType(OneSamplePerStep),
|
sampleType(OneSamplePerStep),
|
||||||
sampleRate(0),
|
sampleRate(0),
|
||||||
hasDuration(false) { }
|
hasDuration(false) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<OutputDescriptor> OutputList;
|
using OutputList = std::vector<OutputDescriptor>;
|
||||||
|
|
||||||
/**
|
struct Feature
|
||||||
* 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
|
bool hasTimestamp;
|
||||||
* FeatureSet returned from the process() call.
|
real_time timestamp;
|
||||||
*/
|
|
||||||
virtual OutputList getOutputDescriptors() const = 0;
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
bool hasDuration;
|
bool hasDuration;
|
||||||
|
real_time duration;
|
||||||
|
std::vector<float> values;
|
||||||
|
std::string label;
|
||||||
|
Feature() : hasTimestamp(false), hasDuration(false) { }
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
using FeatureList = std::vector<Feature>;
|
||||||
* Duration of the output feature. This is mandatory if the
|
using FeatureSet = std::map<int, FeatureList>;
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
std::vector<float> values;
|
|
||||||
|
|
||||||
/**
|
virtual OutputList getOutputDescriptors() const = 0;
|
||||||
* Label for the sample of this feature.
|
virtual bool initialise(size_t inputChannels, size_t stepSize, size_t blockSize) = 0;
|
||||||
*/
|
virtual void reset() = 0;
|
||||||
std::string label;
|
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"; }
|
||||||
|
|
||||||
Feature() : // defaults for mandatory non-class-type members
|
float getInputSampleRate() const { return m_inputSampleRate; }
|
||||||
hasTimestamp(false), hasDuration(false) { }
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::vector<Feature> FeatureList;
|
|
||||||
|
|
||||||
typedef std::map<int, FeatureList> FeatureSet; // key is output no
|
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>;
|
||||||
* Process a single block of input data.
|
using programs = std::vector<std::string>;
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
public:
|
||||||
* After all blocks have been processed, calculate and return any
|
virtual std::string get_identifier() const = 0;
|
||||||
* remaining features derived from the complete input.
|
virtual std::string get_name() const = 0;
|
||||||
*/
|
virtual std::string get_description() const = 0;
|
||||||
virtual FeatureSet getRemainingFeatures() = 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 ""; }
|
||||||
* Used to distinguish between Vamp::Plugin and other potential
|
virtual parameter_descriptors get_parameter_descriptors() const { return parameter_descriptors(); }
|
||||||
* sibling subclasses of PluginBase. Do not reimplement this
|
virtual programs get_programs() const { return programs(); }
|
||||||
* 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
virtual void set_parameter(std::string, float) { }
|
||||||
|
virtual void select_program(std::string) { }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
plugin(float inputSampleRate) : m_inputSampleRate(inputSampleRate) { }
|
||||||
|
float m_inputSampleRate;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,76 +1,44 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include "vamp.h"
|
#include "vamp.h"
|
||||||
|
|
||||||
#include "vamp-sdk/Plugin.h"
|
#include "vamp-sdk/Plugin.h"
|
||||||
|
|
||||||
namespace Vamp {
|
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
|
|
||||||
*/
|
|
||||||
|
|
||||||
class PluginAdapterBase
|
|
||||||
{
|
{
|
||||||
public:
|
class PluginAdapterBase
|
||||||
virtual ~PluginAdapterBase();
|
{
|
||||||
|
public:
|
||||||
|
virtual ~PluginAdapterBase();
|
||||||
|
const VampPluginDescriptor *getDescriptor();
|
||||||
|
|
||||||
/**
|
protected:
|
||||||
* Return a VampPluginDescriptor describing the plugin that is
|
PluginAdapterBase();
|
||||||
* wrapped by this adapter.
|
|
||||||
*/
|
|
||||||
const VampPluginDescriptor *getDescriptor();
|
|
||||||
|
|
||||||
protected:
|
virtual plugin* createPlugin(float inputSampleRate) = 0;
|
||||||
PluginAdapterBase();
|
|
||||||
|
|
||||||
virtual Plugin *createPlugin(float inputSampleRate) = 0;
|
class Impl;
|
||||||
|
Impl* m_impl;
|
||||||
|
};
|
||||||
|
|
||||||
class Impl;
|
template <typename Plugin>
|
||||||
Impl *m_impl;
|
class PluginAdapter : public PluginAdapterBase
|
||||||
};
|
{
|
||||||
|
public:
|
||||||
|
PluginAdapter() : PluginAdapterBase() { }
|
||||||
|
virtual ~PluginAdapter() { }
|
||||||
|
|
||||||
/**
|
protected:
|
||||||
* \class PluginAdapter PluginAdapter.h <vamp-sdk/PluginAdapter.h>
|
plugin* createPlugin(float inputSampleRate) {
|
||||||
*
|
Plugin* pl = new Plugin(inputSampleRate);
|
||||||
* PluginAdapter turns a PluginAdapterBase into a specific wrapper for
|
plugin* p = dynamic_cast<plugin*>(pl);
|
||||||
* a particular plugin implementation.
|
if (!p) {
|
||||||
*
|
std::cerr << "ERROR: PluginAdapter::createPlugin: "
|
||||||
* See PluginAdapterBase.
|
<< "Template type is not a plugin!"
|
||||||
*/
|
<< std::endl;
|
||||||
|
delete pl;
|
||||||
template <typename P>
|
return 0;
|
||||||
class PluginAdapter : public PluginAdapterBase
|
}
|
||||||
{
|
return p;
|
||||||
public:
|
}
|
||||||
PluginAdapter() : PluginAdapterBase() { }
|
};
|
||||||
virtual ~PluginAdapter() { }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Plugin *createPlugin(float inputSampleRate) {
|
|
||||||
P *p = new P(inputSampleRate);
|
|
||||||
Plugin *plugin = dynamic_cast<Plugin *>(p);
|
|
||||||
if (!plugin) {
|
|
||||||
std::cerr << "ERROR: PluginAdapter::createPlugin: "
|
|
||||||
<< "Template type is not a plugin!"
|
|
||||||
<< std::endl;
|
|
||||||
delete p;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return plugin;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
};
|
||||||
|
}
|
104
test/main.cpp
104
test/main.cpp
@ -1,49 +1,45 @@
|
|||||||
#include "hack/logger/logger.hpp"
|
#include "hack/logger/logger.hpp"
|
||||||
|
|
||||||
|
#include "vamp-sdk/Plugin.h"
|
||||||
#include "vamp-hostsdk/PluginInputDomainAdapter.h"
|
#include "vamp-hostsdk/PluginInputDomainAdapter.h"
|
||||||
#include "vamp-hostsdk/PluginBufferingAdapter.h"
|
#include "vamp-hostsdk/PluginBufferingAdapter.h"
|
||||||
#include "vamp-sdk/Plugin.h"
|
|
||||||
|
|
||||||
|
|
||||||
class MyPlugin : public Vamp::Plugin
|
class MyPlugin : public vamp::plugin
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MyPlugin(float inputSampleRate);
|
MyPlugin(float inputSampleRate);
|
||||||
virtual ~MyPlugin();
|
virtual ~MyPlugin();
|
||||||
|
|
||||||
std::string getIdentifier() const;
|
std::string get_identifier() const override;
|
||||||
std::string getName() const;
|
std::string get_name() const override;
|
||||||
std::string getDescription() const;
|
std::string get_description() const override;
|
||||||
std::string getMaker() const;
|
std::string get_maker() const override;
|
||||||
int getPluginVersion() const;
|
|
||||||
std::string getCopyright() const;
|
|
||||||
|
|
||||||
InputDomain getInputDomain() const;
|
InputDomain getInputDomain() const override;
|
||||||
size_t getPreferredBlockSize() const;
|
size_t getPreferredBlockSize() const override;
|
||||||
size_t getPreferredStepSize() const;
|
size_t getPreferredStepSize() const override;
|
||||||
size_t getMinChannelCount() const;
|
size_t getMinChannelCount() const override;
|
||||||
size_t getMaxChannelCount() const;
|
size_t getMaxChannelCount() const override;
|
||||||
|
|
||||||
ParameterList getParameterDescriptors() const;
|
parameter_descriptors get_parameter_descriptors() const override;
|
||||||
float getParameter(std::string identifier) const;
|
float get_parameter(std::string identifier) const override;
|
||||||
void setParameter(std::string identifier, float value);
|
void set_parameter(std::string identifier, float value) override;
|
||||||
|
|
||||||
ProgramList getPrograms() const;
|
programs get_programs() const override;
|
||||||
std::string getCurrentProgram() const;
|
std::string get_current_program() const override;
|
||||||
void selectProgram(std::string name);
|
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);
|
bool initialise(size_t channels, size_t stepSize, size_t blockSize) override;
|
||||||
void reset();
|
void reset() override;
|
||||||
|
|
||||||
FeatureSet process(const float *const *inputBuffers,
|
FeatureSet process(const float *const *inputBuffers, vamp::real_time timestamp) override;
|
||||||
Vamp::RealTime timestamp);
|
FeatureSet getRemainingFeatures() override;
|
||||||
|
|
||||||
FeatureSet getRemainingFeatures();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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";
|
return "myplugin";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MyPlugin::getName() const
|
std::string MyPlugin::get_name() const
|
||||||
{
|
{
|
||||||
return "My Plugin";
|
return "My Plugin";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MyPlugin::getDescription() const
|
std::string MyPlugin::get_description() const
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MyPlugin::getMaker() const
|
std::string MyPlugin::get_maker() const
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
int MyPlugin::getPluginVersion() const
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string MyPlugin::getCopyright() const
|
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@ -106,48 +92,48 @@ size_t MyPlugin::getMaxChannelCount() const
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
MyPlugin::ParameterList MyPlugin::getParameterDescriptors() const
|
MyPlugin::parameter_descriptors MyPlugin::get_parameter_descriptors() const
|
||||||
{
|
{
|
||||||
ParameterList list;
|
parameter_descriptors list;
|
||||||
ParameterDescriptor d;
|
parameter_descriptor d;
|
||||||
d.identifier = "parameter";
|
d.identifier = "parameter";
|
||||||
d.name = "Some Parameter";
|
d.name = "Some Parameter";
|
||||||
d.description = "";
|
d.description = "";
|
||||||
d.unit = "";
|
d.unit = "";
|
||||||
d.minValue = 0;
|
d.min_value = 0;
|
||||||
d.maxValue = 10;
|
d.max_value = 10;
|
||||||
d.defaultValue = 5;
|
d.default_value = 5;
|
||||||
d.isQuantized = false;
|
d.is_quantized = false;
|
||||||
list.push_back(d);
|
list.push_back(d);
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
float MyPlugin::getParameter(std::string identifier) const
|
float MyPlugin::get_parameter(std::string identifier) const
|
||||||
{
|
{
|
||||||
if (identifier == "parameter")
|
if (identifier == "parameter")
|
||||||
return 5;
|
return 5;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyPlugin::setParameter(std::string identifier, float value)
|
void MyPlugin::set_parameter(std::string identifier, float value)
|
||||||
{
|
{
|
||||||
if (identifier == "parameter") {
|
if (identifier == "parameter") {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MyPlugin::ProgramList MyPlugin::getPrograms() const
|
MyPlugin::programs MyPlugin::get_programs() const
|
||||||
{
|
{
|
||||||
ProgramList list;
|
programs list;
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MyPlugin::getCurrentProgram() const
|
std::string MyPlugin::get_current_program() const
|
||||||
{
|
{
|
||||||
return "";
|
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();
|
return FeatureSet();
|
||||||
}
|
}
|
||||||
@ -195,10 +181,10 @@ auto main() -> int
|
|||||||
{
|
{
|
||||||
float samplerate = 10.f;
|
float samplerate = 10.f;
|
||||||
MyPlugin* ch = new MyPlugin(samplerate);
|
MyPlugin* ch = new MyPlugin(samplerate);
|
||||||
Vamp::HostExt::PluginInputDomainAdapter* ia = new Vamp::HostExt::PluginInputDomainAdapter(ch);
|
vamp::host::PluginInputDomainAdapter* ia = new vamp::host::PluginInputDomainAdapter(ch);
|
||||||
ia->setProcessTimestampMethod(Vamp::HostExt::PluginInputDomainAdapter::ShiftData);
|
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();
|
int blocksize = adapter->getPreferredBlockSize();
|
||||||
if (!adapter->initialise(1, blocksize, blocksize))
|
if (!adapter->initialise(1, blocksize, blocksize))
|
||||||
|
Loading…
Reference in New Issue
Block a user