http://bugs.winehq.org/show_bug.cgi?id=29585
--- Comment #48 from Chris Purnell cjp@lost.org.uk 2012-04-06 14:14:20 CDT --- I've found what was causing me crackling with dsound playback.
I was watching the "padding" in the logging and noticed that I was getting the crackling every time it hit 0. This padding value is the held_frames. For me this was hovering around 1024 and always a multiple of 512 and never more than 2048. So it didn't take much for it to hit 0.
Now 512 was what dsound had chosen as a fragment size in frames based upon the sample rate which in this case was 44100. My sound device was defaulting to a fragment size of 1024 frames.
Dsound was tying to keep the sound device filled with 10 of its fragments and wineoss.drv was trying to keep 3 whole device fragments buffered in the sound device. So yeah, 10*512(from dsound) = 3*1024(written) + 2048(held).
The condition under which I was getting crackling (frames_held==0) is one that occurs more often with larger device fragment sizes.
The crackling was not the result of any underrun. In fact it existed in the data that was being written.
What dsound was doing was instead of adding 1 or 2 of its fragments it was buffering all 10. It was doing this because the value from GetPosition was jumping ahead to exactly 10 dsound fragments beyond the dsound's saved value.
AudioClock_GetPosition in wineoss.drv has a check for !This->held_frames and if so does not subtract the value it gets from SNDCTL_DSP_GETODELAY. This delay was hovering around a little under 3-4 device fragments. That is about 7 dsound fragments.
What I'm guessing is that dsound does not have the data for that far ahead and is mixing in 0s. It probably should not be doing that but then wineoss.drv should definitely not be reporting the position of an underrun event that has not happened yet.
Removing the "|| !This->held_frames" from AudioClock_GetPosition got rid of the crackling for me.
Looking at the corresponding ALSA code there does not appear to be an equivalent test.