|Audio dropouts when using directsound|
Have recently been investigating reports of crackling/corrupt audio and tried to investigate. Using the same code, my audio was fine on one device (sb x-fi) but I could hear skips & artefacts on the other (onboard audio).
I eventually found my way into looking at the cursors returned from IDirectSoundBuffer_GetCurrentPosition, and tracking the positions. What I found was that on the sb x-fi, the distance between read & write cursors was within a constant range, where-as with the onboard audio the distance would decrease over time and then the write cursor would suddenly jump forward by more than a block, causing the glitch in the audio. SDL's WaitDevice() looks at the write cursor to decide when more audio is required, so there is nothing the application can do to rectify the situation other than ask for a block size higher than the largest increase (so that the sudden increase in write cursor position doesn't cause it to jump a full block).
In the case on my local machine, I was using blocksize of 128 samples (512 bytes), typically the cursor was moving forward at 10/11ms (440/444 bytes) but then would suddenly leap forward by double that amount (around 880 bytes), skipping a full block.
To work around this, I modified SDL:
1) Added DSBCAPS_TRUEPLAYPOSITION flag, so that the play cursor is updated more often (supported since Vista)
2) Added a hint so that the app can tell SDL "assume the real write cursor position is at least X bytes after the read cursor"
This is essentially taking the smooth play cursor and working out an equivalent smooth write cursor position, then using that to determine when & where to place the next block of audio. (In retrospect, it's possible this could be turned into a boolean flag, and the size of the required buffer could be determined every time the write cursor changes.. haven't tried that tho)
(source changes here)
Is there a better way round this? I feel certain I must have made a mistake somewhere, or is everyone else using larger buffers?