Subject: [linux-audio-dev] RE: A Plugin API
From: Richard W.E. Furse (richard_AT_muse.demon.co.uk)
Date: ma helmi 28 2000 - 13:08:06 EST
All fine by me - forget petty if you're being constructive - thank you!
I've made a couple of further (petty!) clarifications to some of the
comments. Apologies for the mixed-up ANDing... Yes, I agree it's relatively
difficult to fix Csound to install any plugin mechanism, but at least this
API fits its logical model and there are a lot of competent programmers out
there who have tinkered with Csound. I'm a bit surprised you dislike the
multiple-UG-per-plugin model - it was partly designed to allow Quasimodo to
load overloaded opcodes (e.g. oscillators with a-rate or k-rate freq
inputs) in a single file - fine by me though, either way.
Cool - beginnings of consensus! :) Anyone else out there have any
tweaks/opinions?
-- Richard
/* ladspa.h - Copyright 2000 Richard W.E. Furse & Paul Barton-Davis */
#ifndef LADSPA_INCLUDED
#define LADSPA_INCLUDED
/**********************************************************************/
/* Overview:
There is a large number of synthesis packages in use or development
on the Linux platform at this time. This API (`The Linux Audio
Developer's Simple Plugin API') attempts to give programmers the
ability to write simple `plugin' audio processors in C and link
them dynamically (`plug') into a range of these packages (`hosts').
It should be possible for any host and any plugin to communicate
completely through this interface.
This API is deliberately short and simple. To achieve compatibility
with a range of promising Linux sound synthesis packages it
attempts to find the `lowest common denominator' in their logical
behaviour. Having said this, certain limiting decisions are
implicit, notably the use of a fixed type for all data transfer and
absence of a parameterised `initialisation' phase. For this version
of the API the fixed type will be `float.'
Plugins are expected to use the `control rate' thinking implicit in
the Music N languages (including Csound). Plugins have `ports' that
are inputs or outputs for audio or control data and the plugin is
`run' for a `block' corresponding to a short time interval measured
in samples. Audio data is communicated using arrays of floats,
allowing a block of audio to be processed by the plugin in a single
pass. Control data is communicated using single LADSPA_Data
values. Control data may only change once per call to the `run'
function. It is not suitable for the transfer of many types of
data, however it can a significant performance benefit. The plugin
may assume that all its inputs and outputs are bound before it is
asked to run.
This API contains very limited error-handling at this time.
*/
/* Fundamental data type passed around between plugins. Corresponds
to one sample and one control value.
*/
typedef float LADSPA_Data;
/*********************************************************************/
typedef int LADSPA_Properties;
/* Indicates that the plugin has a real-time dependency and so
its output should not be cached or subject to serious latency.
*/
#define LADSPA_PROPERTY_REALTIME 0x1
#define LADSPA_IS_REALTIME(x) ((x) & LADSPA_PROPERTY_REALTIME)
/***********************************************************************/
/* Unit Generator Ports:
Plugins have `ports' that are inputs or outputs of audio or
data. Ports can communicate arrays of LADSPA_Data (for audio-rate
inputs/outputs) or single LADSPA_Data values (for control-rate
input/outputs). This information is encapsulated in the
LADSPA_PortDescriptor type which is assembled by ORing properties
together.
Note that a port cannot be both an input and an output and that a
port cannot be both a control rate and an audio rate port.
*/
typedef int LADSPA_PortDescriptor;
#define LADSPA_PORT_INPUT 0x1 /* port is for input */
#define LADSPA_PORT_OUTPUT 0x2 /* port is for output */
#define LADSPA_PORT_CONTROL 0x4 /* port is control-rate (single
LADSPA_Data) */
#define LADSPA_PORT_AUDIO 0x8 /* port is audio-rate (LADSPA_Data array)
*/
#define LADSPA_IS_PORT_INPUT(x) ((x) & LADSPA_PORT_INPUT)
#define LADSPA_IS_PORT_OUTPUT(x) ((x) & LADSPA_PORT_OUTPUT)
#define LADSPA_IS_PORT_CONTROL(x) ((x) & LADSPA_PORT_CONTROL)
#define LADSPA_IS_PORT_AUDIO(x) ((x) & LADSPA_PORT_AUDIO)
/**********************************************************************/
/* Plugin Handles:
This plugin handle indicates access to a particular
instance of the plugin concerned. It is valid to compare
this to NULL (0 for C++).
*/
typedef void * LADSPA_Handle;
/**********************************************************************/
/* Descriptor for a Type of Plugin:
This structure is used to describe a type of plugin. It
provides a number of functions to examine the type, instantiate it,
link it to buffers and workspaces and to run it.
*/
struct LADSPA_Descriptor {
/* This indicates a number of properties of the plugin. */
LADSPA_Properties Properties;
/* This member points to the null-terminated name of the plugin
(e.g. "Sine Oscillator").
*/
const char * Name;
/* This indicates the number of ports (input AND output) present on
the plugin.
*/
unsigned long PortCount;
/* This member indicates an array of port descriptor. Valid index
numbers vary from 0 to PortCount-1.
*/
LADSPA_PortDescriptor * PortDescriptors;
/* This member is a function pointer that takes a port number as an
input and returns a short null-terminated string (e.g. "frequency
(Hz)") describing the port. The string returned should be
finished with (but not freed) before calling this method again in
case the memory space is reused by the plugin.
*/
const char * (*get_port_name)(unsigned long Port);
/* This member is a function pointer that instantiates a plugin.
A handle is returned, indicating the new function. The
instantiation function accepts a sample rate as a
parameter. Returns NULL if instantiation fails.
*/
LADSPA_Handle (*instantiate)(unsigned long SampleRate);
/* This member is a function pointer that connects a port on an
instantiated plugin to a memory location at which a frame
of data for the port will be read/written. The data location is
expected to be an array of LADSPA_Data for audio rate ports or a
single LADSPA_Data value for control rate ports. Memory issues
will be managed by the host. The plugin should read/write the
data at these locations every frame and the data present at the
time of this connection call should not be considered meaningful.
Connection functions may be called more than once for a single
instance of a plugin to allow the host to change the buffers that
the unit generator is reading or writing. They must be called at
least once for each port. When working with blocks of LADSPA_Data
the unit generator should pay careful attention to the frame size
passed to the run function as the block allocated may only just be
large enough to contain the block of samples.
*/
void (*connect_port)(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * DataLocation);
/* This method is a function pointer that runs an instance of a unit
generator for a frame. Two parameters are required: the first is
a handle to the particular instance to be run and the second
indicates the frame size (in samples) for which the unit
generator may run.
*/
void (*run)(LADSPA_Handle Instance,
unsigned long sampleCount)
/* Once an instance of a plugin has been finished with it
can be deleted using the following function. The handle passed
ceases to be valid after this call.
*/
void (*cleanup)(LADSPA_Handle instance);
/* Reserved area for extensions. Must be initialised to zero. */
char reserved[1000];
};
/**********************************************************************/
/* Loading A Plugin:
The exact mechanism by which a plugin is loaded is host-dependent,
however all most hosts will need to know is the name of the
shared object file containing the plugin. Each shared object file
will contain one plugin.
*/
/**********************************************************************/
/* Writing a Plugin:
A plugin programmer should include a function called
"descriptor" with the following function prototype. This function
should reside in the shared object corresponding to the plugin.
A host will find the plugin shared object file by one means or
another, and then lookup the "descriptor" function, call it,
and proceed from there.
*/
typedef LADSPA_Descriptor * (*LADSPA_Descriptor_Function)(void);
/**********************************************************************/
#endif /* LADSPA_INCLUDED */
/* EOF */
This archive was generated by hypermail 2b28 : pe maalis 10 2000 - 07:23:27 EST