amerkoleci / Vortice.Windows

.NET bindings for Direct3D12, Direct3D11, WIC, Direct2D1, XInput, XAudio, X3DAudio, DXC, Direct3D9 and DirectInput.
MIT License
992 stars 73 forks source link

X3DAudio Exception #180

Closed h1cks closed 3 years ago

h1cks commented 3 years ago

Running my game, i'm calling CreateSourceVoice which randomly throws an exception each time. I removed my custom parameters but same issue. I've attached the error content from the exception including the HRESULT. If the info isn't enough, may need to give you access to my project as the issue is 100% reproducible.

I may also look at maybe the way i'm handling buffers also, so I may close if I find an issue in my own handling logic, but currently error thrown seems to be unidentified. The issue is occurs sporadically after that, it seems to recover than fail again. The exception swallows the error and the game continues.

Code Sample it crashes in.

               try
                {
                    if (sourcebuffer != null)
                    {
                        _sourceVoice = _parent.CreateSourceVoice(sourcebuffer.WaveFormat, VoiceFlags.None, 5, _callbackDefault);
              //          _sourceVoice = _parent.CreateSourceVoice(sourcebuffer.WaveFormat, VoiceFlags.None);
                    }
                    else
                    {
                        Debug.Assert(true);
                    }
                }
                catch (Exception ex_)
                {
                    var res_ = Result.GetResultFromException(ex_);

                    Debug.Assert(true);
                }
-       ex_ {"HRESULT: [0x88960001], Module: [Unknown], ApiCode: [Unknown/Unknown], Message: Unknown"}  System.Exception {SharpGen.Runtime.SharpGenException}
-       Data    {System.Collections.ListDictionaryInternal} System.Collections.IDictionary {System.Collections.ListDictionaryInternal}
        Count   0   int
        IsFixedSize false   bool
        IsReadOnly  false   bool
        IsSynchronized  false   bool
+       Keys    {System.Collections.ListDictionaryInternal.NodeKeyValueCollection}  System.Collections.ICollection {System.Collections.ListDictionaryInternal.NodeKeyValueCollection}
+       SyncRoot    {System.Collections.ListDictionaryInternal} object {System.Collections.ListDictionaryInternal}
-       Values  {System.Collections.ListDictionaryInternal.NodeKeyValueCollection}  System.Collections.ICollection {System.Collections.ListDictionaryInternal.NodeKeyValueCollection}
-       Non-Public members      
        System.Collections.ICollection.Count    0   int
        System.Collections.ICollection.IsSynchronized   false   bool
+       System.Collections.ICollection.SyncRoot {System.Collections.ListDictionaryInternal} object {System.Collections.ListDictionaryInternal}
        isKeys  false   bool
+       list    {System.Collections.ListDictionaryInternal} System.Collections.ListDictionaryInternal
+       Results View    Expanding the Results View will enumerate the IEnumerable   
+       Non-Public members      
+       Results View    Expanding the Results View will enumerate the IEnumerable   
-       Descriptor  {HRESULT: [0x88960001], Module: [Unknown], ApiCode: [Unknown/Unknown], Message: Unknown}    SharpGen.Runtime.ResultDescriptor
        ApiCode "Unknown"   string
        Code    -2003435519 int
        Description "Unknown"   string
        Module  "Unknown"   string
        NativeApiCode   "Unknown"   string
-       Result  {Result: -2003435519}   SharpGen.Runtime.Result
        Code    -2003435519 int
        Failure true    bool
        Success false   bool
+       Static members      
+       Static members      
        HResult -2003435519 int
        HelpLink    null    string
-       InnerException  null    System.Exception
-       Static members      
-       Non-Public members      
        InnerExceptionPrefix    " ---> "    string
        _COMPlusExceptionCode   -532462766  int
        Message "HRESULT: [0x88960001], Module: [Unknown], ApiCode: [Unknown/Unknown], Message: Unknown"    string
-       ResultCode  {Result: -2003435519}   SharpGen.Runtime.Result
        Code    -2003435519 int
        Failure true    bool
        Success false   bool
+       Static members      
        Source  "SharpGen.Runtime"  string
        StackTrace  "   at SharpGen.Runtime.Result.ThrowFailureException()\r\n   at Vortice.XAudio2.IXAudio2.CreateSourceVoice(IntPtr sourceFormatRef, VoiceFlags flags, Single maxFrequencyRatio, IXAudio2VoiceCallback callbackRef, Nullable`1 sendListRef, Nullable`1 effectChainRef)\r\n   at Vortice.XAudio2.IXAudio2.CreateSourceVoice(WaveFormat sourceFormat, VoiceFlags flags, Single maxFrequencyRatio, IXAudio2VoiceCallback callback, EffectDescriptor[] effectDescriptors)\r\n   at Insane3D.Sound.SoundChannel.SetSourceSample(SoundSourceBuffer sourcebuffer) in D:\\Development\\Pacific Strafe\\Pacific Strafe\\Code\\Core Classes\\Containers\\Sound\\SoundChannel.cs:line 146"   string
+       TargetSite  {Void ThrowFailureException()}  System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}
+       Static members      
+       Non-Public members      
-       res_    {Result: 0} SharpGen.Runtime.Result
        Code    0   int
        Failure false   bool
        Success true    bool
+       Static members      
amerkoleci commented 3 years ago

I've added SoundStream and RiffParser from SharpDX, I've managed to handle sound playing without issues, code bellow:

IXAudio2 xaudio2 = XAudio2Create();
                using (IXAudio2MasteringVoice masteringVoice = xaudio2.CreateMasteringVoice())
                {
                    using (var stream = new SoundStream(File.OpenRead("ergon.wav")))
                    {
                        var waveFormat = stream.Format!;
                        var buffer = new AudioBuffer(stream.ToDataStream());

                        using (var sourceVoice = xaudio2.CreateSourceVoice(waveFormat, true))
                        {
                            sourceVoice.BufferStart += (context) => Console.WriteLine(" => event received: buffer start");
                            sourceVoice.BufferEnd += (context) => Console.WriteLine(" => event received: end of buffer");
                            sourceVoice.SubmitSourceBuffer(buffer, stream.DecodedPacketsInfo);
                            sourceVoice.Start();

                            int count = 0;
                            while (sourceVoice.State.BuffersQueued > 0/* && !IsKeyPressed(ConsoleKey.Escape)*/)
                            {
                                if (count == 50)
                                {
                                    Console.Write(".");
                                    Console.Out.Flush();
                                    count = 0;
                                }
                                Thread.Sleep(10);
                                count++;
                            }

                            sourceVoice.DestroyVoice();
                        }
                    }
                }
h1cks commented 3 years ago

Cheers, I have found the issue, I had some logic around callbacks causing an issue and not releasing the sound channel (my version of wrapper for voice sharing). I realised I didnt have to create a separate IXAudio2VoiceCallback class, I just had to implement the interface into my Sound Channel. I had some weird memory sharing problems, no errors now and all is happy go lucky!

Will close @amerkoleci

h1cks commented 3 years ago

Update, the issue still exists, just less so. The issue is occurring around the time I free and create a voice in quick succession. There maybe a threading issue. The problem is hidden by putting a try/catch around the createvoice code so the problem is hidden.

amerkoleci commented 3 years ago

Well if the problem is not from Vortice.Windows side then I would close the issue?

h1cks commented 3 years ago

I've found the issue, this is related to the sample encoding, playing an MS Extensible Wav Format causes an exception in CreateSourceVoice call. I changed the sound format to PCM Wav and sample worked.

Will close @amerkoleci

h1cks commented 3 years ago

I will test with soundstream and see if the sound will work. If it does then it means my current load method is flawed