My ultimate goal was to solve the dsound underruns which were so
horrible that I had to disable sound in World of Warcraft. While I
managed to get the sound working flawlessly (really... I never heard
such clear sound under wine) in WoW, it required WoW-specific hacks so
my patch will never make it (in its current form) into the official git
tree, but maybe someone can use some of my ideas to improve dsound/winealsa.
The basic idea is to let alsa mix the sound instead of the infamous
dsound mixer. The advantage is that if the hardware supports mixing,
there is very little overhead, if not, there's still dmix which can do
that, but dsound doesn't need to care how it's done, it's entirely up to
alsa.
Now to the actual implementation, it's pretty straight-forward: I
'forced' CreateSoundBuffer to create a hardware buffer (right now it
creates a hw buffer only for the primary buffer) and changed the
winealsa driver to support that. Because winealsa driver opens only one
'connection' (snd_pcm_t) to the soundcar (allowing only one buffer per
device), I simply opened a new 'connection' for each buffer and
configured the hardware for 44100Hz/U16LE/stereo (that's what WoW
expects). Up to this point it was easy.
One of the big problems was that WoW requests a 16kb buffer, but alsa is
unable to allocate a buffer with this exact size, and it caused problems
if I passed the alsa buffer to WoW (so WoW could write directly to it).
I had to allocate a separate buffer, keep track of the play/write
positions in both buffers and copy the data from one to the other.
I'm fairly sure this all could be done in a WoW-independent way, eg.
configure the hardware as the application requests it (by passing
LPCDSBUFFERDESC to the low-level driver etc) and keeping track of the
read/write positions could also be done in a better way.
There are a free questions that should be answered before someone can go
on and make a 'proper' implementation. I simply bypassed the primary
buffer, it doesn't exist since the data from the secondary buffers are
written directly to the soundcard. If it should be possible to read the
data from the primary buffer then we should forget this all and look for
another solution. I believe that it's not possible (it's not possible to
write to the primary buffer and the API doesn't differentiate between
reads and writes), but someone should test that under windows.
(this is only one question but I'm sure you'll come up with more ;) )
Here is the complete patch, I also changed the IDirectSound interface
and a lot unrelated code, so the patch is a bit big :-/ There also are a
few memory leaks, I didn't bother freeing the memory etc.
http://dbservice.com/ftpdir/tom/dsound-alsa.patch
tom