tinyalsa / tinyalsa

Tiny library to interface with ALSA in the Linux kernel

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to get a low latency audio callback

sfjohnson opened this issue · comments

Hi,

I realise this may be outside the scope of this library but I was wondering if there is a standard way to take the blocking IO calls (pcm_writei and pcm_readi) and create a periodic audio callback that feeds the user a small amount of samples each time to minimise latency?

I'm guessing it involves using pcm_get_poll_fd and poll(2), but what I'm not sure about is the callback thread. I thought audio callbacks are supposed to run on "special" OS-defined realtime threads but is it just a case of messing with sched_setscheduler(2)?

Thanks!

I realise this may be outside the scope of this library but I was wondering if there is a standard way to take the blocking IO calls (pcm_writei and pcm_readi) and create a periodic audio callback that feeds the user a small amount of samples each time to minimise latency?

I'm guessing it involves using pcm_get_poll_fd and poll(2), but what I'm not sure about is the callback thread.

I wouldn't say there is a standard way, although you don't need a different thread to do that. If you use the non-blocking I/O and poll the file descriptor in an event loop -like pattern, you should be able to run a callback with minimal latency.

I thought audio callbacks are supposed to run on "special" OS-defined realtime threads but is it just a case of messing with sched_setscheduler(2)?

Yes. Using a real-time scheduler (e.g. SCHED_FIFO) for the tasks involved in audio processing is useful to prevent overruns (when the device is about to overwrite bytes that you haven't read yet) or underruns (when the device is about to consume bytes that you haven't written yet).

Thanks for the info. I ended up getting this working by using SCHED_FIFO and PCM_MMAP and polling pcm_mmap_get_hw_ptr(). I've got a 64 sample buffer size @ 48kHz pretty stable on both Android and Raspberry Pi. I think there may be some driver / scheduler bugs on my Android device because the timing goes haywire when period_size is > 32. On RPi I'm using Preempt RT and everything is nice and stable.

Soon I'll be integrating TinyALSA into my network audio project Waterslide.

@sfjohnson if you are dealing directly with hw_ptr, I recommend you to check out a library that I wrote called NanoALSA https://github.com/psqli/nanoalsa. It's a smaller version of TinyALSA only for interacting with PCM devices.

Also, you may want to implement a timer-based audio scheduling, where a high resolution timer wakes up the audio I/O task. Therefore, it's possible to set period size to higher values. However, it may be necessary to periodically synchronize the system timer with the PCM device.