iam
iam

Reputation: 1713

IAudioClock thread safety

The documentation on the thread safety of various WASAPI interactions is lacking in clarity. For IAudioClock it does mention that IAudioClient::GetService() and the Release() of the interface obtained from that must be called from the same thread: https://learn.microsoft.com/en-us/windows/win32/api/audioclient/nn-audioclient-iaudioclock

But for IAudioClock::GetPosition() it doesn't say at all whether that needs to ONLY be called within that same thread or if it can be called by any thread?

I can find a footnote of 'Note In Windows 8, the first use of IAudioClient to access the audio device should be on the STA thread. Calls from an MTA thread may result in undefined behavior.' here: https://learn.microsoft.com/en-us/windows/win32/api/audioclient/nn-audioclient-iaudioclient

And this 'When releasing an IAudioRenderClient interface instance, the client must call the interface's Release method from the same thread as the call to IAudioClient::GetService that created the object.' here: https://learn.microsoft.com/en-us/windows/win32/api/audioclient/nn-audioclient-iaudiorenderclient

Further to this the docs also say 'To release the IAudioClient object and free all its associated resources, the client must release all references to any service objects that were created by calling GetService, in addition to calling Release on the IAudioClient interface itself. The client must release a service from the same thread that releases the IAudioClient object.': https://learn.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-getservice

Collectively that implies that IAudioClient::GetService(), IAudioClock::Release() and IAudioRenderClient::Release() must all be called from the same thread.

Also it says 'You should never call any blocking code from your streaming thread. If you do, you will glitch. IAudioClock methods are blocking.' here: https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/2f9ec79b-8cc3-4b75-a041-a2847613947e/synchronizing-audio-input-and-output-with-iaudioclockgetposition?forum=windowspro-audiodevelopment

I'm specifically interested in the use case of calling IAudioClock::GetPosition() in a different thread to the one that is filling buffers via IAudioRenderClient. As IAudioClock::GetPosition() is apparently not reliably fast enough to be called from the same thread that is filling the IAudioRenderClient buffers: https://social.msdn.microsoft.com/Forums/sqlserver/en-US/2f9ec79b-8cc3-4b75-a041-a2847613947e/synchronizing-audio-input-and-output-with-iaudioclockgetposition?forum=windowspro-audiodevelopment

So I am trying to figure out if I can efficiently post a message (Signal an event or IOCP) from a thread that handles IAudioRenderClient::GetBuffer()/ReleaseBuffer() to another thread that can then call IAudioClock::GetPosition(). But I have no idea from the documentation whether that is allowed.

Note this is related to my other more general question here: Efficient sampling of audio render client position

Upvotes: 0

Views: 422

Answers (1)

Vladimir Khmelev
Vladimir Khmelev

Reputation: 1

If you meant to call PostMessage/PostThreadMessage by "efficiently post a message", I do not recommend to do this "from a thread that handles IAudioRenderClient::GetBuffer()/ReleaseBuffer()". From my experience, even if those Post* functions are non-blocking, it seems they still do something inside that blocks execution for some short period and adds unexpected latencies. It is better to use, for example, critical sections, events. If you actually need to call PostMessage to notify application about something, it is better to run additional proxy thread.

Upvotes: 0

Related Questions