Xbox LIVE Indie Games
Sort Discussions: Previous Discussion Next Discussion
Page 1 of 1 (7 posts)

XAudio2 and Remote Desktop Question

Last post 6/19/2017 11:04 PM by Charybdis. 6 replies.
  • 9/4/2012 3:23 PM

    XAudio2 and Remote Desktop Question

    So I'm actually using SlimDX with C# to do my audio in XAudio2, but I figured this was more of a general XAudio2 question.

    Anyway, I've written a sound engine that uses XAudio2. I was told it's not good to have multiple devices and mastering voices, so I changed it to use only one static instance for my whole program. This worked great; however, we recently discovered an issue when playing audio over remote desktop.

    It looks like if you disconnect, then reconnect, a previously created device no longer plays sound. So far as I can tell, no error condition or exception is generated, it just doesn't play the sound any more. This holds true with pretty much everything... if I play sounds using System::Media::SoundPlayer I get the same behaviour. Start a long sound, disocnnect, reconnect, the sound is longer playing.

    So now I have two questions:

    1) Is it a big deal to have multiple XAudio2 devices?
    2) Is there some error condition that gets generated that I might be missing?

    Any help would be appreciated!!

  • 9/4/2012 7:06 PM In reply to

    Re: XAudio2 and Remote Desktop Question

    The mastering voice is like the graphics device; it's the representation of the audio output device such that having more than one of them would be a bit odd. But having multiple IXaudio2 engines is fine (each with its own mastering voice) and is something Microsoft uses in its samples (e.g. the Marble Maze sample: http://code.msdn.microsoft.com/windowsapps/DirectX-Marble-Maze-Game-e4806345 ) to separate game music and sound effects. If it made sense for your game you could create a third engine for voice acting sounds so that you could give players the ability to easily control the volume level of those separately from music and non-dialog sound effects.

    As far as error conditions, it's hard to say what you might be missing without knowing what you have. Do you have engine and voice callbacks ( http://msdn.microsoft.com/en-us/library/ee415745(VS.85).aspx ) and are you implementing the error methods for them in a way that would show you problems? Are you checking the HRESULT of SubmitSourceBuffer ( http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.ixaudio2sourcevoice.ixaudio2sourcevoice.submitsourcebuffer(VS.85).aspx ) to make sure it's not an error ( http://msdn.microsoft.com/en-us/library/ee419234(VS.85).aspx )? And any other HRESULT values that might be returned? (It's been a little while since I've looked at SlimDX so I forget if they give you the HRESULT or convert it to an exception or what).
  • 9/5/2012 7:38 PM In reply to

    Re: XAudio2 and Remote Desktop Question

    Thanks for your response!

    It's not so much that I need to control the volume of difference sounds, per se. My only requirement is that they play and you can hear them. The problem is that they can be created in a remote desktop session and played, but when that session is disconnected, they can no longer be played. This is because the old session created the XAudio2 device. If I create a new device in the next session, the new sound plays fine. Since I currently have no way to tell if the sound is no good (more on this in a second), my only option right now is to create a new XAudio2 device and mastering voice for each sound played. To me this doesn't seem like a good idea, but maybe I'm wrong? Also, even if I do this, if I play a long sound (ie, several minutes), and I disconnect/reconnect during the playback, the sound is no longer audible.

    On the topic of the error checking, it's SlimDX that handles most of this for me. That said, it looks like they do pass back a structure that holds the HRESULT for some things, such as submitting the source buffer. I did check this and in all cases it returns S_OK. I think SlimDX has the engine and voice callbacks you're talking about. I'm digging through their source trying to understand it, but this stuff is quite a bit above my head, but I can kind of see where they set it up, even if I don't fully understand. I checked as many HRESULT values as I've found and so far everything is ok.

    That said, they have an event on their XAudio2 class (which wraps IXAudio2) called CriticalError, which somehow (I'm not 100% sure yet) ties into IXAudio2Engine's OnCriticalError method. Your post led me to this and I discovered that this event will get fired when I disconnect from the remote session. So this is definitely something, but not quite what I'm looking for. I suppose I could try to reinitialize on some interval until I don't get a critical error, but I'm not sure.

    Have you ever encountered this issue? I did some tests with windows audio player and noted similar issues (though their sounds start right away). Is this just something Microsoft doesn't support, maybe?
  • 9/5/2012 7:56 PM In reply to

    Re: XAudio2 and Remote Desktop Question

    Answer
    Reply Quote
    XAudio2 is mostly for low latency sound (i.e. games) so it's not targeted specifically at a Remote Desktop scenario (but that doesn't mean it won't work). MediaFoundation might be a better choice though it'd depend on your specific needs (and I'm honestly not sure how MF handles RD disconnect/reconnect either).

    The CriticalError event is the way to go; it's there for situations where something catastrophic happened. When that triggers, I'd set up a flag with a double-based timer where you add the elapsed time to the double each frame and then retry bringing sound online again every X milliseconds, e.g.

        soundFailureTimerInMilliseconds += elapsedTimeInMilliseconds;
        if (soundFailure && soundFailureTimerInMilliseconds >= 1000.0)
        {
            soundFailureTimerInMilliseconds -= 1000.0;
            // try restarting sound, if successful set soundFailure to false
        }

    For testing purposes, I think plugging/unplugging headphones might trigger a critical error event (it's been a few months since I've had time to work on any XAudio2 code unfortunately). If so, that might be easier for initial testing purposes than doing the remote desktop dance while you're trying to get your restart code working (once it is working then you could switch to testing the remote desktop disconnect/reconnect to verify that your solution works with that too).
  • 9/5/2012 8:08 PM In reply to

    Re: XAudio2 and Remote Desktop Question

    I should point out that this isn't a game, it's a control system application. Our requirement for sound was that it needed to be mixed (many sounds playing simultaneously) and the best solution I could find was DirectX. There was a weird Win32 API call by the name of mciSendString that seemed to do it as well, but managing the sound submitted to it for cleanup was a pain. I haven't heard of this MediaFoundation, though doing some quick Googling shows that this might have worked also, though we'd have needed to create our own managed wrapper for it. Suffice it to say, we landed on DirectX using SlimDX as our managed wrapper. It's not too late to change, of course, and the way I wrote the sound system would allow me to change out what provides playback, but I'd like to hold off on that option. At least for now ;)

    I'm thinking you're right though, CriticalError is what I'm looking for. I can set up a loop to detect an error state, then wait until it can properly reinitialize sounds. I should then be able to reinitialize all my existing sounds and restart playback. It could lead to some weird situations but it might work... at least it gives me a starting point which is a lot more than I had before!

    So thank you for your help in this, it's very much appreciated. I've been switched to another task for now but I will be coming back to this some time in the next month or so. I'll mark your above post as the answer, but I'll also come back here and post an update when I have more information.

    Thanks again!
  • 6/16/2017 10:29 PM In reply to

    Re: XAudio2 and Remote Desktop Question

    So for anybody interested, we have finally implemented this solution (only took 5 years). Trapping CriticalError on XAudio2 was the key. Past that, we set up a background thread to periodically attempt to create a new XAudio2 and MasteringVoice object, performed inside a try/catch block. Once creation succeeded, we allowed sounds to play again.

    One thing we weren't able to do was correctly dispose of the previously existing XAudio2 and MasteringVoice objects (that were present when the CriticalError event was fired). Whenever we tried this the program would hang indefinitely. We figured there might be some deadlock issue inside either the SlimDX, or the XAudio2 code. Ultimately we decided we could accept the relatively small memory leak and just ignore the old objects.

    Anyway, I just wanted to post back for anybody else encountering this issue. This also works for when the Windows Audio service is stopped and restarted... both that case and a Remote Desktop Disconnect will trigger XAudio2::CriticalError.

    Thanks to those involved in this discussion! :)
  • 6/19/2017 11:04 PM In reply to

    Re: XAudio2 and Remote Desktop Question

    XAudio2 CriticalError is indeed a challenging scenario to handle robustly. For Windows 10, the 'default' Windows Core audio device is virtualized which makes this a lot easier to handle.

    See the Remarks on MSDN
Page 1 of 1 (7 posts) Previous Discussion Next Discussion