[linux-audio-dev] LASE (needs better name) synthesizer interface proposal

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

Subject: [linux-audio-dev] LASE (needs better name) synthesizer interface proposal
From: David A. Bartold (foxx_AT_mail.utexas.edu)
Date: Sun Aug 26 2001 - 10:10:30 EEST


Hello, I have always wanted to use Linux to synthesize music. However,
there's been a lack of a standard midi synthesizer interface to support
pluggable midi engines. Each unix midi program implements its own midi
engine that usually sucks badly because the programmers focus on the
application not the synthesizer. Windows has long allowed programmers to
write their own midi modules to soft/hard synthesize wavetable, FM
sounds, and beyond (such as Yamaha's XG plugins). By abstracting an
interface for a midi synthesizer, app developers can focus on their apps
and synthesizer writers can develop an engine confident it will be
usable in a variety of programs across various widget sets and languages.
(mmmm.. a midi player capable of switching between Timidity and soft
synth..)

So here's a first attempt at a general interface. If you're familiar
with LADSPA, this stuff should be no surprise, in fact much of it's
cut and pasted from its header file. I did change the id type from an
integer to a 128 bit uuid because I wanted to decentralize the
architecture as much as possible. Note that this code only addresses
midi output and not input. The name LASE stands for Linux Audio
Synthesis Engine. The name could be better.. any suggestions?

- David

lase.h:

#include "ladspa.h"

#ifdef __cplusplus
extern "C" {
#endif

/* Linux Audio Synthesis Engine */

typdef int LASE_Properties;

#define LASE_PROPERTY_SUPPORTS_CHANNELS 0x01
/* Property LASE_PROPERTY_SUPPORTS_CHANNELS indicates that the plugin
   differentiates between channels. For example, a program change
   on channel 1 won't affect notes playing on channel 2. */

#define LASE_PROPERTY_GM_INSTRUMENTS 0x02
/* Property LASE_PROPERTY_GM_INSTRUMENTS indicates that the plugin
   provides a GM compatible soundbank. */

#define LASE_PROPERTY_HARD_RT_CAPABLE 0x04
/* Property LASE_PROPERTY_HARD_RT_CAPABLE indicates that the plugin
   is capable of running not only in a conventional host but also in a
   `hard real-time' environment. To qualify for this the plugin must
   satisfy all of the following:

   (1) The plugin must not use malloc(), free() or other heap memory
   management within its run() function. All new
   memory used in run() must be managed via the stack. These
   restrictions only apply to the run() function.

   (2) The plugin will not attempt to make use of any library
   functions with the exceptions of functions in the ANSI standard C
   and C maths libraries, which the host is expected to provide.

   (3) The plugin will not access files, devices, pipes, sockets, IPC
   or any other mechanism that might result in process or thread
   blocking.

   (4) The plugin will take an amount of time to execute a run()
   call approximately of form (A+B*SampleCount) where A and B
   depend on the machine and host in use. This amount of time
   may not depend on input signals or plugin state. The host is left
   the responsibility to perform timings to estimate upper bounds for
   A and B. */

typedef struct LASE_Descriptor
{
  /* This numeric identifier indicates the plugin type
     uniquely. Plugin programmers may generate a random 128 bit number
     to use as a unique ID. UUIDs rely on statistics to avoid clashes. */
  unsigned char UniqueID[16];

  /* This identifier can be used as a unique, case-sensitive
     identifier for the plugin type within the plugin file. Plugin
     types should be identified by file and label rather than by index
     or plugin name, which may be changed in new plugin
     versions. Labels must not contain white-space characters. */
  const char * Label;

  /* This indicates a number of properties of the plugin. */
  LASE_Properties Properties;

  /* This member points to the null-terminated name of the plugin
     (e.g. "Phase Modulated Synthesizer"). */
  const char * Name;

  /* This member points to the null-terminated string indicating the
     maker of the plugin. This can be an empty string but not NULL. */
  const char * Maker;

  /* This member points to the null-terminated string indicating any
     copyright applying to the plugin. If no Copyright applies the
     string "None" should be used. */
  const char * Copyright;

  /* Instantiate a module at the given sample rate and polyphony. The
     polyphony parameter is a hint to the synthesis engine that it
     should support at least the number of voices given. */
  LASE_Handle (*instantiate) (const LASE_Descriptor *Descriptor,
                              unsigned long SampleRate,
                              unsigned long Polyphony);

  /* Configure the synthesis engine's global properties. When called,
     this function should fork and execute a graphical X program that
     allows the user to configure the engine. It may allow the user to
     select between different sound banks, set the engine's sound quality,
     or edit sounds. Set this structure member to NULL if the plugin does
     not support user configuration. */
  void (*configure) (const LASE_Descriptor *Descriptor);

  /* Activate the sound engine. */
  void (*activate) (LASE_Handle Instance);

  /* Return the actual number of voices supported by this instance of
     the synthesis engine. */
  int (*polyphony) (LASE_Handle Instance);

  /* Change the instrument for a particular channel. The channel
     parameter must be between 0 and 15. */
  void (*change_program) (LASE_Handle Instance,
                          int channel,
                          int program);

  /* Channel is between 0 and 15,
     Note is between 0 and 127,
     Velocity is between 0 and 127 */
  void (*press_note) (LASE_Handle Instance,
                      int channel,
                      int note,
                      int velocity);

  /* Channel is between 0 and 15,
     Note is between 0 and 127,
     Velocity is between 0 and 127 */
  void (*release_note) (LASE_Handle Instance,
                        int channel,
                        int note,
                        int velocity);

  /* Change a parameter for all notes played on a particular channel.
     Parameters map to MIDI and have a 16-bit precision. Unlike MIDI,
     the parameters are not split into MSB and LSB values. */

     0. Pitch Bend 0 - 16383, 8192 = Center
     1. Aftertouch 0 - 16383, 0 = Soft, 16383 = Hard
     2. Modulation Wheel 0 - 16383
     3. Main Volume 0 - 16383, 0 = Off, 16383 = Full Vol.
     4. Breath Controller 0 - 16383
     5. Foot Pedal 0 - 16383
     6. Portamento 0 - 16383
     7. Sustenuto 0 - 16383
     8. Damper Pedal 0 - 16383
     9. Soft Pedal 0 - 16383
     10. Pan 0 - 16383, 0 = Left, 16383 = Right
     11 - 31. Reserved
     32 - 16383. User Defined
   */
  void (*parameter) (LASE_Handle Instance,
                     int channel,
                     int parameter,
                     int value);

  /* Calculate the given number of samples */
  void (*run) (LASE_Handle Instance,
               unsigned long SampleCount,
               LADSPA_Data *LeftChannel,
               LADSPA_Data *RightChannel);

  /* Deactivate the sound engine. */
  void (*deactivate) (LASE_Handle Instance);

  /* Deallocate the synthesis engine. */
  void (*cleanup) (LASE_Handle Instance);
} LASE_Descriptor;

const LASE_Descriptor * lase_descriptor(unsigned long Index);

/* Datatype corresponding to the lase_descriptor() function. */
typedef const LASE_Descriptor *
(*LASE_Descriptor_Function)(unsigned long Index);

#ifdef __cplusplus
}
#endif


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

This archive was generated by hypermail 2b28 : Sun Aug 26 2001 - 10:12:44 EEST