sharpdx / SharpDX

SharpDX GitHub Repository
http://sharpdx.org
MIT License
1.69k stars 639 forks source link

SharpDX 3.0.1 XAudio2 VoiceSendDescriptor holds invalid data #723

Open quasaroq opened 8 years ago

quasaroq commented 8 years ago

Hi, I use this code

m_gameAudioVoice = new SubmixVoice(m_audioEngine);
m_gameAudioVoiceDesc = new VoiceSendDescriptor[] { new VoiceSendDescriptor(m_gameAudioVoice) };

But when I immediately look into m_gameAudioVoiceDesc[0].OutputVoice.VoiceDetails.InputChannelCount it causes exception (VoiceDetails is broken), the same for sourceVoice.SetOutputVoices(m_gameAudioVoiceDesc)

I tried SharpDX 3.0.0 and 3.0.1 both cause exceptions, older versions (2.x) were ok on Windows7. Can somebody, please, help me?

xoofx commented 8 years ago

I guess this was fixed by #710 not pushed yet to a public version but you can grab dlls from the latest build

waltdestler commented 8 years ago

Nope, not fixed by #710; I just tried reproducing and I get a crash when accessing VoiceSendDecriptor.OutputVoice.VoiceDetails (NullReferenceException inside the VoiceDetails getter) that I don't get when accessing the VoiceDetails property of the voice passed into the VoiceSendDescriptor. I'll look into this and see if I can figure out what's going on, since I've gotten familiar with the XAudio2 code lately.

SetOutputVoices is working fine for me, though.

waltdestler commented 8 years ago

Okay, so I found the issue, but I'm not sure what the best way to solve it is.

Here's the implementation of Voice.VoiceDetails:

    public SharpDX.XAudio2.VoiceDetails VoiceDetails
    {
        get
        {
            SharpDX.XAudio2.VoiceDetails __output__; 
            GetVoiceDetails(out __output__);

            // Handle 2.7 version changes here
            if (device.Version == XAudio2Version.Version27)
            {
                __output__.InputSampleRate = __output__.InputChannelCount;
                __output__.InputChannelCount = __output__.ActiveFlags;
                __output__.ActiveFlags = 0;
            }

            return __output__;
        }
    }

The NullReferenceException is because device is null, and device is null because VoiceSendDescriptor.OutputVoice creates its returned Voice object via the constructor that takes an IntPtr, which doesn't set the device field.

    public Voice OutputVoice
    {
        get
        {
            return OutputVoicePointer==IntPtr.Zero?null:new Voice(OutputVoicePointer);
        }
        set
        {
            OutputVoicePointer = value.NativePointer;                
        }
    }
quasaroq commented 8 years ago

Thank you, I added check for null device and it seems to be OK.

if (device != null && device.Version == XAudio2Version.Version27)
waltdestler commented 8 years ago

If that fixes the bug for your particular situation, then great, but it's not really a general fix. With XAudio 2.8+ (Windows 8+), it'd work fine, but with XAudio 2.7 (Windows 7) that code will return incorrect data.