Chris@37: /* Chris@37: jVamp Chris@37: Chris@37: A Java host interface for Vamp audio analysis plugins Chris@37: Chris@37: Centre for Digital Music, Queen Mary, University of London. Chris@37: Copyright 2012 Chris Cannam and QMUL. Chris@37: Chris@37: Permission is hereby granted, free of charge, to any person Chris@37: obtaining a copy of this software and associated documentation Chris@37: files (the "Software"), to deal in the Software without Chris@37: restriction, including without limitation the rights to use, copy, Chris@37: modify, merge, publish, distribute, sublicense, and/or sell copies Chris@37: of the Software, and to permit persons to whom the Software is Chris@37: furnished to do so, subject to the following conditions: Chris@37: Chris@37: The above copyright notice and this permission notice shall be Chris@37: included in all copies or substantial portions of the Software. Chris@37: Chris@37: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, Chris@37: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF Chris@37: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND Chris@37: NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR Chris@37: ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF Chris@37: CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION Chris@37: WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Chris@37: Chris@37: Except as contained in this notice, the names of the Centre for Chris@37: Digital Music; Queen Mary, University of London; and Chris Cannam Chris@37: shall not be used in advertising or otherwise to promote the sale, Chris@37: use or other dealings in this Software without prior written Chris@37: authorization. Chris@37: */ 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@39: public static final int ADAPT_BUFFER_SIZE = 4; 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@45: /** Chris@45: * Return the plugin path, that is, the series of local file Chris@45: * folders that will be searched for plugin files. This is Chris@45: * platform-specific; it may be a default path, or it may be Chris@45: * determined by factors such as the VAMP_PATH environment Chris@45: * variable. Chris@45: */ Chris@45: public native String[] getPluginPath(); Chris@45: 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: