MME USB Device Disconnection can break MME stack

The Virtual Audio Mixer discussions and support...
Post Reply
Vincent Burel
Site Admin
Posts: 2008
Joined: Sun Jan 17, 2010 12:01 pm

MME USB Device Disconnection can break MME stack

Post by Vincent Burel »

Selecting MME USB Audio Devices in Voicemeeter can generate problem if you plan to disconnect/reconnect your device.
in this case it's recommended to use WDM interface instead.


TEST on WIN7 (32 or 64bits) shows that any input device disconnection (used with MME interface) breaks all MME Stack: All devices connected with MME interface will be stopped (recording and playback devices) and any MME functions will become blocking (deadlock)... that's why any further action regarding audio device will freeze Voicemeeter (like opening device menu or shutting down Voicemeeter ... because it will call MME functions and freeze)

[WIN API: waveinStop() or even waveInGetNumDevs() are placed in deallock (call does not return).]

TEST on WIN8.1 (64bits) shows the same behavior.

TEST on WIN10 (64bits) shows the same behavior.

CONCLUSION: do not use MME audio interface with USB audio device (if you plan to remove it while running).
laucomm
Posts: 2
Joined: Fri Jul 02, 2021 3:06 pm

Re: MME USB Device Disconnection can break MME stack

Post by laucomm »

This is actually a bug in VoiceMeeter after all, which seems to be using the waveInProc callback (instead of other means like window messages or events).

The waveInProc callback has harsh restrictions on what Win32 functions are allowed to be called from within the callback.

From the Remarks section:
Applications should not call any system-defined functions from inside a callback function, except for EnterCriticalSection, LeaveCriticalSection, midiOutLongMsg, midiOutShortMsg, OutputDebugString, PostMessage, PostThreadMessage, SetEvent, timeGetSystemTime, timeGetTime, timeKillEvent, and timeSetEvent. Calling other wave functions will cause deadlock.
According to a locally run thread stack trace, VoiceMeeter calls the waveInAddBuffer function directly from within the waveInProc callback, and thereby violates the previously listed restrictions:

Code: Select all

0, ntoskrnl.exe!KeWaitForSingleObject+0x38f0
1, ntoskrnl.exe!KeWaitForSingleObject+0x1787
2, ntoskrnl.exe!KeWaitForSingleObject+0x98f
3, ntoskrnl.exe!IoGetSiloParameters+0xec
4, ntoskrnl.exe!IoCheckLinkShareAccess+0x480
5, ntoskrnl.exe!setjmpex+0x7c48
6, wow64cpu.dll!TurboDispatchJumpAddressEnd+0x544
7, wow64cpu.dll!TurboDispatchJumpAddressEnd+0x421
8, wow64cpu.dll!BTCpuSimulate+0x9
9, wow64.dll!Wow64KiUserCallbackDispatcher+0x4b9
10, wow64.dll!Wow64LdrpInitialize+0x12d
11, ntdll.dll!LdrInitializeThunk+0x479
12, ntdll.dll!LdrInitializeThunk+0x63
13, ntdll.dll!LdrInitializeThunk+0xe
14, ntdll.dll!ZwWaitForAlertByThreadId+0xc (No unwind info)
15, ntdll.dll!RtlDllShutdownInProgress+0x19d (No unwind info)
16, ntdll.dll!RtlEnterCriticalSection+0x1fa (No unwind info)
17, ntdll.dll!RtlEnterCriticalSection+0x49 (No unwind info)
18, winmmbase.dll!mmDrvInstall+0x1ccb (No unwind info)
19, winmmbase.dll!waveInAddBuffer+0x37 (No unwind info)                <-- unsupported outgoing call
20, voicemeeter8.exe+0x374b2 (No unwind info)                          <-- waveInProc entry
21, winmmbase.dll!DriverCallback+0x7b (No unwind info)
22, wdmaud.drv+0x88e4 (No unwind info)
23, wdmaud.drv+0x791e (No unwind info)
24, wdmaud.drv+0x764c (No unwind info)
25, kernel32.dll!BaseThreadInitThunk+0x19 (No unwind info)
26, ntdll.dll!RtlGetAppContainerNamedObjectPath+0x11e (No unwind info)
27, ntdll.dll!RtlGetAppContainerNamedObjectPath+0xee (No unwind info)
You need to readd the buffer (assuming that is what you are doing) from outside of the waveInProc callback (another thread).

If you don't want to deal with these restrictions, just use the window message pipeline.

Also, the current VoiceMeeter bug is not just an issue for USB sound cards. It is an issue on my non-USB sound card (some integrated "Realtek High Definition Audio" device on my Thinkpad x230 Laptop) as well, when disconnecting (and maybe later reconnecting) the audio cable from the speakers/microphone combo jack (3.5 mm).

I have tested the behavior locally with some sample code (which I can provide if needed).
When disconnecting the audio cable from the microphone jack while recording, my sample app will not deadlock when only using the allowed Win32 functions from the waveInProc callback (deferring all not allowed work to another thread).
It will then get the expected MM_WIM_CLOSE send to the callback.
Vincent Burel
Site Admin
Posts: 2008
Joined: Sun Jan 17, 2010 12:01 pm

Re: MME USB Device Disconnection can break MME stack

Post by Vincent Burel »

ok, thanks a lot for this analysis, this is definitively the good way to remove this problem.
we did not think about this before for different reasons...

Anyway, this will be fixed in next coming update.
laucomm
Posts: 2
Joined: Fri Jul 02, 2021 3:06 pm

Re: MME USB Device Disconnection can break MME stack

Post by laucomm »

Anyway, this will be fixed in next coming update.
Awesome! Looking forward to it.
Post Reply