[linux-audio-dev] LADSPA with dynamic datatype and multichannel support released !!

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

Subject: [linux-audio-dev] LADSPA with dynamic datatype and multichannel support released !!
From: Benno Senoner (sbenno_AT_gardena.net)
Date: Mon Mar 27 2000 - 17:20:09 EEST


folks , after working very hard on LADSPA during the whole weekend ,
I _GOT_ it. :-)

dynamic datatype and multichannel support for LADSPA is here (works great)

but before you download the code, please read the whole mail,
because we need your comments and ideas in order to make
LADSPA the best and most flexible API, while still retaining simplicity.

the ladspa package:
http://www.linuxdj.com/ladspa/ladspa03272000.tar.gz
 
the header file:
http://www.linuxdj.com/ladspa/ladspa.h.txt

I adapted the example host and the two plugins ( delay.c and filter.c) to the
new LADSPA API.

The only structure which used LADSPA_Data directly was PortRangeHint
( LowerBound and UpperBound).
The PortRangeHint structure now contains two void * pointer to LowerBound
and UpperBound. Therefore the plugin has to malloc() the memory for the values.

I eliminated the LADSPA_Data type completely , since neither the union
nor the char[16] solution sounded acceptable to me after reading David's mail.
The approach is now to allow _ANY_ datatype, with no size restrictions, since
it's all managed dynamically.

Now to general capabilities:

- hosts and plugin can support an arbitrary number of datatypes.
   the host can lookup the supported datatypes and choose amongst one of them

- plugins can support DIFFERENT datatypes for input and outputs.
   The restriction is that you can have only one input datatype and one output
   datype.
   For example if you set input datatype = float and output datatype = double
   the both input CONTROL ports and input AUDIO ports have to use the float
   type, while output CONTROL ports and output AUDIO ports have to use double.

   Allowing per-port datatype would make things much more complicated for host
  and plugins, since our goal here is audio streaming not events.
  
For example if you have a lowpassfilter running in 32bit float mode, then the
 cutoff frequency will be a float too, when you use the 64bit version, the
parameter becomes 64bit too. I think that is not that much restrictive.
Notice that input and output is decoupled.
if you run a plugin with input dataype=float and output datatype=double
(assuming that it supports different datatypes for input and output)
the input control ports become float and the output control ports become
double.
Too much restrictive ? (IMHO it's not worth the trouble change this)

  I opted for separate input and output datatypes since it will allow
  to implement easily the famous CONVERTER-PLUGINS.
  (e.g. the ones which Juhana was talking about: double->16bit int converters
  etc) there is no limit about combinations.
  Each datatype is described by a DataTypeDescriptor:

typedef struct {
                 int BitSize;
                 int BitAlign;
                 int Type;
                 char *Name;
                 char *Description;
               } LADSPA_DataTypeDescriptor;

let's take the famous 'float' datatype (32bit)

BitSize=32
BitAlign=32 (aligned to its size)
Type=LADSPA_DATATYPE_NUMERIC | LADSPA_DATATYPE_FLOAT (just informational flags)
Name="FLOAT32"
Description: if the plugin wants, it can supply a brief description about the
datatype.

FLOAT32 is the UNIQUE identifier of the datatype.
That means new datatype names have to be callocated in a centralized fashion,
in order to avoid name clashes.

Notice that this design allows even streams of single bits to be streamed
between plugins.
The key issue is that the data "supplier" plugin and data "consumer" plugin ,
speak the same language.
For example setting BitSize=4 and BitAlign=8, one could send a stream of 4bit
data incapsulated into byte arrays (8 bit aligned etc)

But most plugins will mostly only use the "float" or the "double" datatype, or
maybe some integers for performance reasons.

I'd say the genral recommendation for plugin-developers if to support the
"float" datatype if they want that the plugin can run on as many as possible
hosts.
high-end plugins should provide the 32bit-float algorithm AND the 64bit-double
algorithm, so that it runs well on "toy" hosts, and on complicated/professional
hosts.

Performance: SAME as old LADSPA since there is no runtime overhead

Multichannel capabilities:

although old LADSPA allows multiple input/output channels , it's not flexible
enough, because the host sometimes want to use a subset of the available
channels to perform operations.

The only restriction of my multichannel model is that the ports are created
when the descriptor() function is called that means.
If we have a 32channel -> 1channel mixer
the mixer shows up 32input ports after the descriptor() function is called.
Then when calling instantiate() we can choose the number of desired channels.
But we can tolerate this little waste of mem (in the case we use <32channels),
since redesigning the port concept in order to be fully dynamic would complicate
things.

A plugin can inform the host how many channels it supports on the input side and
output side. ( fields inside the plugin Descriptor)
 int InputChannelsMin; /* minimum number of supported input channels */
 int InputChannelsMax; /* maximum number of supported input channels */
 int OutputChannelsMin; /* minimum number of supported output channels */
 int OutputChannelsMax; /* maximum number of supported output channels */

plus there is a flag if number of input channels has to match the number of
output channels

eg. A Hall plugin which supports mono and stereo:
 InputChannelsMin=1
 InputChannelsMax=2
 OutputChannelsMin=1
 OutputChannelsMax=2
 MultiChannelFlags=LADSPA_MULTICHANNEL_MATCH_INOUT (number of input channels
has to be equal to the number of output channels)

as another example a 4channel -> 1 channel mixer has:
 InputChannelsMin=1
 InputChannelsMax=4
 OutputChannelsMin=1
 OutputChannelsMax=1
and the MATCH_IN_OUT flag is NOT set since you can choose the number of inputs
between 1 and 4 while on the output side there is always only one channel.

The API supports interleaved multichannel mode too:
basically instead of using N (N=number of channels) ports with data-rate of R,
you use one singe port with datarate N*R.
But this will ONLY be used in very special cases, for example
there could arise the need to process a 100 track interleaved stream
with specialized multichannel plugins. In this case the interleaved mode
can increase the performance quite a bit, but again , "normal" plugins and
hosts will use the separate channel mode. (one port for every channel)

(Notice: mentally sick people could even combine the interleaved multichannel
mode with bit fields, for example streaming multiple interleaved single-bit
streams over arrays of bytes. David, u like this ? :-) )

In the case of a plugin supporting multiple datatypes ,
since the datatype is passed to the instantiate function, some of the
functionpointer assignments have to be moved from the descriptor()
function to the instantiate() function since these are datatype dependent.
eg. a plugin supporting float and double would have two run() functions
run32() and run64() the Descriptor->run pointer would be assigned based
on the datatype passed to the instantiate function.
It's really easy to add a new datatype to a plugin.

 
What is still missing is runAdd() support, it will be added as soon we
agree on the setGian() issue (per-channel setGain etc).
Any proposal ?

Please study the C examples carefully:
ladspa.h , the plugins: delay.c filter.c
and the host: applyplugin.c

And make your positive/negative comments / proposals etc.

Anyway I think most of the people on the list will agree that the API is still
small and clean, and that simple plugin writers and host writers do not have to
face with added complexity (except for the few initialization issues).

I think that ardour can take advantage of many of the new capabilities, since
there are basically no restrictions in terms of dataype or number of channels.
( Paul you got your outbits == inbits , satisfied now ? :-)) )

If some people are still fixated on the float-only method, then we should vote
which version to use.

I see ZERO advantages of old LADSPA over my
multidatatype/multichannel version, but the NEARTERM DANGERS of old LADSPA
are around the corner, and when they will show up there will be already
zillions of plugins around, and here we have the Y2K-bug-like problem again.

cheers,
Benno.


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

This archive was generated by hypermail 2b28 : Mon Mar 27 2000 - 20:23:58 EEST