[linux-audio-dev] RE: A Plugin API

New Message Reply About this list Date view Thread view Subject view Author view Other groups

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 */


New Message Reply About this list Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b28 : pe maalis 10 2000 - 07:23:27 EST