[LAD] Jack ringbuffer

Len Ovens len at ovenwerks.net
Thu Dec 10 21:57:45 UTC 2015


On Thu, 10 Dec 2015, Will J Godfrey wrote:

> On Thu, 10 Dec 2015 06:51:48 -0800 (PST)
> Len Ovens <len at ovenwerks.net> wrote:
>
>> You can check if there are 4 bytes available, if not don't read (yet).
>> Normally (at least for anything I have done) the reason I use the ring
>> buffer is to divorce the data processing from any real time requirement.
>> So I am reading the ring buffer in a loop, I can check how many bytes are
>> available. jack_ringbuffer_read_space(buffer) can be used I think.
>
> I'm doing this. My main concern was whether the pointers would be updated in
> byte steps or block size steps, and what implications that might have.
>
> I'm quite prepared to believe I might be over-thinking the problem. This has
> been known before :)

On the input end of the ringbuffer we put a set number of bytes into the 
buffer. This is done during the time our app has it's time to do whatever 
it is going to do in that jack period. But this callback might be running 
on another core than the rest of the app and so it is possible that the 
write event may be only partly done when our app looks at the buffer. That 
is why it is not known that if there is data there it has all been 
written. However, the call back is a RT thread and so it will finish the 
write "real soon".  So there should be an event's worth of bytes by the 
time you look at it a second time. A time out does not really make sense 
that I can see. I don't think the ring buffer is un reliable. But, don't 
read till all the bytes are there.

The answer to your question of how the pointer is updated, does't matter 
really. What matters is if everything that goes in gets to the output. So 
if one checks that the right number of bytes are there before reading, it 
doesn't matter. The safe way to do things might be to update the pointer 
after each byte written. The least code way/cpu way may be to write n 
bytes then update. But Paul's answer seems to indicate the first is 
true... but, the buffer can be written to manually too, where the input 
manually inserts a byte at a time and updates the pointers after each 
byte. The API allows that from what I can tell. In fact, if the calling SW 
wanted to, it could write 10 bytes and only update the pointer 3, write 
another 3 and then update the pointer 10 (I can't see any sane SW doing 
so).

But you have control of both the input and the output, so you can make 
sure the event based input API is used rather than a manual method. The 
jack ringbuffer does not force you to code in a sane manner, but you can 
still choose to code in a sane manner if you want to.

In general, jack does things in chunks. It starts doing things at the 
beginning of a period going through all it's call backs and when finished 
it does nothing till the beginning of the next period. On a single core 
system, it is this time when your application will be looking at the 
non-RT end of the ringbuffer. So in general, so long as the RT end can 
always access the right number of bytes when it needs to, everything will 
work.... nothing will be lost.

Someone will correct all my mistakes I am sure.

My own code, after having thought this through in answer to your question, 
does not do enough checks at all  :)  I need to go back and fix some 
things. Oddly enough, it does work  :)  My particular code is all MIDI 
events and so those events are various sizes, not all 4 bytes. I started 
off with more than one ringbuffer for each expected event size. This meant 
I had to do my sorting in RT, so I have now gone to one buffer and parse 
it on the output. With one, two or three byte events, I can easily look 
for the right number... I pull one byte, parse it and know I have it all 
or expect one or two more. However, I do use sysex events as well so I 
have to look for an eox.

Len goes back to redo a big chunk of his code. I must be missing at least 
some events.

--
Len Ovens
www.ovenwerks.net



More information about the Linux-audio-dev mailing list