Recover audio mixer after XAUDIO2_E_DEVICE_INVALIDATED error

I’m experiencing a random XAUDIO2_E_DEVICE_INVALIDATED error with Scream audio device driver on Windows 10.
It does not reproduce 100% but rather happens randomly (though quite often). The LogAudioMixer log excerpts can be found at the end of this message (games launched with -logcmds="LogAudio all, LogAudioMixer all, LogAudioConcurrency all, LogAudioDebug all, LogAudioMixerDebug all, JourneeLog all" -ExecCmds="au.UseThreadedDeviceSwap 0; au.EnableDetailedWindowsDeviceLogging 1;" CMD args).

What I don’t understand is:

  • I don’t disable/re-enable the Scream device manually; for some reason it happens automatically at some point, during the runtime or shortly after startup, so I’m not sure why OnSessionDisconnected notification is received from FWindowsMMNotificationClient;
  • I can see that once mixer gets into failed state due to the XAUDIO2_E_DEVICE_INVALIDATED error, there really is no programmatic way to force it out of it – the mixer will switch to running on null device; the broken state can be fixed, if i go to Windows sound settings and disable/enable Scream device, but this manual solution doesn’t work for me (the -Unattended switch is on, as well as PixelStreamingPort and PixelStreamingIp).

I am wondering:

  1. How one can reliably detect whether the mixer is using Null device? I tried iterating thorugh devices in device manager, but all the output stays the same after error, because internally, audio mixer does not update device info variable when this error happens. Here’s the inspecting code I tried which always returns same output no matter whether instance is broken or not:
auto aDevMgr = FAudioDeviceManager::Get();

if (aDevMgr)
{
    auto aDevs = aDevMgr->GetAudioDevices();

    if (aDevs.Num())
    {
        int audioSubsystemIdx = 0;
        for (auto& audioSubsystem : aDevs)
        {
            UE_LOG(LogTemp, Log, TEXT("%d dev id %u, mixer %d, non-realtime %d, is main %d"),
                audioSubsystemIdx++ ,
                audioSubsystem->DeviceID,
                audioSubsystem->IsAudioMixerEnabled(),
                audioSubsystem->IsNonRealtime(),
                audioSubsystem->IsMainAudioDevice());
        }
    }
    else
    {
        UE_LOG(LogTemp, Log, TEXT("No Audio Devices available"));
    }

    auto audioMixer = aDevMgr->GetAudioMixerDeviceFromWorldContext(GetWorld());
    if (audioMixer)
    {
        UE_LOG(LogTemp, Log, TEXT("world mixer dev id %d is main %d hardware initialized %d, device %s, device id %s, system default %d, sample rate %d, num channels %d"),
            audioMixer->DeviceID,
            audioMixer->IsMainAudioMixer(),
            audioMixer->bIsAudioDeviceHardwareInitialized,
            *audioMixer->GetPlatformDeviceInfo().Name,
            *audioMixer->GetPlatformDeviceInfo().DeviceId,
            audioMixer->GetPlatformDeviceInfo().bIsSystemDefault,
            audioMixer->GetPlatformDeviceInfo().SampleRate,
            audioMixer->GetPlatformDeviceInfo().NumChannels);
    }
}
  1. How one can reliably detect this error? I had to use UAudioDeviceNotificationSubsystem delegates for device switches, but none of these detect failures.
  2. How one can force mixer to try again to acquire default system device and re-create Mastering and Source voice?

Working instance logs:

[2023.02.23-12.25.51:124][  0]LogAudioMixer: Display: Audio Mixer Platform Settings:
[2023.02.23-12.25.51:125][  0]LogAudioMixer: Display: 	Sample Rate:						  48000
[2023.02.23-12.25.51:125][  0]LogAudioMixer: Display: 	Callback Buffer Frame Size Requested: 1024
[2023.02.23-12.25.51:125][  0]LogAudioMixer: Display: 	Callback Buffer Frame Size To Use:	  1024
[2023.02.23-12.25.51:125][  0]LogAudioMixer: Display: 	Number of buffers to queue:			  1
[2023.02.23-12.25.51:125][  0]LogAudioMixer: Display: 	Max Channels (voices):				  0
[2023.02.23-12.25.51:125][  0]LogAudioMixer: Display: 	Number of Async Source Workers:		  4
[2023.02.23-12.25.51:326][  0]LogAudioMixer: Display: Initializing audio mixer using platform API: 'XAudio2'
[2023.02.23-12.25.51:351][  0]LogAudioMixer: Verbose: FWindowsMMNotificationClient: Registering for sessions events for 'Speakers (Scream (WDM))'
[2023.02.23-12.25.51:354][  0]LogAudioMixer: Verbose: FWindowsMMDeviceCache: Render Device '{0.0.0.00000000}.{722ce526-a11a-434c-859c-62ce48238e47}' ID='Speakers (Scream (WDM))'
[2023.02.23-12.25.51:354][  0]LogAudioMixer: Verbose: FWindowsMMDeviceCache: Default Render Role='Console', Device='Speakers (Scream (WDM))'
[2023.02.23-12.25.51:354][  0]LogAudioMixer: Verbose: FWindowsMMDeviceCache: Default Render Role='Multimedia', Device='Speakers (Scream (WDM))'
[2023.02.23-12.25.51:355][  0]LogAudioMixer: Verbose: FWindowsMMDeviceCache: Default Render Role='Communications', Device='Speakers (Scream (WDM))'
[2023.02.23-12.25.51:650][  0]LogAudioMixer: Display: Using Audio Hardware Device Speakers (Scream (WDM))
[2023.02.23-12.25.51:663][  0]LogAudioMixer: Display: Initializing Sound Submixes...
[2023.02.23-12.25.51:665][  0]LogAudioMixer: Display: Creating Master Submix 'MasterSubmixDefault'
[2023.02.23-12.25.51:666][  0]LogAudioMixer: Display: Creating Master Submix 'MasterReverbSubmixDefault'
[2023.02.23-12.25.51:679][  0]LogAudioMixer: FMixerPlatformXAudio2::StartAudioStream() called. InstanceID=1
[2023.02.23-12.25.51:681][  0]LogAudioMixer: Display: Output buffers initialized: Frames=1024, Channels=2, Samples=2048, InstanceID=1
[2023.02.23-12.25.51:682][  0]LogAudioMixer: Display: Starting AudioMixerPlatformInterface::RunInternal(), InstanceID=1
[2023.02.23-12.25.51:682][  0]LogAudioMixer: Display: FMixerPlatformXAudio2::SubmitBuffer() called for the first time. InstanceID=1
[2023.02.23-12.25.53:816][  0]LogAudioMixer: Verbose: No commands were queued while flushing the source manager.
[2023.02.23-12.26.03:497][131]LogAudioMixer: Verbose: Session Disconnect: Reason=DisconnectReasonSessionDisconnected, DeviceBound=Speakers (Scream (WDM)), HasDisconnectSessionHappened=0
[2023.02.23-12.26.03:497][131]LogAudioMixer: Verbose: Attempt to swap audio render device to new device: '[System Default]', because: 'FMixerPlatformXAudio2::OnSessionDisconnect() - Other', force=1, InstanceID=1
[2023.02.23-12.26.03:506][132]LogAudioMixer: Resetting audio stream to device id '[System Default]'
[2023.02.23-12.26.03:598][132]LogAudioMixer: Display: XAudio2 CreateMasterVoice Channels=2 SampleRate=48000 DeviceId={0.0.0.00000000}.{722ce526-a11a-434c-859c-62ce48238e47} Name=Speakers (Scream (WDM))
[2023.02.23-12.26.03:598][132]LogAudioMixer: Verbose: Flush succeeded in the source manager command queue (1).
[2023.02.23-12.26.03:598][132]LogAudioMixer: Verbose: Flush succeeded the source manager command queue (2).
[2023.02.23-12.26.03:598][132]LogAudioMixer: Display: Output buffers initialized: Frames=1024, Channels=2, Samples=2048, InstanceID=1
[2023.02.23-12.26.03:598][132]LogAudioMixer: Display: Starting AudioMixerPlatformInterface::RunInternal(), InstanceID=1
[2023.02.23-12.26.03:976][150]LogAudioMixer: Verbose: Session Disconnect: Reason=DisconnectReasonSessionDisconnected, DeviceBound=Speakers (Scream (WDM)), HasDisconnectSessionHappened=1
[2023.02.23-12.26.04:592][179]LogAudioMixer: Verbose: OnPropertyValueChanged: Speakers (Scream (WDM)) : {9855C4CD-DF8C-449C-A181-8191B68BD06C} 0
[2023.02.23-12.26.08:930][398]LogAudioMixer: Verbose: Attempt to swap audio render device to new device: '[System Default]', because: 'AudioMixerPlatformInterface. Timeout waiting for h/w.', force=1, InstanceID=1
[2023.02.23-12.26.08:930][398]LogAudioMixer: Warning: AudioMixerPlatformInterface Timeout [5000ms] waiting for h/w. InstanceID=1
[2023.02.23-12.26.08:944][399]LogAudioMixer: Resetting audio stream to device id '[System Default]'
[2023.02.23-12.26.08:980][399]LogAudioMixer: Display: XAudio2 CreateMasterVoice Channels=2 SampleRate=48000 DeviceId={0.0.0.00000000}.{722ce526-a11a-434c-859c-62ce48238e47} Name=Speakers (Scream (WDM))
[2023.02.23-12.26.08:980][399]LogAudioMixer: Verbose: Flush succeeded in the source manager command queue (1).
[2023.02.23-12.26.08:980][399]LogAudioMixer: Verbose: Flush succeeded the source manager command queue (2).
[2023.02.23-12.26.08:980][399]LogAudioMixer: Display: Output buffers initialized: Frames=1024, Channels=2, Samples=2048, InstanceID=1
[2023.02.23-12.26.08:980][399]LogAudioMixer: Display: Starting AudioMixerPlatformInterface::RunInternal(), InstanceID=1
[2023.02.23-12.26.09:965][447]LogAudioMixer: Verbose: OnPropertyValueChanged: Speakers (Scream (WDM)) : {9855C4CD-DF8C-449C-A181-8191B68BD06C} 0

Broken instance logs:

[2023.02.23-11.19.13:503][  0]LogAudioMixer: Display: Audio Mixer Platform Settings:
[2023.02.23-11.19.13:504][  0]LogAudioMixer: Display: 	Sample Rate:						  48000
[2023.02.23-11.19.13:504][  0]LogAudioMixer: Display: 	Callback Buffer Frame Size Requested: 1024
[2023.02.23-11.19.13:504][  0]LogAudioMixer: Display: 	Callback Buffer Frame Size To Use:	  1024
[2023.02.23-11.19.13:504][  0]LogAudioMixer: Display: 	Number of buffers to queue:			  1
[2023.02.23-11.19.13:504][  0]LogAudioMixer: Display: 	Max Channels (voices):				  0
[2023.02.23-11.19.13:504][  0]LogAudioMixer: Display: 	Number of Async Source Workers:		  4
[2023.02.23-11.19.13:681][  0]LogAudioMixer: Display: Initializing audio mixer using platform API: 'XAudio2'
[2023.02.23-11.19.13:704][  0]LogAudioMixer: Verbose: FWindowsMMNotificationClient: Registering for sessions events for 'Speakers (Scream (WDM))'
[2023.02.23-11.19.13:706][  0]LogAudioMixer: Verbose: FWindowsMMDeviceCache: Render Device '{0.0.0.00000000}.{722ce526-a11a-434c-859c-62ce48238e47}' ID='Speakers (Scream (WDM))'
[2023.02.23-11.19.13:706][  0]LogAudioMixer: Verbose: FWindowsMMDeviceCache: Default Render Role='Console', Device='Speakers (Scream (WDM))'
[2023.02.23-11.19.13:706][  0]LogAudioMixer: Verbose: FWindowsMMDeviceCache: Default Render Role='Multimedia', Device='Speakers (Scream (WDM))'
[2023.02.23-11.19.13:707][  0]LogAudioMixer: Verbose: FWindowsMMDeviceCache: Default Render Role='Communications', Device='Speakers (Scream (WDM))'
[2023.02.23-11.19.13:920][  0]LogAudioMixer: Display: Using Audio Hardware Device Speakers (Scream (WDM))
[2023.02.23-11.19.13:924][  0]LogAudioMixer: Display: Initializing Sound Submixes...
[2023.02.23-11.19.13:926][  0]LogAudioMixer: Display: Creating Master Submix 'MasterSubmixDefault'
[2023.02.23-11.19.13:928][  0]LogAudioMixer: Display: Creating Master Submix 'MasterReverbSubmixDefault'
[2023.02.23-11.19.13:936][  0]LogAudioMixer: FMixerPlatformXAudio2::StartAudioStream() called. InstanceID=1
[2023.02.23-11.19.13:936][  0]LogAudioMixer: Display: Output buffers initialized: Frames=1024, Channels=2, Samples=2048, InstanceID=1
[2023.02.23-11.19.13:937][  0]LogAudioMixer: Display: Starting AudioMixerPlatformInterface::RunInternal(), InstanceID=1
[2023.02.23-11.19.13:937][  0]LogAudioMixer: Display: FMixerPlatformXAudio2::SubmitBuffer() called for the first time. InstanceID=1
[2023.02.23-11.19.15:478][  0]LogAudioMixer: Verbose: No commands were queued while flushing the source manager.
[2023.02.23-11.19.25:813][157]LogAudioMixer: Verbose: Session Disconnect: Reason=DisconnectReasonSessionDisconnected, DeviceBound=Speakers (Scream (WDM)), HasDisconnectSessionHappened=0
[2023.02.23-11.19.25:813][157]LogAudioMixer: Verbose: Attempt to swap audio render device to new device: '[System Default]', because: 'FMixerPlatformXAudio2::OnSessionDisconnect() - Other', force=1, InstanceID=1
[2023.02.23-11.19.25:819][158]LogAudioMixer: Verbose: FMixerPlatformXAudio2::CheckThreadedDeviceSwap() Starting swap to [[System Default]]
[2023.02.23-11.19.25:819][158]LogAudioMixer: Verbose: StartRunningNullDevice() called, InstanceID=1
[2023.02.23-11.19.25:819][158]LogAudioMixer: Display: FMixerNullCallback: Simulating a h/w device callback at [21ms], ThreadID=7452
[2023.02.23-11.19.25:819][158]LogAudioMixer: Verbose: FMixerPlatformXAudio2::CheckThreadedDeviceSwap() - AsyncTask Start. Because=FMixerPlatformXAudio2::OnSessionDisconnect() - Other
[2023.02.23-11.19.26:269][174]LogAudioMixer: Verbose: Session Disconnect: Reason=DisconnectReasonSessionDisconnected, DeviceBound=Speakers (Scream (WDM)), HasDisconnectSessionHappened=1
[2023.02.23-11.19.26:373][178]LogAudioMixer: Error: XAudio2System->CreateMasteringVoice() -> 0x88960004: XAUDIO2_E_DEVICE_INVALIDATED (line: 345) with Args (NumChannels=2, SampleRate=48000, DeviceID={0.0.0.00000000}.{722ce526-a11a-434c-859c-62ce48238e47} Name=Speakers (Scream (WDM)))
[2023.02.23-11.19.27:378][222]LogAudioMixer: Verbose: OnPropertyValueChanged: Speakers (Scream (WDM)) : {9855C4CD-DF8C-449C-A181-8191B68BD06C} 0