http://bugs.winehq.org/show_bug.cgi?id=19124
--- Comment #3 from Jörg Höhle hoehle@users.sourceforge.net 2009-09-15 11:00:33 --- It's only now that I realize that bug #20056 "crash follows bogus DSOUND:SetFormat call" completes the information here, but is not a different bug.
From that we now know there's at least one bug in SetFormat()'s handling of the
device->pwfx structure. Why warn+heap matters is still unclear.
For whatever reason, The Westerner calls SetFormat initially (when displaying the main menu) with the bogus values shown in bug #20056 (with or without warn+heap). (formattag=0x0001,chans=0,samplerate=0,bytespersec=0,blockalign=0,bitspersamp=0,cbSize=0) but I've also seen chans=1812, nSamplesPerSec=456741109, nBlockAlign=28872
It's only when the introductory western movie starts that reasonable values are supplied.
That bogus SetFormat explains all the rest. Those bogus values are stored in device->pwfx. After ReopenDevice, the timer interrupts kicks in but does do not much. When CreateSoundBuffer is called, the bogus values lead RecalcFreqAcc to estimate the new buffer length to nearly 2GB (which explains the errors from allocate_large_block). After that, when the timer interrupt kicks in, MixToTemporary wants to adjust the frequency from 22050Hz to 456MHz. The error from MixInBuffer about length not being a multiple of block size follows soon. And again and again every time the interrupt triggers.
An experimental plausibility check (nchannels<6) aborting SetFormat leads to reasonable behaviour. warn+heap is then not needed anymore.
http://msdn.microsoft.com/en-us/library/bb206059(VS.85).aspx "The method succeeds even if the hardware does not support the requested format; DirectSound sets the buffer to the closest supported format. To determine whether this has happened, an application can call the GetFormat method for the primary buffer and compare the result with the format that was requested with the SetFormat method." This suggests that it is acceptable to ignore bogus formats (that can be detected early), arguing that the "closest supported" was the previous or default one. The app ought to call GetFormat to see what's actually being used.
Nevertheless the dsound code should leave the device in a sane state even after ReopenDevice fails.