Okay,
So I'm trying to clean up dsound before I make it run properly in different scheduling conditions, and I'm having a heck of a time with it; hoping for some advice/thoughts.
First, I encountered two glitches in dsound/mixer.c that appear to be bugs, but I do not understand the code well enough to be sure. The attached diff addresses both.
Case 1: In the first case, in DSOUND_MixOne, we compute a 'probably_valid_to' based on the 'write_pos', which seems quite wrong; I believe the logic should be testing whether or not there is sufficient data in the mixing buffer, not whether or not there is sufficient room in the buffer overall.
Case 2: In DSOUND_PerformMix, I found that on my sound card, I frequently hit cases where 'inq' (afaict, amount mixed but yet to be played) was higher than the computed value of 'maxq' (maximum amount we're supposed to write). At best, the calculations for 'maxq' need to be corrected, and perhaps coupled directly to the code that limits the data. At worst, I suspect the entire block of code could be removed, but I know way too little to be sure.
Then, to my great joy, I found two separate apparent OSS bugs on two different systems. In one, the result of DSP_GETOPTR would temporarily 'go backwards' when doing mmaped transfers; in the other, my laptop would just stop reading data out of an mmapped buffer, for no apparent reason. Questions: 1) Is there a good set of OSS test programs (particularly for mmap) I could/should use to simply validate that my system is rational wrt OSS? 2) Are the performance gains from DMA mmap really worthwhile? I wonder if mmap mode is buggy and if we wouldn't be better off swtiching to a pure 'write' approach.
I'd appreciate any thoughts/feedback/wacks with a clue bat.
Cheers,
Jeremy
tor, 24,.02.2005 kl. 22.56 -0600, skrev Jeremy White:
Case 1: In the first case, in DSOUND_MixOne, we compute a 'probably_valid_to' based on the 'write_pos', which seems quite wrong; I believe the logic should be testing whether or not there is sufficient data in the mixing buffer, not whether or not there is sufficient room in the buffer overall.
The probably_valid_to check is for whether there's likely to be sufficient data in the *source* streaming buffer to warrant filling the destination buffer. If the app has only half-filled the streaming buffer, then it's a better idea to only mix what we know it put there, and mix the rest of the buffer only after the app has written more stuff to the buffer, rather than mix everything we can, including invalid data, then having to backtrack and do a full mix reset when the app overwrites the invalid data with valid data. The existing code should be correct.
Then, to my great joy, I found two separate apparent OSS bugs on two different systems. In one, the result of DSP_GETOPTR would temporarily 'go backwards' when doing mmaped transfers; in the other, my laptop would just stop reading data out of an mmapped buffer, for no apparent reason. Questions: 1) Is there a good set of OSS test programs (particularly for mmap) I could/should use to simply validate that my system is rational wrt OSS? 2) Are the performance gains from DMA mmap really worthwhile? I wonder if mmap mode is buggy and if we wouldn't be better off swtiching to a pure 'write' approach.
In my experience mmap is the only way to get all of good latency, good precision, minimal sound choppage, reduced CPU usage, and reduced Linux scheduler issues. But Cedega's wineoss still have mmap disabled by default since a lot of OSS drivers have bugs. Since ALSA is supposed to be better, mmap is enabled by default for its winealsa.
Ove Kaaven wrote:
tor, 24,.02.2005 kl. 22.56 -0600, skrev Jeremy White:
Case 1: In the first case, in DSOUND_MixOne, we compute a 'probably_valid_to' based on the 'write_pos', which seems quite wrong; I believe the logic should be testing whether or not there is sufficient data in the mixing buffer, not whether or not there is sufficient room in the buffer overall.
The probably_valid_to check is for whether there's likely to be sufficient data in the *source* streaming buffer to warrant filling the destination buffer. If the app has only half-filled the streaming buffer, then it's a better idea to only mix what we know it put there, and mix the rest of the buffer only after the app has written more stuff to the buffer, rather than mix everything we can, including invalid data, then having to backtrack and do a full mix reset when the app overwrites the invalid data with valid data. The existing code should be correct.
Whoops; I think I see the source of the confusion. I meant to say that the computation of 'probably_valid_left' was incorrect (which is what my patch addressed); the use and computation of 'probably_valid_to' is correct afaict.
In fact, I believe my code more properly enforces the use of 'probably_valid_to'.
In other words, afaict, the current code computes the difference between the number of bytes that have been played from the input source stream (buf_writepos) and the end of the data the app has written (probably_valid_to). It then clips the mixing length to that size.
But what it should really be interested is the amount of as yet unmixed data in the source stream buffer, and that would be properly computed by taking the difference of probably_valid_to and dsb->buf_mixpos.
Does that make sense?
Cheers,
Jeremy
man, 28,.02.2005 kl. 11.23 -0600, skrev Jeremy White:
In other words, afaict, the current code computes the difference between the number of bytes that have been played from the input source stream (buf_writepos) and the end of the data the app has written (probably_valid_to). It then clips the mixing length to that size.
But what it should really be interested is the amount of as yet unmixed data in the source stream buffer, and that would be properly computed by taking the difference of probably_valid_to and dsb->buf_mixpos.
It is true that probably_valid_left is the distance between writepos and probably_valid_to, and that this is used to cut off the mixlen. But the original mixlen (before cutting it) is *also* measured from the writepos (in the primary buffer's frame of reference, of course). The value you're apparently after, the amount of as yet unmixed data, is computed from the mixlen shortly after this, by subtracting primary_done (done above the "remaining mixlen" trace). So this should already be taken care of.