0

I want to efficiently monitor audio playback position. I understand I can use IAudioClock::GetPosition() and that this is a blocking call that can fail, and should not be called from a thread that is decoding or resampling the audio stream.

So I set a waitable timer object with a dedicated thread blocked on it, that then calls IAudioClock::GetPosition() and invokes a callback function to process that. There is the concern of the effect on low power state if the timers frequency is too high, and with a period of 16ms this makes me go from 0-1% to 13% CPU usage.

Now I've noticed that IAudioClient::GetDevicePeriod() gives a value of 3ms for exclusive mode and 10ms for shared mode. As my PC is about 8 years old I assume this is a common situation. Which leads me to believe that as I used an event for wasapi to notify me to fill the audio play buffer, which is maybe guaranteed to happen at the device period intervals? If so the the check on position at that event being signaled should be more than precise enough if I only want a bit better than 16ms precision? I believe human audio/visual sync is good enough at close to 16ms for example.

I also understand how to extrapolate the position due to the coupling with query performance counter specified by IAudioClock::GetPosition() which of course helps.

So the crux of my question is, in a modern PC is the waitable timer object approach overkill? As simply sampling the position on the wasapi fill the buffer event is more than good enough? (But then you are calling a blocking GetPosition() in a situation where you shouldn't!) Or is the latter too unreliable for slightly better than 16ms precision? In which case I would have to suffer the extra CPU usage?

There is some interesting relevant discussion here: https://github.com/kinetiknz/cubeb/issues/324

iam
  • 1,623
  • 1
  • 14
  • 28
  • You can [adjust the period of filling the buffer](https://github.com/microsoft/Windows-classic-samples/blob/1d363ff4bd17d8e20415b92e2ee989d615cc0d91/Samples/Win7Samples/multimedia/audio/RenderSharedEventDriven/WASAPIRenderer.cpp#L104) based on samples per second and device period (default:10ms, minimum: 3ms) to make sure the render device will not run of data. – Rita Han Nov 27 '20 at 07:57
  • In addition to event driven mode, you can [set the system timer to 1ms](https://github.com/microsoft/Windows-classic-samples/blob/1d363ff4bd17d8e20415b92e2ee989d615cc0d91/Samples/Win7Samples/multimedia/audio/RenderExclusiveTimerDriven/WASAPIRenderer.cpp#L416) to make sure that our timer resolution is a multiple of the latency to prevent from starving the renderer. – Rita Han Nov 27 '20 at 07:57
  • I believe using timeBeginPeriod is actually bad practice to suggest. I think yes using the minimum buffer size in shared mode for 10ms is probably the well behaved approach. However you shouldn't call GetPosition() then as it may block! The ideal solution might have been been if wasapi provided the current position when it signals the event. – iam Nov 27 '20 at 09:01
  • At what condition the GetPosition() block for you? – Rita Han Nov 27 '20 at 09:38
  • I believe I read somewhere in the docs that it may be prone to blocking so that you shouldn't specifically call it from a decoding thread. So I assumed it's not a good idea to call it from the thread blocked on the wasapi event? – iam Nov 27 '20 at 10:05
  • Actually it may have been here where I found the info on GetPosition() being potentially slow 'IAudioClock::GetPosition is an RPC call, so it can take a long time - long enough that by the time it returns, you have already glitched' https://social.msdn.microsoft.com/Forums/sqlserver/en-US/2f9ec79b-8cc3-4b75-a041-a2847613947e/synchronizing-audio-input-and-output-with-iaudioclockgetposition?forum=windowspro-audiodevelopment – iam Nov 29 '20 at 09:34
  • 'You should never call any blocking code from your streaming thread. If you do, you will glitch. IAudioClock methods are blocking.' from https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/2f9ec79b-8cc3-4b75-a041-a2847613947e/synchronizing-audio-input-and-output-with-iaudioclockgetposition?forum=windowspro-audiodevelopment – iam Nov 30 '20 at 04:25
  • @RitaHan-MSFT Also 'GetPosition calls go down to the audio driver and involve a switch from user-mode to kernel-mode and back. Doing a lot of GetPosition calls very frequently can slow the system down and induce glitching' here https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/55987ac9-69b5-46e5-9615-141fba07ac9e/the-pu64position-obtained-using-getposition-in-iaudioclock-sometimes-doesnt-correlate-with-time?forum=windowspro-audiodevelopment – iam Nov 30 '20 at 04:33

0 Answers0