[linux-audio-dev] XAP status : incomplete draft

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

Subject: [linux-audio-dev] XAP status : incomplete draft
From: Tim Hockin (thockin_AT_hockin.org)
Date: Fri Dec 13 2002 - 10:55:40 EET


Here is a draft incorportaing a lot of what we've talked about. It is
missing a lot, and some is probably wrong/inconsistent. We've been talking
a LOT. :)

Notes:
* All VVID stuff is missing
* All pitch stuff is missing
* Currently uses a monolithic ChannelType for channels until actual answer
is decided (though I rather like the simple monolith)
* several things are not commented or are insufficiently commented
* Several FIXMEs
* several things still on the TODO list

Have at it...

Tim

/* $Id: $ */
/*
 * Tim Hockin <thockin_AT_hockin.org>
 * Copyright (c) 2001-2002 Tim Hockin
 *
 * This header file defines the API for the XAP - the XAP Audio Plugin
 * interface.
 *
 * Goals:
 * The main goal of this API is to provide an API that is full-featured
 * enough to be the primary plugin system for audio-development
 * applications, while remaining as simple, lightweight, and self-contained
 * as possible.
 *
 * Credits:
 * This API originated from LADSPA by Richard W.E. Furse et al. and evolved
 * through dialog between Tim Hockin, David Olofson, Steve Harris, and
 * others via the linux-audio-devel mailing list
 * (linux-audio-dev_AT_music.columbia.edu).
 *
 * Overview:
 * Plugins are loaded from shared object files. A shared object file holds
 * one or more plugin descriptors, accessed by index. Each descriptor holds
 * all the information about a single plugin - it's identification,
 * capabilities, controls, and access methods.
 */
#ifndef XAP_H__
#define XAP_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>

/*
 * The current version of the API: read as "major.minor.micro".
 */
#define XAP_VERSION 0x000010
#define XAP_MKVERSION(maj, min, mic) (((mar)<<16) | ((min)<<8) | (mic))

/*
 * A single audio sample: this datatype is used for passing audio data
 * between plugins and hosts. Data is normalized between -1.0 and 1.0
 * as the 0dB value, with 0.0 being silence.
 */
typedef float XAP_sample;

/* the fundamental XAP types */
typedef struct XAP_descriptor XAP_descriptor;
typedef struct XAP_channel XAP_channel;
typedef struct XAP_port XAP_port;
typedef struct XAP_host XAP_host;
typedef struct XAP_control XAP_control;
typedef enum XAP_ctrl_type XAP_ctrl_type;
typedef struct XAP_ctrl_int XAP_ctrl_int;
typedef struct XAP_ctrl_float XAP_ctrl_float;
typedef struct XAP_ctrl_enum XAP_ctrl_enum;
typedef struct XAP_ctrl_string XAP_ctrl_string;
typedef struct XAP_raw_data XAP_raw_data;
typedef struct XAP_ctrl_raw XAP_ctrl_raw;
typedef struct XAP_event_port XAP_event_port;
typedef struct XAP_event_queue XAP_event_queue;
typedef struct XAP_event XAP_event;
typedef enum XAP_event_id XAP_event_id;
typedef uint32_t XAP_timestamp;

/*
 * A plugin descriptor: this structure describes what an plugin can do.
 * Every plugin has exactly one descriptor, which the host must treat as
 * READ-ONLY.
 */
struct XAP_descriptor {
        /*
         * The ID is a bitmask of the vendor code (high-order 16 bits) and
         * the product code (low-order 16 bits). The vendor code is
         * assigned by a central authority, and the product code is vendor
         * assigned. For plugins that are in development, or for vendors
         * who have not yet received a vendor code, the vendor code field
         * should be 0. Vendors/authors MUST NOT distribute plugins with
         * the vendor code set to 0.
         */
        uint32_t xap_id;

        /*
         * The api is the XAP_VERSION that this plugin understands. Hosts
         * should use this to allow older plugins to load without
         * overstepping the plugin's capabilities.
         */
        uint32_t xap_api;

        /*
         * The serial is simply a number by which the host can compare two
         * versions of a plugin and pick the later version. The actual
         * value has no meaning to the host. The only requirement for this
         * field is that the value never gets smaller in new releases.
         */
        uint32_t xap_serial;

        /*
         * The label is a file-unique, non-whitespace, string identifier for
         * the plugin. Hosts can use the filename and label to identify a
         * plugin uniquely. The label is all upper case, by convention.
         */
        const char *xap_label;

        /*
         * The name is an arbitrary string, which hosts can display to
         * users.
         */
        const char *xap_name;

        /*
         * These are display-friendly fields, which hosts can display to
         * users.
         */
        const char *xap_version;
        const char *xap_author;
        const char *xap_copyright;
        const char *xap_license;
        const char *xap_url;
        const char *xap_notes;

        /* master controls and I/O */
        int xap_n_controls;
        XAP_control **xap_controls;
        int xap_n_ports;
        XAP_port **ch_ports;

        /* channel descriptors */
        int xap_n_channel_types;
        XAP_channel *xap_channel_types;
        //FIXME: how to get the num/info currently instantiated channels?

        //FIXME: enumerate negative return values == better error reporting

        /*
         * create: instantiate the plugin
         *
         * This method is used to create an instance of the plugin described
         * by the descriptor. Memory will be allocated and state will be
         * initialized in this method.
         *
         * Arguments:
         * descriptor: a pointer to the plugin descriptor.
         * host: a pointer to the host callback structure.
         * rate: the host sample rate (see xap_set_rate below).
         *
         * Returns:
         * This method returns a pointer to a plugin-private handle. If
         * initialization fails for any reason, this method must return
         * NULL.
         */
        void *(*xap_create)(XAP_descriptor *descriptor, XAP_host *host,
            int rate);
        //FIXME: how to enumerate errors from this?
        //FIXME: return something better than void *?

        /*
         * destroy: destroy an instance
         *
         * This method is used to destroy and clean up after an instance of
         * the plugin. All allocated resources must be released. After
         * this method is invoked, the plugin handle is no longer valid.
         * This function can not fail.
         *
         * Arguments:
         * plugin: a pointer to the plugin instance.
         *
         * Returns:
         * This method does not return a value.
         */
        void (*xap_destroy)(void *plugin);

        /*
         * set_rate: set the sample rate
         *
         * This method may only be called on plugins that are not active.
         * There is no required set of supported sample rates, but plugins
         * should support the common sample rates (44100, 48000, 96000) to
         * be generally useful. Hosts should always check that all plugins
         * support the desired sample rate.
         *
         * Arguments:
         * plugin: a pointer to the plugin instance.
         * rate: the desired sample rate.
         *
         * Returns:
         * This method returns 0 on success and -1 if the sample rate is
         * not supported or some error occurred.
         */
        int (*xap_set_rate)(void *plugin, int rate);

        /*
         * activate: prepare a plugin for running
         *
         * This method is used to prepare a plugin before being run. This
         * is an optional method, and if provided, will be called once
         * before the first call to the run() method. This method will not
         * be called again by the host until the deactivate() method has
         * been called. Plugins may interpret or ignore the quality
         * parameter as they see fit.
         *
         * Arguments:
         * plugin: a pointer to the plugin instance.
         * quality: an integer between 1 (lowest) and 10 (highest).
         *
         * Returns:
         * This method returns 0 on success and -1 on error.
         */
        int (*xap_activate)(void *plugin, int quality);

        /*
         * deactivate: stop a plugin after running
         *
         * This method is used to shut down a plugin when the host is done
         * running it. This method, if provided, will be called at least
         * once some time after a call to the activate() method and before
         * the destroy() method. Hosts may use the deactivate()/activate()
         * pair as a way to reset the plugin's state.
         *
         * Arguments:
         * plugin: a pointer to the plugin instance.
         *
         * Returns:
         * This method returns 0 on success and -1 on error.
         */
        int (*xap_deactivate)(void *plugin);

        /*
         * connect_port: connect buffers for data
         *
         * Hosts must connect ports to buffers in order for a plugin to
         * operate. The Plugins are expected to handle the case of the
         * input buffer being the same as the output buffer (in-place
         * operation) transparently to the host. The host must connect
         * every port except if the host and plugin agree to disable a
         * port (see xap_disable_port), in which case it does not need to
         * be connected.
         *
         * Arguments:
         * plugin: a pointer to the plugin instance.
         * channel: the channel number or CHANNEL_MASTER
         * port: the port number (zero-based value).
         * buffer: the buffer in which to read/write audio data.
         *
         * Returns:
         * This method returns 0 on success and -1 on error.
         */
        int (*xap_connect_port)(void *plugin, int channel, int port,
            XAP_sample *buffer);

        /*
         * disable_port: request that a port not be used.
         *
         * If a host does not want the plugin to operate on a given port, it
         * may ask the plugin to disable the port. This method is optional,
         * but highly recommended if the plugin can save cycles. If the
         * plugin provides this method and this method succeeds, the port
         * does not need to be connected. If this method is not provided,
         * or this method fails, the host must follow normal port connection
         * rules. If a host disables a port and later connects it, the port
         * is enabled. If the host wishes to disable it again, it must call
         * this method again.
         *
         * Arguments:
         * plugin: a pointer to the plugin instance.
         * channel: the channel number or XAP_CHANNEL_MASTER
         * port: the port number (zero-based value).
         *
         * Returns:
         * These methods return 0 on success and -1 on error.
         */
        int (*xap_disable_port)(void *plugin, int channel, int port);

        /*
         * get an event port, XAP_CHANNEL_MASTER for master
         */
        XAP_event_port *(*xap_event_port)(void *plugin, int channel, int index);

        /*
         * run: use the plugin
         *
         * This method invokes the plugin for a number of audio samples,
         * which are provided on connected ports.
         *
         * Arguments:
         * plugin: a pointer to the plugin instance.
         * nsamples: the number of samples available on port buffers.
         *
         * Returns:
         * This method returns 0 on success and -1 on error.
         */
        int (*xap_run)(void *plugin, int nsamples, XAP_timestamp now);
};

struct XAP_channel {
        char *chan_label;
        char *chan_name;
        uint32_t chan_flags;

        /* how many instances of this channel are allowed? */
        int chan_count_min;
        int chan_count_max;

        /* channel controls and I/O */
        int chan_n_controls;
        XAP_control **chan_controls;
        int chan_n_ports;
        XAP_port **chan_ports;
};

/* an audio port */
struct XAP_port {
        char *port_label;
        char *port_name;
        char *port_hints;
        uint32_t port_flags;
};

/* flags for various control types */
#define XAP_PTFL_INPUT_P 0x01
#define XAP_PORT_IS_INPUT(port) ((port)->flags & XAP_CTFL_INPUT_P)
#define XAP_PORT_IS_OUTPUT(port) (!((port)->flags & XAP_CTFL_INPUT_P))

/* common port labels - a good source of hints to the host! */
#define XAP_PORTHINT_MONO "MONO"
#define XAP_PORTHINT_FLEFT "FRONT_LEFT"
#define XAP_PORTHINT_FRIGHT "FRONT_RIGHT"
#define XAP_PORTHINT_FCENTER "FRONT_CENTER"
#define XAP_PORTHINT_RLEFT "REAR_LEFT"
#define XAP_PORTHINT_RRIGHT "REAR_RIGHT"
#define XAP_PORTHINT_SUB "SUB"
#define XAP_PORTHINT_SLEFT "SURR_LEFT"
#define XAP_PORTHINT_SRIGHT "SURR_RIGHT"

/*
 * A XAP host: this provides callbacks for plugins to access host-provided
 * resources. This puts control of things such as failures in the hands of
 * the host, not the plugin.
 */
struct XAP_host {
        //FIXME: some sort of host ID/version ?
        uint32_t host_api;
        //FIXME: how does the host know where an event came from?
        XAP_event_queue *host_queue;
        void *(*host_malloc)(size_t size);
        void (*host_free)(void *ptr);
        void *(*host_realloc)(void *ptr, size_t size);
        void (*host_alloc_failure)(void);
        //FIXME: get_buffer(int nsamples) ?
        //FIXME: free_buffer() ?
        //FIXME: get_silent_buffer(int nsamples) ?
};

struct XAP_event_port {
        XAP_event_queue *evp_queue;
        uint32_t exp_cookie;
};

/* the various types that a control may be */
enum XAP_ctrl_type{
        XAP_CTRL_INT = 1,
        XAP_CTRL_FLOAT = 2,
        XAP_CTRL_ENUM = 3,
        XAP_CTRL_STRING = 4,
        XAP_CTRL_RAW = 5,
};

/* for declaring ctrl sub-types */
#define XAP_CONTROL_COMMON_FIELDS_ \
        /* \
         * Label is a unique (within this plugin), non-whitespace string \
         * identifier. The label is all upper case, by convention. \
         */ \
        const char *ctrl_label; \
        /* display-friendly name */ \
        const char *ctrl_name; \
        /* hints to the host */ \
        const char *ctrl_hints; \
        /* the type of control */ \
        XAP_ctrl_type ctrl_type; \
        /* global and per-type flags - XAP_CTFL_* */ \
        uint32_t ctrl_flags; \
        /* hints about real-time behavior of controls - XAP_RTFL_* */ \
        uint32_t ctrl_rtflags;

/* a knob, button, etc. of a plugin */
struct XAP_control {
        XAP_CONTROL_COMMON_FIELDS_
};
/* to help in declaring arrays of pointers to structs statically */
#define XAP_DECL_CONTROL(type) (XAP_control *)&(XAP_ctrl_ ## type)

/* the expanded structs for each control type */
struct XAP_ctrl_int {
        XAP_CONTROL_COMMON_FIELDS_
        int ctrl_min;
        int ctrl_max;
        int ctrl_default;
};

struct XAP_ctrl_float {
        XAP_CONTROL_COMMON_FIELDS_
        float ctrl_min;
        float ctrl_max;
        float ctrl_default;
};

struct XAP_ctrl_enum {
        XAP_CONTROL_COMMON_FIELDS_
        int ctrl_min;
        int ctrl_max;
        int ctrl_default;
        const char **ctrl_options;
};

struct XAP_ctrl_string {
        XAP_CONTROL_COMMON_FIELDS_
        const char *ctrl_default;
};

struct XAP_raw_data {
        int raw_size; /* bytes */
        void *raw_data;
};

struct XAP_ctrl_raw {
        XAP_CONTROL_COMMON_FIELDS_
        XAP_raw_data *ctrl_default;
};

/* flags for various control types */
#define XAP_CTFL_PERVOICE_P 0x01
#define XAP_CTRL_IS_VOICE(ctrl) ((ctrl)->flags & XAP_CTFL_VOICE_P)
#define XAP_CTRL_IS_CHANNEL(ctrl) (!((ctrl)->flags & XAP_CTFL_VOICE_P))
#define XAP_CTFL_INPUT_P 0x02
#define XAP_CTRL_IS_INPUT(ctrl) ((ctrl)->flags & XAP_CTFL_INPUT_P)
#define XAP_CTRL_IS_OUTPUT(ctrl) (!((ctl)->flags & XAP_CTFL_INPUT_P))
#define XAP_CTFL_HARDLIM_P 0x04
#define XAP_CTRL_IS_HARDLIMIT(ctrl) ((ctrl)->flags & XAP_CTFL_HARDLIM_P)
#define XAP_CTRL_IS_SOFTLIMIT(ctrl) (!((ctl)->flags & XAP_CTFL_HARDLIM_P))

//FIXME: renumber, re-examine
#define XAP_CTFL_SCALAR 0x01 /* is scalar to the sample rate */
#define XAP_CTFL_LOG 0x02 /* is logarithmic */
#define XAP_CTFL_FILE 0x04 /* is a file name */
#define XAP_CTFL_DIR 0x08 /* is a directory */
#define XAP_CTFL_BOOL 0x10 /* is a boolean */
#define XAP_CTFL_FRAMES 0x20 /* is a measurement of frames */
#define XAP_CTFL_RDONLY 0x40 /* is read-only */

/* flags to identify real-time behavior of controls */
#define XAP_RTFL_NEVER 0x01 /* is never RT safe */
#define XAP_RTFL_MALLOC 0x02 /* allocates/frees memory */
#define XAP_RTFL_HMALLOC 0x04 /* allocates memory through the host */
#define XAP_RTFL_HFREE 0x08 /* frees memory through the host */
#define XAP_RTFL_FILEIO 0x10 /* performs file I/O */
#define XAP_RTFL_SLOW 0x20 /* is 'slow' in general */

/* common control labels - a good source of hints to the host! */
#define XAP_CTRLHINT_VELOCITY "VELOCITY" //voice
#define XAP_CTRLHINT_AFTERTOUCH "AFTERTOUCH" //voice
#define XAP_CTRLHINT_CHPRESSURE "CHPRESSURE" //channel
#define XAP_CTRLHINT_PITCH "PITCH" //channel,voice
#define XAP_CTRLHINT_MODULATION "MODULATION" //channel,voice
#define XAP_CTRLHINT_BREATH "BREATH" //channel,voice
#define XAP_CTRLHINT_FOOTPEDAL "FOOTPEDAL" //channel,voice
#define XAP_CTRLHINT_PORTATIME "PORTATIME" //channel,voice
#define XAP_CTRLHINT_VOLUME "VOLUME" //channel,voice
#define XAP_CTRLHINT_BALANCE "BALANCE" //channel,voice
#define XAP_CTRLHINT_PAN "PAN" //channel,voice
#define XAP_CTRLHINT_EXPRESSION "EXPRESSION" //channel,voice
#define XAP_CTRLHINT_HOLDPEDAL "HOLDPEDAL" //channel,voice: bool
#define XAP_CTRLHINT_PORTAMENTO "PORTAMENTO" //channel,voice: bool
#define XAP_CTRLHINT_SOSTENUTO "SOSTENUTO" //channel,voice: bool
#define XAP_CTRLHINT_SOFTPEDAL "SOFTPEDAL" //channel,voice: bool
#define XAP_CTRLHINT_HOLD2PEDAL "HOLD2PEDAL" //channel,voice: bool
#define XAP_CTRLHINT_SNDTIMBRE "SNDTIMBRE" //channel,voice
#define XAP_CTRLHINT_SNDRELEASE "SNDRELEASE" //channel,voice
#define XAP_CTRLHINT_SNDATTACK "SNDATTACK" //channel,voice
#define XAP_CTRLHINT_SNDBRIGHT "SNDBRIGHT" //channel,voice
#define XAP_CTRLHINT_FXDEPTH "FXDEPTH" //channel,voice
#define XAP_CTRLHINT_TREMELO "TREMELO" //channel,voice
#define XAP_CTRLHINT_CHORUS "CHORUS" //channel,voice
#define XAP_CTRLHINT_CELESTE "CELESTE" //channel,voice
#define XAP_CTRLHINT_PHASER "PHASER" //channel,voice
#define XAP_CTRLHINT_POLYPHONY "POLYPHONY" //channel
#define XAP_CTRLHINT_TEMPO "TEMPO" //channel
#define XAP_CTRLHINT_VOICECTRL "VOICECTRL" //channel
//FIXME: describe these controls, maybe have a macro to declare them [0.0-1.0]
// or [-1.0 to 1.0] or whatever

/* An event queue - where events are actually stored */
struct XAP_event_queue {
        XAP_event *evq_first;
        XAP_event *evq_last;
};

/*
 * An event - passed to plugins on their XAP_event_queue. The ev_time field
 * is a sample count, from some arbitrary start. Hosts pass the timestamp
 * of the start of the buffer to the plugin run() method.
 */
struct XAP_event {
        XAP_event *ev_next;
        uint32_t ev_cookie;
        XAP_timestamp ev_time;
        XAP_event_id ev_event;
        uint32_t ev_voice;
        XAP_event_ramp ev_ramp_type;
        XAP_timestamp ev_ramp_length;
};

/* The known events */
enum XAP_event_id {
        XAP_EVENT_NULL = 0,
        XAP_EVENT_CTRL = 1,
};

/* ramp styles */
enum XAMP_event_ramp {
        XAP_RAMP_NONE = 0,
        XAP_RAMP_LINEAR = 1,
};

/* how the host learns about the plugin */
XAP_descriptor *xap_descriptor(int index);

/*
 * utility functions
 */

/* return true if time0 is after time1 */
static inline int
xap_time_after(XAP_timestamp time0, XAP_timestamp time1)
{
        return ((long)(time1) - (long)(time0) < 0);
}
#define xap_time_before(t0, t1) xap_time_after(t1, t0)

/* return true if time0 is after or equal to time1 */
static inline int
xap_time_after_eq(XAP_timestamp time0, XAP_timestamp time1)
{
        return ((long)(time1) - (long)(time0) <= 0);
}
#define xap_time_before_eq(t0, t1) xap_time_after_eq(t1, t0)

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /* XAP_H__ */


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

This archive was generated by hypermail 2b28 : Fri Dec 13 2002 - 10:59:10 EET