Synchonous and asynchronous streaming in aRts
There are various requirements how a module can do streaming. To see the
difference, here some examples:
- scale a signal by factor two
- sample frequency conversations
- decompressing encoded signal, run length encoded to make it difficult
- read midi events from /dev/midi00 and put them into a stream
The first case is the simplest. On getting 200 samples input, the module
produces 200 samples output. It only produces output when it gets input.
The second case produces different output sizes on 200 samples input,
depending what conversion is performed.
The third case is even worse, from the outside you can not even guess how
much data 200 bytes in will generate (probably a lot more than 200 bytes,
but...)
The last case is a module which becomes active by itself, and sometimes
produces some data.
In aRts-0.3.4, only streams of the first type where handled, and most things
worked nicely. So this is probably what you need most when writing modules
that process audio. The problem with the other, more complex types of
streaming is that they are hard to program, and that you don't need the
features most of the time.
That is why I'll to this with two different stream types:
synchronous streams:
- modules must be able to calculate data of any length, given they have
enough input
- all streams have the same sampling rate
- the calculateBlock function will be called when enough data is available,
and the module can rely on the pointers pointing to data
- there is no allocation and deallocation to be done
asynchronous streams:
- modules may produce data sometimes, or with varying sampling rate, or
only if they have input from some filedescriptor - they are not bound
to the rule "must be able to satisfy requests of any size"
- asynchronous streams of a module may have entierly different sampling
rate
- outgoing streams: there are explicit functions to allocate packets, to
send packets - and an optional polling mechanism that will tell you when
you should create some more data
- incoming streams: you get a call when you received a new packet - you
have to say when you are through with processing all data of that
packet, which must not happen at once (you can say that anytime later,
and if everybody has processed a packet, it will be freed/reused)
When you declare streams, you use the keyword "async" to indicate you want
to make an asynchronous stream. So for instance assume you want to convert
an asynchronous stream of bytes into a synchronous stream of samples, your
interface could look like:
interface ByteStreamToAudio : SynthModule {
async in byte stream indata; // the asynchonous input sample stream
out audio stream left,right; // the synchronous output sample streams
};
back to index