What API is being used to play or record audio?


When troubleshooting audio problems it is sometimes interesting to know exactly what audio API the app in question is using.

Sometimes we can just ask the app developer, or look at their code.

Sometimes it is possible to get an educated guess by looking at the list of .dlls that get loaded into the app. But in cases where an app uses multiple audio APIs simultaneously, this doesn't help much.

The old-school technique, if you have a repro sitting in front of you, is to attach a debugger to the app, set a breakpoint or two, resume, and then once a breakpoint hits, dump the stack. But if you don't have a repro sitting in front of you, this is difficult.

Fortunately, Event Tracing for Windows (ETW) has a feature that you can ask for the stack at the time a given event was logged! I've blogged about this before in Tracking down calls to AvSetMmThreadCharacteristics.

Instructions:

  1. Download audio-client-stack.wprp
  2. From an elevated Command Prompt or PowerShell window:
    wpr.exe -start audio-client-stack.wprp
    (run the app and trigger the audio activity)
    wpr.exe -stop some-filename.etl
  3. Open some-filename.etl in Windows Performance Analyzer
  4. Look at System Activity > Generic Events and System Activity > Stacks. Use Trace > Load Symbols to get function names to resolve.

For example, this is the callstack I get for Microsoft.Windows.Audio.Client/AudioClientInitialize when I do echo ^G (that's Ctrl-G) from a PowerShell window:

ntdll.dll!RtlUserThreadStart
kernel32.dll!BaseThreadInitThunk
wdmaud.drv!CWorker::_StaticThreadProc
wdmaud.drv!CWorker::_ThreadProc
wdmaud.drv!`CWaveHandle::Open'::`2'::COpenJob::Work
wdmaud.drv!CWaveOutHandle::_Open
wdmaud.drv!CWaveHandle::_Open
AudioSes.dll!CAudioClient::Initialize
AudioSes.dll!CAudioClientTraceLogger::LogInitialize
ntdll.dll!EtwEventWriteTransfer
ntdll.dll!EtwpEventWriteFull
ntdll.dll!ZwTraceEvent

So in the case of echo ^G I can conclude that the API layer immediately above the Windows Audio Session API (WASAPI) is Windows Multimedia (WinMM)'s Waveform-Audio interface (waveOutOpen), because I happen to know that wdmaud.drv is the module that implements Waveform-Audio.

I can't tell from this stack alone whether there is another audio API above that (say, PlaySound.) I could repeat this process by finding an event that was logged by waveOutOpen and constructing another .wprp to grab the stack on that thread, and so on and so forth.

Comments (1)

  1. Another neat way of doing this is to use the excellent API Monitor: http://www.rohitab.com/apimonitor

    What’s even more impressive when using API Monitor is that it will show you the DirectSound/MME calls as well as the WASAPI calls that these “legacy libraries” are making *internally*. It’s really cool to see the various calls and instantly see in real time how they are actually implemented in terms of WASAPI calls.

Skip to main content