Re: [LAD] Realtime and helper threads

From: Olivier Guilyardi <ml@email-addr-hidden>
Date: Wed Aug 27 2008 - 14:27:52 EEST

Dan Mills wrote:
> On Sat, 2008-08-23 at 14:56 +0200, Olivier Guilyardi wrote:
>
>>> That is a fairly common approach, one thread per core is good. I have
>>> code that reads audio, sample rate converts it, time-stretches it if
>>> appropriate and sticks it in a ring buffer. The realtime thread does not
>>> pay any attention to the transport at all, it just handles the realtime
>>> controls (some mixing and routing in my case).
>> I am unsure what you mean by "core".
>
> Processor core on the machine, having multiple threads will allow more
> then one core to be utilised if required.

Right. Although this is one of the reason I thought about helper threads, I also
believed it could help on single cpu systems. For this to be true, is the only
solution to have a big ringbuffer?

>>> One thing you do want to watch is that the disk IO threads should
>>> probably run at a realtime priority (just lower then the one for the
>>> audio thread), otherwise a make -j10 on the kernel can result in
>>> ringbuffer under run.
>> Disk IO is another problem to me. I would prefer to focus on computation load
>> here, that is: helper threads that performs audio conversion/transformation,
>> etc.... I assume that the thread priority you advise also concerns this though.
>
> It would, in my app it is basically disk io that feeds the system but in
> your case it seems to be something else, but the same principle applies.

Okay, so just a side question about disk IO: can you do that in a realtime
thread? On http://rt.wiki.kernel.org/index.php/HOWTO:_Build_an_RT-application,
it says: "File handling is known to generate disastrous pagefaults. So,if there
is a need for file access from the context of the RT-application, then this can
be done best by splitting the application in an RT part and a file-handling part".

>>> If you need to be able to vary the timestrtch in real time with a file
>>> playing, any ring buffer after the timestretcher will need to be short,
>>> otherwise it is fairly straightforward.
>> That worries me a bit. If my ringbuffer is really short, for responsive user
>> control, and the time stretching performed in a non-RT thread, isn't this going
>> to make things worse?
>
> I was advocating having this done in a RT thread at lower priority then
> the audio thread.

Right, sorry I misread this. Just a little practical question here: what could
be the event waking my RT helper thread? Sleeping for a fixed amount of time,
waking up, checking if there's some write space in the ringbuffer, if not then
sleeping again?

> How much control latency can you tolerate? That number will tell you
> what is possible in terms of approach, quantify the problem.

It depends on the control type. I'm having problems thinking about this for time
stretching, I've never done it and it operates on time, which will interfere
with bpm, transport position, etc.. But in regard to pitch shifting, I would
like the latency to be as small as possible. Something less than 30ms. At
44100Hz, on a mono track, a buffer of 1024 bytes would do I suppose.

>> What about the following idea:
>>
>> Say I make a Converter object, which performs time stretching. It doesn't know
>> anything about threading.
>>
>> I also have a Reader object, with an internal ringbuffer, it reads raw audio
>> data, converts it using the Converter, and fills its ringbuffer with the
>> converted content.
>>
>> The Reader objects exposes read(double time_ratio, int nframes) to the realtime
>> thread. When this function gets called, the Reader checks if it has data time
>> stretched according to this time ratio in its internal ringbuffer. If it does it
>> simply returns it. Otherwise, it calls the Converter on the fly, discarding the
>> irrelevant data in the ringbuffer, and causing a sudden small overhead.
>
> Then you are no longer realtime as Linux audio understands the concept.

What do you mean?

>> Once the time ratio has stopped varying (the user has stopped playing with the
>> knob), the ringbuffer rapidly gets filled with data at the right time ratio, and
>> the overhead vanishes.
>
> It still does not solve your problem as clicks and pops can happen while
> the user is playing with the knob.

No, I believe it could solve it: this is only a small overhead, on a single
track, for a short period of time. This is very different from, say, performing
time/pitch shifting in realtime on 16 tracks. In my idea, when the user vary the
pitch, you would only have one track that would temporarily perform some heavy
computation in realtime. The other 15 tracks would still rely on the background
job performed by the helper thread. This way I could have big ringbuffers (say
64k), to ensure smooth output.

Regards,

-- 
  Olivier Guilyardi / Samalyse
_______________________________________________
Linux-audio-dev mailing list
Linux-audio-dev@email-addr-hidden
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev
Received on Wed Aug 27 16:15:02 2008

This archive was generated by hypermail 2.1.8 : Wed Aug 27 2008 - 16:15:02 EEST