http://bugs.winehq.org/show_bug.cgi?id=29585
--- Comment #4 from Andrew Eikum aeikum@codeweavers.com 2012-01-23 10:28:01 CST --- (In reply to comment #2)
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 ?
There's two cases I've found, neither of which match that documentation. When I use the Test Sound button in winecfg (44.1 kHz, 1 channel, 16 bits), it gives me:
bi.fragstotal = 32 bi.fragsize = 2048 bi.bytes = 65536 = 32 * 2048
In Lemmix (7092 Hz, 1 channel, 8 bits), I get:
bi.fragstotal = 32 bi.fragsize = 151 bi.bytes = 4096 = 128 * 32 = 151 * 27.125...
So it seems like a bug related to rate conversion. However, (151/128) != (8000/7092) so it's not obvious where the bug comes from.
- limit the buffer to 4 mmdevapi periods s.t. Stop won't loose much.
- 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.
Of course the trouble here is OSS can't guarantee that behavior: "It's important to understand that this call just sets the size hint. There is no guarantee that the requested size gets used. For example some devices always use fixed buffer size and there is no way to affect this." http://manuals.opensound.com/developer/SNDCTL_DSP_SETFRAGMENT.html
So the trouble remains, how can we limit the data we write to OSS?
- Does OSS4 care about underrun and need a restart like ALSA? If yes, how to
detect it?
I haven't tested this thoroughly, but it seems like OSS behaves like MMDevAPI. That is, it just stops playing when it hits underrun, and resumes when you begin feeding it data again. The documentation on the HALT ioctl command agrees with that implicitly: http://manuals.opensound.com/developer/SNDCTL_DSP_HALT.html
- 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).
I'm actually not sure if OSS shares this issue. Needs more testing.
- Amenable to a blocking design, using poll(fd,period) instead of
CreateTimerQueue;
Looking forward to doing this after 1.4. That will be a very nice improvement, I think.