Re: [linux-audio-dev] API design again

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

Subject: Re: [linux-audio-dev] API design again
From: David Olofson (audiality_AT_swipnet.se)
Date: to loka   07 1999 - 16:38:29 EDT


On Thu, 07 Oct 1999, Paul Barton-Davis wrote:
> >If it was only about the 5% (or whatever) of CPU time, I would have
> >dropped the buffered event system. But how do you generate and/or
> >process events in a system where plug-ins don't know about events? I
> >see events as data that can be processed - not just a simple
> >parameter control interface.
>
> Its not about keeping the event system hidden from the plugin. Its
> about separating the delivery of real-time information about the state
> of the world from the request to process some sound.

Ok. Good point.

However, there is another point in keeping the event processing in the process()
function, apart from eliminating two extra function calls per state change: The
plug-in gets to decide the actual event timing precision. That is, if there is a
significant performance advantage in quantizing to a certain number of samples
(SIMD code, FFTs...) and full sample accuracy doesn't make much sense, the
plug-in code can be optimized that way.

That could be done by telling the engine about buffer size granularity or
something, but that adds code to the main path of the engine. Too many features
of that kind will make it very hard to hack efficient implementations...

Plug-in code would hardly add any overhead at all, as any quantizing would be
hardcoded.

Another advantage of using *fixed buffer sizes* and inline event handling in
the process() function, is that the entire "dynamic" buffer size management
logic moves out of the main engine code path.

Of course, this is only about performance. How much CPU is a simpler process()
function allowed to cost? :-)

> Clearly, a plugin must still be able to handle state changes. But the
> code to do that will, in most cases, simple be resetting variables,
> setting flags, etc. This is quite distinct from the task done by
> process(). If an event generates or actually contains data to be
> processed, then it goes into the plugin via process(). If it merely
> tells us about a state change ("MIDI NoteOn", "GUI says value shifted
> to 0.92", etc.), then the plugin gets told via (we'll call it ...)
> notify().

...but how would that be done if events are to be processed by another
callback? It's all or nothing here; no point in moving *some* events out of
process().

However, supporting two "levels" of plug-ins may be an alternative...

> Think of it another way. Lets suppose I have the code for the Antares
> AutoTune TDM plugin. Lets suppose its written without any idea of an
> event system, it might even be written without much idea that its a
> plugin at all.
>
> If I want to use this code as a plugin for <insert-plugin-API-name-here>,
> then there are two possibilities that I can see:
>
> 1) if the API passes an event buffer to process()
>
> - I need to write a wrapper for the code along the lines suggested
> by Roger Larsson.
>
> 2) if the API passes events to a separate function, and a frame count
> to process()
>
> - I can probably use the code as-is, and add an event-handling
> function.
>
> So, in both cases, I'll have to do some real work. Which is better ?

Three possibilities:

3) if the API passes an event buffer to process()

   - You can use the code as-is (turn it into an inline if you like)
     and use it from your new "event handling" function, which is
     actually the new process() function.

> My guess, and its only a guess, is that for the most part, it will be
> less work, and less disruptive to the code, to use (2). But I could be
> wrong.

Not sure either, but I think it's more a matter of coding style than how well
the API fits code from other environments. A nice wrapper template (no, not a
C++ template! :-) should cover the "quick'n'dirty" porting. If you want the
best of performance and features of the new API, you need to do some extra
work on the details anyway.

> I see this as a key question, because the idea that the only
> code to be used with a plugin API will be new code is crazy - reuse is
> part of the whole joy of open source, and
> reuse-without-excessive-rewriting is even better.

It's important, but the issues you mentioned are probably more important if you
*don't* have the source code. Binary level wrappers can be hard to get efficient
no matter how similar the APIs are. While adding an "inline" here and there
directly eliminates the extra function call overhead, and then you can have a
look at the data type declarations, and the function prototypes... And *then*
you could start to look at the actual "old_process()" code, if you think
there are more cycles to gain.

//David

 ·A·U·D·I·A·L·I·T·Y· P r o f e s s i o n a l L i n u x A u d i o
- - ------------------------------------------------------------- - -
    ·Rock Solid David Olofson:
    ·Low Latency www.angelfire.com/or/audiality ·Audio Hacker
    ·Plug-Ins audiality_AT_swipnet.se ·Linux Advocate
    ·Open Source ·Singer/Composer


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:27:13 EST