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



Reply via email to