Subject: Re: [linux-audio-dev] LADSPA 64bit FP support ?
From: David Olofson (david_AT_gardena.net)
Date: Sat Mar 25 2000 - 20:26:12 EET
On Wed, 22 Mar 2000, Karl W. MacMillan wrote:
> >
> > Even if computers get fast enough to handle 64 bits all the way
> > through, 32 bits will still be faster and good enough for many
> > applications. No matter how fast the bus is - less data always get
> > accross faster.
> >
>
> I'm not convinced that this is the case - 32 bits is always faster if the
> bus is the limitation but what if you are cpu bound on a 64 bit processor?
> Isn't the natural word size for any given processor always the fastest?
> Regardless, choice of data type never has speed as the first choice at
> this point. If you need 64 bits to get the results that you want you are
> going to use 64 bits and buy a faster computer. Otherwise I would be
> using 8 bits 22500 hz audio.
Yes, obviously you have to get the job done.
But are you going to use another API for price sensitive production
systems...? This contradicts the whole idea of a standard API, and
leaves us where we are now - nothing but dedicated, specialized APIs
that are about as reusable as Microsoft APIs.
> > The API problem is that this has to be done at run time, unless we
> > want to end up with two actual standards used in parallel. This is
> > not a transition thing, but two different data types with slightly
> > different uses.
> >
> > There's no way we can make sure all plugins are available both in 32
> > bit and 64 bit versions, and not specifying support for both in the
> > API might end up as a big mess. For starters, how would a host
> > identify the dataformat of a plugin unless it's specified in the API?
> > If it's not possible to do in a safe way, and the user have both
> > kinds of plugins - boom!
> >
>
> I was assuming that the host and plugins would be compiled against the
> same header using the data type specified there. Is there no some type of
> versioning built-in to the API now?
Does that mean that there won't be development after the 1.0? If not,
versioning will force everyone to upgrade, or at least recompile
everything every few months, or alternatively, ignore any new plugins
or applications.
> It seems to me that the general
> solution would be to check for a API version (v1.1-64 or v1.1-32) when
> loading plugins to assure both binary compatibility AND data type
> integrity.
This won't work in real life unless all development is centralized.
The whole point with plugins is to make things pluggable; not to save
some RAM through dynamic loading of "built-in" code modules. How many
versions will there be? Why should people upgrade their code to the
latest version when it doesn't add any features they need? Can a
host support all versions without expensive or complicated hacks?
> > Anyway, I still believe the data formats should be separated from the
> > basic API. Ports should handle blocks of any number of bytes, and on
> > the binary level, at process time, the actual formats are determined
> > by the plugin code and any inlined host "plugins" that deal with the
> > data. Port compatibility is checked by the host when making
> > connections, or when loading the plugins. (Notice the distinction: The
> > latter implicitly states that it's not allowed to have plugins that
> > can instantiate with different data types from the same class. This
> > matters a whole lot to real time instantiation capable plugins and
> > hosts.)
> >
> <snipped lots of stuff>
>
> I guess I don't see any advantage to having different data types at
> runtime passing between plugins. Yes, if you specify data types on a per
> port basis you can create conversion plugins, but to convert what? 32 to
> 64 bit floats or vice versa? Either you want 64 bits - in which case
> there is little point to using 32 bit floats in the plugin network - or 32
> bits is good enough and you wouldn't want to use 64 bits because of the
> overhead.
Important point: Who decides what format to use?
(Hint: The user and the developer may not always be the same person.)
Also note that we don't have a $,$$$,$$$ machine to push developers
and users around to use whatever standard we decide on. They will use
the official standard, or fork/break the API.
> Allowing multiple data types will make both the API and the
> plugins MUCH more complicated with little gain.
No. I noticed Benno has been working on one solution, and I have
another one (don't know how similar they are). My solution means no
more work than for plugins to provide a list of data type descriptors
for it's ports, and for hosts to make sure not to connect ports with
different data type descriptors. Here's a snippet from my
work-in-progress:
---8<----------------------------------------------------------------
/*****************************************************************************/
/* Data Type Descriptors:
This API is (after some destructive hacking by David Olofson ;-)
basically separated from the audio and control data types used by
plugins and hosts. Hosts determine what ports can be directly
connected by comparing their LADSPA_DataTypeDescriptor entries.
Hosts may simply refuse to host plugins that use unknown data types,
or automatically insert conversion plugins as needed. The latter
alternative is preferable, as it enables almost any plugins to
run inside any host, even if the host itself does not know the
data formats used for connections between plugins.
Descriptors contain, in addition to the data type ID code, some
other information that the host can use to determine appropriate
buffer sizes and similar things, without having to know details
about the actual data types. This information must always be
correct, as some hosts may well depend on this information in order
to function properly!
The fields describing a data type are encapsulated in the
LADSPA_DataTypeDescriptor type. This is assembled by ORing
individual fields together.*/
typedef int LADSPA_DataTypeDescriptor;
/* Field LADSPA_TYPE_ID holds the data type ID code. */
#define LADSPA_TYPE_ID 0x0000ffff
#define LADSPA_TYPE_ID_B 0
/* Field LADSPA_TYPE_SIZE holds the size of an element of this type,
in bytes. */
#define LADSPA_TYPE_SIZE 0xffff0000
#define LADSPA_TYPE_SIZE_B 16
/* These macros extract the fields out of a LADSPA_DataTypeDescriptor. */
#define LADSPA_TYPE_GET_ID(x) \
(((x) & LADSPA_TYPE_ID) >> LADSPA_TYPE_ID_B)
#define LADSPA_TYPE_GET_SIZE(x) \
(((x) & LADSPA_TYPE_SIZE) >> LADSPA_TYPE_SIZE_B)
/* This macro turns an ID code into a field to OR into a
LADSPA_DataTypeDescriptor. */
#define LADSPA_TYPE_MAKE_ID(x) ((x) << LADSPA_TYPE_ID_B)
/* This macro turns element size into a field to OR into a
LADSPA_DataTypeDescriptor. */
#define LADSPA_TYPE_MAKE_SIZE(x) ((x) << LADSPA_TYPE_SIZE_B)
/* When constructing and testing new data types, use IDs in the range
LADSPA_TYPE_ID_PROTOTYPE through LADSPA_TYPE_ID_PROTOTYPE + 15. */
#define LADSPA_TYPE_ID_PROTOTYPE 0xfff0
/*****************************************************************************/
/* Data Types:
Plugin developers are strongly encouraged to use the official
data type descriptors listed here, and never to use the reserved
prototyping IDs in stable/final releases of their software. Useful
data types will be added to the official API when submitted to the
LADSPA team. Managing the descriptors centrally, as a part of the
LADSPA API is a means of avoiding plugins using different IDs for
physically compatible data types.
*/
#define LADSPA_TYPE_DESCRIPTOR_RESERVED 0x00000000
/* Integer Types (signed) */
typedef char LADSPA_Type_I8;
#define LADSPA_TYPE_DESCRIPTOR_I8 \
( 0x0001 << LADSPA_TYPE_ID_B \
| sizeof(LADSPA_Type_I8) << LADSPA_TYPE_SIZE_B)
typedef short LADSPA_Type_I16;
#define LADSPA_TYPE_DESCRIPTOR_I16 \
( 0x0002 << LADSPA_TYPE_ID_B \
| sizeof(LADSPA_Type_I16) << LADSPA_TYPE_SIZE_B)
typedef int LADSPA_Type_I32;
#define LADSPA_TYPE_DESCRIPTOR_I32 \
( 0x0003 << LADSPA_TYPE_ID_B \
| sizeof(LADSPA_Type_I32) << LADSPA_TYPE_SIZE_B)
typedef long long LADSPA_Type_I64;
#define LADSPA_TYPE_DESCRIPTOR_I64 \
( 0x0004 << LADSPA_TYPE_ID_B \
| sizeof(LADSPA_Type_I64) << LADSPA_TYPE_SIZE_B)
/* Real Types */
typedef float LADSPA_Type_F32;
#define LADSPA_TYPE_DESCRIPTOR_F32 \
( 0x0011 << LADSPA_TYPE_ID_B \
| sizeof(LADSPA_Type_F32) << LADSPA_TYPE_SIZE_B)
typedef double LADSPA_Type_F64;
#define LADSPA_TYPE_DESCRIPTOR_F64 \
( 0x0012 << LADSPA_TYPE_ID_B \
| sizeof(LADSPA_Type_F64) << LADSPA_TYPE_SIZE_B)
typedef long double LADSPA_Type_F128;
#define LADSPA_TYPE_DESCRIPTOR_F128 \
( 0x0013 << LADSPA_TYPE_ID_B \
| sizeof(LADSPA_Type_F128) << LADSPA_TYPE_SIZE_B)
/* Buffer Reference Type */
typedef struct {
void *data;
int size;
} LADSPA_Type_BufRef;
#define LADSPA_TYPE_DESCRIPTOR_BUFREF \
( 0x0020 << LADSPA_TYPE_ID_B \
| sizeof(LADSPA_Type_BufRef) << LADSPA_TYPE_SIZE_B)
/*****************************************************************************/
-------------------------------------------------------------->8---
Now, in your plugin, this is what you'll have to bother with:
/* This member indicates an array of port data type descriptor. Valid
indices vary from 0 to PortCount-1. */
const LADSPA_DataTypeDescriptor * PortDataTypeDescriptors;
I'm even thinking about adding this;
/* ...
By setting this member to NULL, the plugin indicates that it uses
only LADSPA_Type_F32 data, ie 32 bit float data for all audio and
control ports. */
but I'm not sure the extra check the host has to perform makes it a
good idea. If/when most developers of mainstream audio plugins decide
to use F64 instead, it's just wasted instructions and another
obsolete API feature that still must be supported.
> I can't see adding this
> complexity just to be able to do conversions (and I can't think of any
> other use for the multiple types).
Using plugins for different primary target environments, or just
coded by developers with different ideas. Allowing a set of plugins
to communicate something that the average host won't understand.
Using plugins for processing all kinds of signals and data, rather
than high end audio only.
Is it really a good idea to cripple the API just to remove a few
instructions from the simplest hosts? Any host that wants to support
more than one data format will be a lot more complex and messy than
*any* host for an API that supports multiple formats from the ground
up.
If you *really* don't want to support more than one format in you
host, you can just scan * PortDataTypeDescriptors, and refuse to use
plugins with anything but your favourite data format, rather than
checking before making connections.
//David
.- M u C o S --------------------------------. .- David Olofson ------.
| A Free/Open Multimedia | | Audio Hacker |
| Plugin and Integration Standard | | Linux Advocate |
`------------> http://www.linuxdj.com/mucos -' | Open Source Advocate |
.- A u d i a l i t y ------------------------. | Singer |
| Rock Solid Low Latency Signal Processing | | Songwriter |
`---> http://www.angelfire.com/or/audiality -' `-> david_AT_linuxdj.com -'
This archive was generated by hypermail 2b28 : Sat Mar 25 2000 - 21:23:24 EET