This algorithm is fairly similar to what currently exists in ALSA with a few modifications. I'm trying to come up with guaranteed way to play glitch free audio. Does this algorithm work or could it be modified to work?
The main change is to track a high resolution timer as the means of estimating where in the buffer to insert new, low latency data. This tracking is done in a timer tick interrupt. Jiffies are too coarse and not all hardware allows you to ask the current DMA position.
The other change is to keep all of the buffers filled with silence if there isn't any pending data. (not doing this caused problem in my mpc5200 AC97 driver)
Three buffers are used as a way to deterministically bound the DMA pointer without needing interrupts.
---
Use three chained buffers. Buffer size is samples/tick (or maybe 1.5 samples/tick) Initialize buffers to silence. Set end of buffer three to automatically terminate DMA
Set FIFO to minimum bus allows Fill buffer one with samples available, start playing.
On timer tick call into driver.. If buffer one has finished playing move it to third position. New last buffer is set to automatically stop DMA. Return swap status to ALSA If swapped, fill buffer three with silence or pending data It is important to fill this buffer with silence if there is no pending data
The size of the buffers needs to be large enough to cover worst case timer tick latency. Buffer two has to be large enough to ensure that the tick routine will notice buffer one has been played before buffer three starts.
If two buffers have been completed when the tick runs, let the third buffer finish without swapping. Since you don't know where you are in the third buffer, it is unsafe to swap at this point.
Playing the last buffer causes the end of buffer interrupt to happen. Callback into ALSA to alert it of the underrun and need to restart DMA. If this callback happens, make the buffers larger.
Long term observation of buffer completion status in tick handler will allow accurate computation of samples/HPET unit. Record high accuracy timer (HPET) on tick.
New low latency data that arrives can be inserted into the buffers dynamically. Use the high resolution timer source to estimate where to place it. Minimum FIFO ensures low latency play.
Design a minimum power mode. Allows a huge FIFO to be loaded (like 128KB). Call into driver to reset to minimum latency, small FIFO mode.
Advantages:
1) If ALSA goes away, hardware will stop on it's own with no noise. 2) No need to know the current position of DMA hardware. 3) Both low and high latency modes. 4) Audio interrupts only generated as error condition 5) Behavior is deterministic. Nothing is left to guess work.