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).