http://bugs.winehq.org/show_bug.cgi?id=28093
Summary: GetCurrentPadding must slowly decrease (MacOS) Product: Wine Version: 1.3.25 Platform: x86 OS/Version: Mac OS X Status: UNCONFIRMED Severity: normal Priority: P2 Component: mmdevapi AssignedTo: wine-bugs@winehq.org ReportedBy: hoehle@users.sourceforge.net
This issue lends itself to an interesting case in a (hypothetical) article about how to fully satisfy the static requirements of an API by the letter yet lose on the dynamic (or timing) aspects of it.
Unsurprisingly, the dynamics are not well covered in MSDN.
It struck me when analysing the log of my render test (attachment #35968 to bug #28047) that it plays ping pong with mmdevapi using two buffers: 20671/22050 and 1379/22050, then waits for almost half a second while GetCurrentPadding yields "buffer full" at 22050 = GetBufferSize = 500ms. 100ms later, it suddenly says "buffer almost empty". Follows another round of ping pong.
Now imagine what happens after Start when an app prefills the buffer with a single GetBuffer(GetBufferSize): winecoreaudio will let it starve with "buffer full" until after that one buffer is returned from MacOS' audio queue, e.g. 500ms later. IOW an underrun and pause is guaranteed every half second.
Perhaps that explains the 0.5s pauses in bug #28027.
Native does not at all behave like this. I've mentioned its 10ms steps a few times. Even a much reduced rate, e.g. buffer duration / 3 would prevent the underruns in Wine.
Unfortunately, fixing this requires a significant rewrite of the mmdevapi->CoreAudio bridge.
Note that this 10ms talk applies only to shared mode. In exclusive mode, Initialize presumably sets the period the user asks for. Only EXCLUSIVE + EVENTCALLBACK is documented to play ping pong with exactly 2 buffers of GetBufferSize.
http://bugs.winehq.org/show_bug.cgi?id=28093
Jörg Höhle hoehle@users.sourceforge.net changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |aeikum@codeweavers.com
http://bugs.winehq.org/show_bug.cgi?id=28093
Jörg Höhle hoehle@users.sourceforge.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Severity|normal |major
--- Comment #1 from Jörg Höhle hoehle@users.sourceforge.net 2011-09-19 03:40:45 CDT --- This is a major design bug that affects many winmm applications.
It explains why winecfg's test sound clicks several times and does not produce the expected sound: underruns occur because winmm plays pong with a single 100ms buffer!
DSound apps seem not affected because they use very small writes w.r.t. GetBufferSize, so several buffers are in use.
Solving this presumably mean the end to the current nice & (too) simple code in winecoreaudio and require managing a buffer like in winealsa and wineoss.
Noteworthy: While winecfg's 44100Hz IMA_ADPCM test sound causes audible underruns, another at 11025Hz does not. This means that the CoreAudio buffer callbacks are invoked early enough for the underrun not to happen in the 11025Hz case, i.e. before the buffer's last sample is played to the speaker. Presumably CoreAudio's resampler introduces sufficient latency and buffering to prevent an audible underrun. Nevertheless, the gap is tiny: my log shows the callback happens within the last 3ms of that 100ms buffer.
http://bugs.winehq.org/show_bug.cgi?id=28093
--- Comment #2 from Jörg Höhle hoehle@users.sourceforge.net 2011-09-19 09:42:05 CDT --- Interim workaround as hinted: Have GetBufferSize >> typical write size.
Wine's winmm:PlaySound and mciwave use 333ms buffers.
Thus calling Initialize with duration 1-2s in WINMM_OpenDevice would be resonable for Wine's internal needs. 2-5 seconds is also the buffering that mciwave is said to be using, so that's not a bad choice. mciwave is data-driven by dwSuggestedBufferSize and I've seen 500ms and even 1s suggestions in .avi files, which Wine's mciavi would use per WAVEHDR. So 2s sounds like a minimum for Initialize.
Alas, the 2s patch does not work without the one to bug #27937.
http://bugs.winehq.org/show_bug.cgi?id=28093
--- Comment #3 from Jörg Höhle hoehle@users.sourceforge.net 2011-09-21 18:21:28 CDT --- An alternative solution path in order to preserve the simplicity and elegance of the current buffer handling with Core Audio is to decouple GetCurrentPadding from the Core Audio callbacks. Instead, padding would be controlled by GetPosition, like some exclusive mode drivers seem to do with some versions of MS-Windows, as my render tests show. (For shared mode, one would still wish to apply deltas of padding by ceiling modulo 10ms period size.) Alas, this requires to fix bug #28039 first.
We'd have something along padding := min(duration, written - position) to accommodate for latency delays > duration
http://bugs.winehq.org/show_bug.cgi?id=28093
Austin English austinenglish@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Target Milestone|--- |1.4.0
--- Comment #4 from Austin English austinenglish@gmail.com 2011-10-09 15:21:38 CDT --- Sound bug => 1.4 milestone.
http://bugs.winehq.org/show_bug.cgi?id=28093
Jörg Höhle hoehle@users.sourceforge.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |RESOLVED Depends on| |28039 Resolution| |FIXED
--- Comment #5 from Jörg Höhle hoehle@users.sourceforge.net 2011-12-17 16:28:14 CST --- Fixed by commit 2da60016affdbc13356aef162e0ff6d70b03d677 GetCurrentPadding is since governed by GetPosition, which is not unlike native behaviour in exclusive mode, as observed in comment #3 and mimics a device with 0 extra latency past the mmdevapi engine.
Applying delta decrements to padding in shared mode shall be the subject of another bug shared with the ALSA and OSS drivers.
Note that GetPadding decreases too fast past underrun, but that's now an issue with GetPosition, bug #28039.
http://bugs.winehq.org/show_bug.cgi?id=28093
Bruno Jesus 00cpxxx@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Fixed by SHA1| |2da60016affdbc13356aef162e0 | |ff6d70b03d677 CC| |00cpxxx@gmail.com
http://bugs.winehq.org/show_bug.cgi?id=28093
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #6 from Alexandre Julliard julliard@winehq.org 2011-12-30 12:55:51 CST --- Closing bugs fixed in 1.3.36.
http://bugs.winehq.org/show_bug.cgi?id=28093
Bug 28093 depends on bug 28039, which changed state.
Bug 28039 Summary: IAudioClock_GetPosition must ignore underruns (MacOS) http://bugs.winehq.org/show_bug.cgi?id=28039
What |Old Value |New Value ---------------------------------------------------------------------------- Status|UNCONFIRMED |RESOLVED Resolution| |FIXED