Good news - I have got it working. It required work in both the mixer and the Wine ALSA sound driver. It works on my system if the ALSA driver is used and hw emulation is NOT used (in winecfg).
If anyone would like to test patches, give me a hoy. In particular I'd like to make sure it doesn't break anything else - StarCraft is one of the few Windows apps I actually have :-)
Davin
On Fri, 28 Oct 2005 18:24:36 +1000 Davin McCall davmac@davmac.org wrote:
Hi,
I'm trying to sort out sound problems with StarCraft and have made some progress by hacking around with the "dlls/dsound/mixer.c" file. I'm new to Wine hacking however, and there's some things in the code which I don't understand (and others which seem blatantly wrong).
Hopefully someone can help me with these questions:
- In DSOUND_PerformMix(), two values inq and maxq are calculated which seem to represent the amount of already-mixed (prebuffered) data in the primary buffer and the maximum amount that should be prebuffered. See lines 1001 - 1012.
Then the comparison "inq > maxq" is made to detect whether all buffered data has been played, and if so the sound is stopped by calling DSOUND_PrimaryStop. However, inq is based on the *writepos* value which is the play position plus a safety margin (latency) - see line 972.
So, sound is stopped before the play position actually reaches the end of the buffered audio. This seems wrong. Can anyone tell me if this is correct (and if so why) or if it really is wrong.
- (same function) on line 1048, after using DSOUND_PrimaryStop(), the playpos is retrieved by making a driver call. The comment says that DSOUND_PrimaryStop() is supposed to reset playpos to 0, but OSS cannot do this and that is why IDsDriverBuffer_GetPosition() is called. However, with ALSA, the driver returns the last played position, even though when the sound is restarted (ie. when DSOUND_PrimaryPlay is called) the position does go back to 0. The result is that playpos is wrong in the meantime. If a sound buffer is added to the queue it gets mixed at the wrong position.
So, should the ALSA driver return 0 for IDsDriverBuffer_GetPosition() or is it simply wrong to use that function to retrieve play position after stopping the device? (and if so, is there a better solution)?
- Was whoever wrote this code allergic to comments? :-)
I'd appreciate any help I can get.
Davin