Chris@0: Chris@0: package org.vamp_plugins; Chris@0: Chris@23: /** Chris@23: * PluginLoader loads a Vamp plugin by searching the standard Vamp Chris@23: * installation path, and returns a Plugin object wrapping the native Chris@23: * plugin. Chris@23: * Chris@23: * To load a plugin call PluginLoader.getInstance().loadPlugin(key, Chris@23: * rate), where rate is the processing sample rate and key is the Chris@23: * plugin key consisting of the plugin's library base name and its Chris@23: * identifier, colon-separated. For example, Chris@23: * Chris@23: * Plugin p = PluginLoader.getInstance().loadPlugin("vamp-example-plugins:percussiononsets", 44100); Chris@23: */ Chris@0: public class PluginLoader Chris@0: { Chris@0: public class LoadFailedException extends Exception { }; Chris@0: Chris@23: /** Chris@23: * PluginLoader is a singleton. Return the instance of it. Chris@23: */ Chris@0: public static synchronized PluginLoader getInstance() { Chris@0: if (inst == null) { Chris@0: inst = new PluginLoader(); Chris@0: inst.initialise(); Chris@0: } Chris@0: return inst; Chris@0: } Chris@0: Chris@23: /** Chris@23: * Search for all available Vamp plugins, and return a list of Chris@23: * their plugin keys (suitable for passing to loadPlugin) in the Chris@23: * order in which they were found. Chris@23: */ Chris@24: public native String[] listPlugins(); Chris@23: Chris@23: /** Chris@29: * AdapterFlags contains a set of values that may be OR'd together Chris@29: * and passed to loadPlugin() to indicate which of the properties Chris@29: * of a plugin the host would like PluginLoader to take care of Chris@29: * for it, rather than having to handle itself. Chris@29: * Chris@29: * Use of these flags permits the host to cater more easily for Chris@29: * plugins with varying requirements for their input formats, at Chris@29: * some expense in flexibility. Chris@29: */ Chris@29: public class AdapterFlags { Chris@29: Chris@29: /** Chris@29: * ADAPT_INPUT_DOMAIN - If the plugin expects frequency domain Chris@29: * input, automatically convert it to one that expects Chris@29: * time-domain input by interpolating an adapter that carries Chris@29: * out the FFT conversion silently. Chris@29: * Chris@29: * This enables a host to accommodate time- and Chris@29: * frequency-domain plugins without needing to do any Chris@29: * conversion itself, but it means the host gets no control Chris@29: * over the windowing and FFT methods used. A Hann window is Chris@29: * used, and the FFT is unlikely to be the fastest native Chris@29: * implementation available. Chris@29: */ Chris@29: public static final int ADAPT_INPUT_DOMAIN = 1; Chris@29: Chris@29: /** Chris@29: * ADAPT_CHANNEL_COUNT - Automatically handle any discrepancy Chris@29: * between the number of channels supported by the plugin and Chris@29: * the number provided by the host when calling Chris@29: * Plugin.initialise(). This enables a host to use plugins Chris@29: * that may require the input to be mixed down to mono, etc., Chris@29: * without having to worry about doing that itself. Chris@29: */ Chris@29: public static final int ADAPT_CHANNEL_COUNT = 2; Chris@29: Chris@29: /** Chris@29: * ADAPT_BUFFER_SIZE - Permit the host to ignore the preferred Chris@29: * step and block size reported by the plugin when calling Chris@29: * initialise(), and to provide whatever step and block size Chris@29: * are most convenient instead. Chris@29: * Chris@29: * This may require modifying the sample type and rate Chris@29: * specifications for the plugin outputs and modifying the Chris@29: * timestamps on the output features in order to obtain Chris@29: * correct time stamping. Chris@29: */ Chris@29: public static final int ADAPT_BUFFER_SIZE = 3; Chris@29: Chris@29: /** Chris@29: * ADAPT_ALL - Perform all available adaptations that are Chris@29: * meaningful for the plugin. Chris@29: */ Chris@29: public static final int ADAPT_ALL = 255; Chris@29: Chris@29: /** Chris@29: * ADAPT_NONE - If passed to loadPlugin as the adapterFlags Chris@29: * value, causes no adaptations to be done. Chris@29: */ Chris@29: public static final int ADAPT_NONE = 0; Chris@29: }; Chris@29: Chris@29: /** Chris@23: * Load a native Vamp plugin from the plugin path. If the plugin Chris@23: * cannot be loaded, throw LoadFailedException. Chris@23: * Chris@23: * key is the plugin key consisting of the plugin's library base Chris@23: * name and its identifier, colon-separated; inputSampleRate is Chris@23: * the processing sample rate for input audio. Chris@23: * Chris@29: * adapterFlags should contain an OR of the desired AdapterFlags Chris@29: * options for the plugin, or AdapterFlags.ADAPT_NONE if no Chris@29: * automatic adaptations are to be made. Chris@23: */ Chris@29: public Plugin loadPlugin(String key, Chris@29: float inputSampleRate, Chris@29: int adapterFlags) Chris@0: throws LoadFailedException { Chris@29: long handle = loadPluginNative(key, inputSampleRate, adapterFlags); Chris@0: if (handle != 0) return new Plugin(handle); Chris@0: else throw new LoadFailedException(); Chris@0: } Chris@0: Chris@23: /** Chris@23: * Return the category hierarchy for a Vamp plugin, given its Chris@23: * identifying key. The hierarchy is a sequence of category names Chris@23: * giving the location of a plugin within a category forest, Chris@23: * containing the human-readable names of the plugin's category Chris@23: * tree root, followed by each of the nodes down to the leaf Chris@23: * containing the plugin. Chris@23: * Chris@23: * If the plugin has no category information, return an empty Chris@23: * list. Chris@23: */ Chris@24: public native String[] getPluginCategory(String key); Chris@23: Chris@0: private PluginLoader() { initialise(); } Chris@29: private native long loadPluginNative(String key, float inputSampleRate, Chris@29: int adapterFlags); Chris@0: private native void initialise(); Chris@0: private static PluginLoader inst; Chris@0: private long nativeHandle; Chris@0: Chris@0: static { Chris@0: System.loadLibrary("vamp-jni"); Chris@0: } Chris@0: } Chris@0: