[…]
I use these stuff to synchronize the buffer read & write. I have two
thread, one for decoding and write the audio data to my buffer, the
other for reading the audio data from the buffer, so I use
mutex/cond to protect the buffer.
Using multiple threads and locking means you’re letting go of the CPU
every now and then - and when you do, you’re not always getting it
back ASAP. General purpose operating systems don’t behave very well
in this regard, and there is little we can do about that, short of
switching to a different OS.
If you need to do things like this, you need to use lock-free
solutions. You can never turn a non RTOS into an RTOS, but at least,
you can reduce the risk of drop-outs by not asking for more trouble
than you have to.
However, before even considering this (lock-free solutions are hairy
business), you should make sure your solution is theoretically
correct in the first place…!
I would like to send the buffer to audio device with nearly 0
latency, which means I need my audio callback function works as fast
as possible, but I find it sometimes takes more than 40 ticks, stuck
in the SDL_Lock/Unlock.
You can’t affect latency in that way. You can be en time, or you can
be late. If you’re on time everything works fine, whereas if you’re
late, you get a drop-out. That’s all there is to it, really.
The audio callback is called as soon as the driver has room for
another buffer of audio, and from that point, you have practically
the full playback time of that audio buffer (ie samples_per_buffer /
output_sample_rate) until you actually have to return. Returning
earlier has no effect whatsoever on latency.
That said, there is a reason to keep the audio callback light:
Finishing quickly means you have more margin for OS induced “coffee
breaks”. The callback may (or rather, will) sometimes fire a bit
late, and then, obviously, you have a better chance of still
finishing in time if you have less work to do. However, you shouldn’t
really care about this unless you’re using substantial amounts of CPU
power for audio processing. (Your average games sound engine would
use a few % of the CPU time available. That’s not an issue worth
considering in this regard.)
You cannot avoid the problem by moving the work elsewhere. All that
can ever do is make things worse. If you can’t deliver the data in
time, there is no way you can make the buffer deadline, no matter
what you do.
Maybe I should not use any protection in my read thread so it would
work pretty fast?
That would solve only one thing: It would avoid blocking the audio
callback. However, that would just mean your audio callback runs with
no input every now and then, so you still get your output ruined.
This is only of use when you have other streams playing at the same
time, or when you’re streaming from disk or similar. In the latter
case, you’d add some intermediate buffering between the
streaming/decoder thread and the audio callback, to allow for more
timing variations without causing drop-outs in the stream.
If you really need low latency all the way from input to output (which
is unusual in the context of codecs), the only real solution is to
just do all your sound processing in the context of the audio
callback.
//David Olofson - Programmer, Composer, Open Source Advocate
.------- http://olofson.net - Games, SDL examples -------.
| http://zeespace.net - 2.5D rendering engine |
| http://audiality.org - Music/audio engine |
| http://eel.olofson.net - Real time scripting |
’-- http://www.reologica.se - Rheology instrumentation --'On Thursday 06 December 2007, Mine wrote: