Subject: [linux-audio-dev] aes: new model
From: Paul Davis (pbd_AT_Op.Net)
Date: Thu May 17 2001 - 21:08:05 EEST
prompted in part by discussions here and partly from discussions on
ardour-dev, i've been revising the design of aes. its about 75% done
right now. here's an attempt at a summary. the big change is that
there is no direct access to the DMA buffers (all audio is written to
Engine-provided buffers), and the object responsible for interfacing
with audio h/w (or whatever) is mutable at run time.
objects:
Port : a description of an input or output
Nodes : has 0...N input ports, 0...M output ports
Plugin : a kind of Node with a "process(nframes)" function
Driver : a kind of Plugin with a "wait()" function
Engine : has a list of Plugins, and a single Driver
the main loop of the audio thread now looks like:
while (!done) {
driver->wait ();
}
inside driver->wait() we do something like:
poll ();
... determine how much data/space is available ...
engine->process (nframes);
move_output_data (); /* moves data from the driver's output ports
to the audio h/w
*/
and Engine::process() looks like:
foreach plugin in sorted Plugin list { plugin->process (nframes)
Note that a Driver is a kind of Plugin. So, the Engine builds a signal
graph for the current interconnections between all the ports, and
executes all Plugins (including both the Driver and regular Plugins)
in the "correct" order (if such a thing exists).
Expected signal flow:
driver internals (e.g. ALSA) -> driver output ports ->
plugin input ports -> plugin processing -> plugin output ports
driver output ports -> driver internals (e.g. ALSA)
Expected execution flow (if the graph looks like the description above):
driver->process (nframes); /* moves data from the audio h/w
to the driver's input ports. */
all other plugins
In the current design, there is only a single driver associated with
the engine.
The design is fairly MP and SP friendly: the engine can instantly
update all Plugins on the locations of their output and input buffers,
which can live in shm for the MP case. The mechanics of
plugin->process() can either be handled by a direct function call (SP)
or via a signal/pipe wake up of the relevant plugin process. This is
all very easy to do.
i don't yet know whether the use of all-engine-provided-buffers and no
direct writing to DMA areas will be more or less efficient than the
old AES design that used write_to_channel etc. but i am convinced that
this design is more correct and more flexible than the old one. It may
be faster to. we'll see.
The engine no longer supports busses directly. Busses would be
supported by a specific plugin, whose job was simply to declare N
inputs and N outputs, and to run a process() function that did
basically nothing. There's work to do on the details of this, but the
idea has great appeal for me, and may help settle the argument over
patchbay/bus designs.
this is not so different than a model Abramo proposed, which did
something like:
foreach plugin { plugin->wait (); }
foreach plugin { plugin->process(); }
however, for reasons that have been discussed here, i (and some other
people) don't believe that a low latency model will allow "waiting" on
anything except the PCM device state, and so i derived a slightly
different type of plugin, the "driver". a single driver is the only
thing which the engine wait()'s for before executing the signal graph
via plugin->process().
"Those who do not understand aRtS are condemned to reinvent it" :)
--p
This archive was generated by hypermail 2b28 : Thu May 17 2001 - 21:47:27 EEST