http://bugs.winehq.org/show_bug.cgi?id=14717
--- Comment #260 from Andrew Eikum aeikum@codeweavers.com 2012-01-03 12:19:08 CST --- (In reply to comment #259)
In bug #9358, comment #21, Maarten Lankhorst explained that primary.c:DSOUND_fraglen is a hack to second-guess the period size as "the current driver model doesn't" tell. This is no more the case. The hack should be removed. The period size is IAudioClient_GetDevicePeriod. With mmdevapi, DSound receives one event every such default period and that's the quantity that it should mix (currently winealsa/oss: 10ms, winecoreaudio: 20ms). IOW, it should act like the XAudio2 in bug #28723 -- ouch! I don't know when DSound is allowed to send more data in advance.
While investigating multi-channel support, I found that primary buffers with sufficiently large frame sizes (6 channel, 24 bit) can actually cause bugs where the total number of fragments in the buffer is the same as the prebuffer size (buffer = 65536 bytes, fraglen = 6144 bytes -> helfrags = 10; snd_queue_max = 10; helfrags <= snd_queue_max) which creates no audio output due to "pwplay %= snd_queue_max"-style logic.
So I wonder if a solution is to make the primary buffer size be (snd_queue_max + 1) * fraglen, and perhaps calculate fraglen from the mmdevapi period size, like you suggest.
I'm not familiar with DSound, but why another buffer? Why not GetCurrentPadding & GetBuffer, then mix into that one, eventually ReleaseBuffer (may release a smaller number of frames)? Sadly, DSound's primary buffer may match HW well, but not mmdevapi's buffer model...
It's unrelated. We need to resample into a temporary buffer, and then mix that into the primary buffer, which later gets copied into the mmdevapi buffer. We might be able to optimize it later, but this works well enough for now.