WINEALSA: comment on unexpected shrinking of mmap-buffer (resend)

Alex Villací­s Lasso a_villacis at
Thu Aug 11 14:32:33 CDT 2005

Alex Villací­s Lasso wrote:

>> The good news: the patch sort of works (in my setup, at least, with 
>> Fedora Core 4). All the games I have (Japanese RPGs) now have smooth 
>> sound, unless the CPU load is too high.
>> The bad news: the patch does nothing to make the dsound tests pass in 
>> Wine (but they were already failing before the patch :-)
> In a previous post, I commented about DirectSound tests failing when 
> ALSA is used with full hardware acceleration. Now I know the reason why.
> As far as I can glean from the code, DirectSound is supposed to report 
> the application several properties of the sound system, including the 
> size of the hardware buffer. This hardware buffer is queried by the 
> snd_hw_params_get_buffer_size(), and is then converted from frame 
> units to bytes. Then the application, or in this case, the test, 
> expects the buffer size to remain constant for each and every hardware 
> buffer created, regardless of requested format. Only this assertion 
> fails in ALSA. For example, the capability query causes the following 
> output to be shown:
> trace:wave:DSDB_CreateMMAP format=U8  frames=11025  channels=2  
> bits_per_sample=8  bits_per_frame=16
> trace:wave:DSDB_CreateMMAP created mmap buffer of 11025 frames (22050 
> bytes) at 0x7c0fd100
> This reported size (22050 bytes) remains constant as long as the 
> request is for U8 format with 2 channels (although the mmap address 
> jumps between three different values in my setup; this may or may not 
> be relevant). However, as soon as the requested format changes, the 
> trace shows the following:
> trace:wave:DSDB_CreateMMAP format=S16_LE  frames=3763  channels=2  
> bits_per_sample=16  bits_per_frame=32
> trace:wave:DSDB_CreateMMAP created mmap buffer of 3763 frames (15052 
> bytes) at 0x7c0fd6b8
> There goes a fourth mmap address, but the truly interesting thing is 
> that the buffer size also changes, and no longer matches the 
> previously reported size of 22050 bytes. The test then goes and plays 
> a 5-second sound with the (now incorrect) buffer size of 22050 bytes, 
> not noting that the reported position is wrapping around at 15052 bytes:
> ds3d.c:431:    Playing 5 second 440Hz tone at 11025x16x2
> ...
> trace:dsound:DSOUND_PrimaryGetPosition (0x7fe03ab8,0x7fa6fa80,(nil))
> trace:wave:IDsDriverBufferImpl_GetPosition hw_ptr=0x00000000, 
> playpos=0, writepos=-1, mmap_buflen_bytes=15052
> trace:dsound:DSOUND_PrimaryGetPosition playpos = 0, writepos = 0 
> (0x7fe03ab8, time=1913)
> trace:dsound:PrimaryBufferImpl_GetCurrentPosition playpos = 0, 
> writepos = 0 (0x7fe03ab8, time=1913)
> ds3d.c:230:buf size=22050 last_play_pos=0 play_pos=0 played=0 / 
> 220500, fraction_played=0
> ds3d.c:248:offset=15052 free=6998 written=15052 / 220500
> ...
> ds3d.c:230:buf size=22050 last_play_pos=10296 play_pos=11700 
> played=11700 / 220500, fraction_played=1404
> ds3d.c:248:offset=10296 free=1404 written=32346 / 220500
> ds3d.c:230:buf size=22050 last_play_pos=11700 play_pos=13104 
> played=13104 / 220500, fraction_played=1404
> ds3d.c:248:offset=11700 free=1404 written=33750 / 220500
> ds3d.c:230:buf size=22050 last_play_pos=13104 play_pos=14508 
> played=14508 / 220500, fraction_played=1404
> ds3d.c:248:offset=13104 free=1404 written=35154 / 220500
> ds3d.c:230:buf size=22050 last_play_pos=14508 play_pos=860 
> played=22910 / 220500, fraction_played=8402
> ds3d.c:248:offset=14508 free=8402 written=36558 / 220500
> Please note that the play_pos wrapped from 14508 to 860 because it 
> exceeded 15052 bytes, but the test assumes it wrapped around at 22050 
> bytes, so it miscalculates the fraction_played, advancing it at an 
> abnormally fast rate. That is how the following result ensues:
> trace:dsound:DSOUND_PrimaryGetPosition playpos = 176, writepos = 0 
> (0x7fe03ab8, time=5366)
> trace:dsound:PrimaryBufferImpl_GetCurrentPosition playpos = 176, 
> writepos = 0 (0x7fe03ab8, time=5366)
> ds3d.c:230:buf size=22050 last_play_pos=13824 play_pos=176 
> played=220676 / 220500, fraction_played=8402
> ds3d.c:237:all the samples have been played, stopping...
> ds3d.c:279:stopping playback
> trace:dsound:PrimaryBufferImpl_Stop (0x7fe143b8)
> ds3d.c:628: Test failed: The sound played for 3453 ms instead of 5000 ms
> Many other tests with formats other than U8, 11025Hz fail for the same 
> reason. Any other DirectSound application that reuses the buffer size 
> as the test does will fail in the same way (music mixing up and 
> prematurely stopping). However, I am to understand that this test 
> passes on Windows, in all versions.
> Now that I have found the issue, I ask for help in suggesting a proper 
> fix. I think that the ALSA implementation used to have a separate 
> buffer from which samples were copied into the hardware buffer, but 
> this implementation was scrapped for some reason (and I think, without 
> re-running the ALSA tests). So I tried using 
> snd_hw_params_set_buffer_size() - it fails to set the buffer size to 
> the previously reported size. So I am still thinking about this. Any 
> comments or suggestions for fixing this will be greatly appreciated.
> BTW, does the DirectSound API allow the application to access the 
> hardware mmap directly (that is, not just by specifying the buffer to 
> be played)? If not, one possible solution would be to remember the 
> first reported buffer size, and wrap the *reported* position around at 
> that buffer size, even when the ALSA playback uses the real buffer 
> size. However, when I tried to do this (by hardcoding 22050 as a 
> wraparound value, just as a test), Wine promptly crashed, so I need 
> more insight into this.
> Alex Villacís Lasso
Resending because previous attempt probably was rejected due to gigantic 
attachment (my bad).
-------------- next part --------------
A non-text attachment was scrubbed...
Name: wine_trace.gz
Type: application/x-gzip
Size: 39552 bytes
Desc: not available
Url :

More information about the wine-devel mailing list