http://bugs.winehq.org/show_bug.cgi?id=29585
--- Comment #2 from Jörg Höhle hoehle@users.sourceforge.net 2012-01-21 08:36:53 CST --- Well, without an OSS4 machine it's tough for me to suggest anything, but here it goes http://manuals.opensound.com/developer/SNDCTL_DSP_GETOSPACE.html "The maximum amount of data the application can ever write is (fragments-1)*fragsize bytes." Is bi.bytes == (fragments-1)*fragsize initially ?
I suggest to try out the alternate design sketched in bug #28723. Drawback: - GetCurrentPadding does not decreases by period size stepts. That will cause failures with my render tests. BTW do you always use at least WINETEST_DEBUG=2? wineoss doesn't do it now either and nobody complained, so perhaps that's not the most important behaviour to mimic from native.
0. Write from the callback only, not ReleaseBuffer. 1. Switch to non-blocking mode -- even though OSS recommends against it. 2. limit the buffer to 4 mmdevapi periods s.t. Stop won't loose much. 3. Never care about GETOSPACE. Write as much as possible into that max 4 periods space. write() should return a smaller number of bytes written than submitted, or EAGAIN. Work with that. 4. Have GetCurrentPadding (GCP) ignore what's in the OSS buffer and report only frames in the mmdevapi buffer.
5. Any issues with GetPosition? 6. Does OSS4 care about underrun and need a restart like ALSA? If yes, how to detect it? 7. Presumably OSS will need trailing silence like ALSA in order to play the last few frames. I've no solution to that yet (that's an area where GETOSPACE would be useful). 8. Ideally, manage to start OSS only when THRESHHOLD = one oss period whatever that is + one mmdevapi period + a little safety like 5ms frames have been written.
Later improvements to the design would be to reduce latency by having GCP take into account a fraction of what's in the OSS buffer (more precisely, only if there's more than THRESHOLD in the OSS buffer) -- but that requires a working GETOSPACE.
The final improvement is to have GCP virtually decrement by mmdevapi steps, taking into account corner cases like the mmdevapi buffer filling up but not being a multiple of the period size. That's what I want for winealsa.
Advantages of the design: - Decouple latency from OSS/ALSA buffer size; - Amenable to a blocking design, using poll(fd,period) instead of CreateTimerQueue; - Decouple OSS/ALSA period from mmdevapi one; - Designed to support the Rage/XAudio2 worst-case low-latency scenario (given point 8.) -- as long as Linux' scheduler doesn't delay our or the app's audio thread for too long, since we can't tell it "this is a Pro Audio high priority task".