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.