trinith_006

Members
  • Content count

    11
  • Joined

  • Last visited

Community Reputation

104 Neutral

About trinith_006

  • Rank
    Member
  1. Sounds good, and thanks for pointing out GitHub as well. We'll likely just end up changing our deployment process to accommodate this. Just wanna take the opportunity to say that I appreciate the work you guys did on SlimDX. We only use it for audio but for the most part we haven't had any issues... even this one only showed up when repeatedly creating/destroying a device/mastering voice in an attempt to speed up the diagnosis of another issue. Thank you
  2. Hey, So we use SlimDX to provide audio playback capability for our product and are currently exploring an issue a customer is reporting. While playing around with XAudio2, we discovered an issue where, after disposing of the XAudio2 device, we would get an InvalidOperationException (handle is not initialized) in EngineCallbackShim::OnProcessingPassStart. Since this happens after Dispose has been called on the SlimDX XAudio2 object, the object m_WrappedInterface (in EngineCallbackShim::OnProcessingPassStart) is no longer valid. I did a bunch of digging around and believe I have discovered a fix. I've changed XAudio2's destructor code to... XAudio2::~XAudio2() { if (callback != NULL) { IXAudio2* pointer = static_cast<IXAudio2*>(this->UnknownPointer); if (pointer != NULL) { pointer->UnregisterForCallbacks(callback); } delete callback; callback = NULL; } } By calling UnregisterForCallbacks, it doesn't appear that the issue happens. I will run this over the weekend, and probably a few more times on Monday, to confirm, but I'm thinking this might resolve the issue. Having said that, I've noticed that at SlimDX.org, the last release is the release I took when I first developed the audio engine... January 2012. Are the devs still active? Is there a way to confirm this functionality with the devs and perhaps have this included in an official build? We are able to build our own SlimDX binaries, but we would prefer to continue to use something official :) Anyway, if anybody has any info, that would be awesome!   Thanks, Gary
  3. Hi all, This is more of a feedback/general question than any kind of specific problem... kind of. A while ago I wrote a sound engine with SlimDX. While writing it, it was pointed out to me that I was creating a new XAudio2 device and mastering voice for each sound I was creating and that this probably wasn't the best approach. It was fine to use a single static instance of these and I created a static manager class to initialize and shut down the sound engine, that is, to create and destroy my XAudio2 device and mastering voice. Everything worked great and no problems! Until now that is... through a rather random incident during testing, it turns out that when a remote desktop session is disconnected, after reconnecting sound won't work. I did some digging around and my guess is that the Windows playback device, Remote Audio, goes away when the session closes and a new one is created when the new session connects. I would then have to guess that the XAudio2 device that was created is no longer valid. Unfortunately there appears to be no exception or error to indicate this... as far as SlimDX/XAudio2 is concerned, there are no problems at all. It continues to play sounds, it's just that nothing happens. I created a test application and modified my code so that each sound would create/destroy it's own device and mastering voice. Doing this, sounds created before the session disconnect no longer work; however, sounds created after reconnecting do play correctly. So I have two questions: 1. Is it reasonable to have each sound create/maintain it's own XAudio2 device and mastering voice? The advice I was given, which makes a lot of sense, was that this is wasteful; however, being unable to create sounds after losing the remote session is a bit of a problem for us. 2. Is this something anybody else has encountered? Does anyone have any thoughts on how to overcome this problem? I appreciate any help anyone can give. Thank you!
  4. Cleanup of XAudio2 device.

    Just to update this... I ran out of time and had to go with a work around solution that I'm not entirely happy with, but I guess them's the breaks. I'll try to revisit the problem at a later date and if I make any headway on it, I'll post back here. Thanks for your help though, Mike. I appreciate the comments!
  5. Cleanup of XAudio2 device.

    Hmmm, perhaps... though I'm not sure why disposing of the items would cause the crash to go away. Is SlimDX doing the CoInitialize call for XAudio2 somewhere? I searched through XAudio2.cpp and MasteringVoice.cpp and didn't get any hits. Our main application does have a CoInitialize call (and subsequent CoUninitialize at the end) and exhibits the same behvaiour as the test app, which doesn't have it's own CoInitialize calls. (Also, I should mention, I know very little about these... the bulk of my experience is on the C# end of things but I find myself getting mixed into unmanaged C++ code ) I appreciate the help and if I can get the debug working maybe I'll have a bit more information, which is taking a while to set up. Yay slow networks.
  6. Cleanup of XAudio2 device.

    So a bit of a follow up to this... everything works great in the C# world but unfortunately there appear to be some problems in the unmanaged/managed mixed C++ world. When I run in the application I'm integrating with, I'm getting a crash message that says "string binding is invalid" along with some other dump info. I went back to disposing of my device when the program exits and still got it. Turns out I have to dispose of both the device and the mastering voice, then no crash. I was able to boil this down to a separate project, outside the main application, that can reproduce the issue. Create a C# class library with the following code: [code]using System; using System.Collections.Generic; using System.Text; using SlimDX; using SlimDX.XAudio2; using SlimDX.Multimedia; namespace TestingSlimDX { public class SomeTest { public static XAudio2 device = null; public static MasteringVoice masteringVoice = null; public static void PlayWarning() { device = new XAudio2(); masteringVoice = new MasteringVoice(device); WaveStream waveStream = new WaveStream("c:\\temp\\warn2.wav"); // Whatever sound you want here AudioBuffer buffer = new AudioBuffer(); buffer.AudioData = waveStream; buffer.AudioBytes = (int)waveStream.Length; buffer.Flags = BufferFlags.EndOfStream; SourceVoice sourceVoice = new SourceVoice(device, waveStream.Format); buffer.AudioData.Position = 0; sourceVoice.SubmitSourceBuffer(buffer); sourceVoice.Start(); while (sourceVoice.State.BuffersQueued > 0) ; sourceVoice.Dispose(); buffer.Dispose(); //waveStream.Dispose(); //Console.Write("Disposing of mastering voice... "); //masteringVoice.Dispose(); //Console.WriteLine("Finished."); //Console.WriteLine(); //Console.Write("Disposing of device... "); //device.Dispose(); //Console.WriteLine("Finished."); //Console.WriteLine(); } } }[/code] Build this, then create a new C++ console application. Use the following code: [code]#include <iostream> #include <windows.h> using namespace std; using namespace System; using namespace TestingSlimDX; int StartPoint(void); //#pragma unmanaged //int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int iCmdShow) //{ // int retVal = StartPoint(); // // return retVal; //} #pragma unmanaged int main(void) { int retVal = StartPoint(); return retVal; } #pragma managed int StartPoint(void) { Console::WriteLine("Starting execution of main..."); try { Console::WriteLine("Starting sound playback..."); SomeTest::PlayWarning(); Console::WriteLine("Sound playback complete!"); } catch (Exception^ e) { Console::WriteLine("Exception occurred!" + Environment::NewLine + e->ToString()); } Console::WriteLine("Execution of main complete."); return 0; }[/code] So build the c++ application and run it. For me, I had to run it twice for some strange reason. The first run wouldn't crash, but the second would... then every run after that. If an undetermined period of time passed, it would then succeed on first run again. I have no idea how long that is... it just seems to work like that. The crash also happens after main exits, so I'm not getting any debug information out of this. I'm not sure how our application gets it either. All I get is a windows dialog saying "blahbityblah.exe has stopped working". Now, if I change the C# code so to uncomment the disposes for device and masteringVoice, build it and then rebuild the C++ project to update the dll, no crashes at all. Everything works fine. I've downloaded the SlimDX source and I don't see anything that would be funny... the destructors both do NULL checks before trying to dispose. I'm attempting to get it building on my machine so that I can set some breakpoints and see if I can figure it out that way but I figured I'd also post here to see if anybody else had encountered this and/or had any insights. Thanks!
  7. Cleanup of XAudio2 device.

    Cool, that's what I was thinking too. And the reason is that our scripting allows the use of any .NET assembly. We don't directly control what they are able to use, so there would be no way to stop them from using this functionality. Whether or not that's good, this is the way that functionality got implemented so I'll just have to work around it I guess Thanks for your feedback, much appreciated!
  8. Hey all, So I've got a question about object cleanup. I've created some sound playback functionality using SlimDX for a project I'm working on and it's working great; however I've got one hitch. Right now I'm creating only one, static instance of my XAudio2 device that all my sounds will use to play. This is for the entire application. A while back I was having some problems with this and the advice I got was to only have once device ([url="http://www.gamedev.net/topic/618436-corruption-when-playing-sound-via-memory-stream-xaudio2/"]http://www.gamedev.n...stream-xaudio2/[/url]). This worked out well and to manage it, I created a static class called SoundEngine that would control instantiating and disposing of that XAudio2 object with the startup and shut down of my program so that everything would dispose nicely. Now for the hitch. The product this is integrated with allows scripting and this scripting is allowed access to any DLL. This is intentional and actually fits with the goals I had in mind for this functionality. I want scripts to be able to create and play sounds. However, what I do not want is for the scripts to have access to SoundEngine, as I only want the hosting application to be able to start up and shut down the sound engine (ie, create or dispose of the XAudio2 object). So I ran through a bunch of ideas and the simplest/easiest I could think of was to just not allow the creation/destruction of the XAudio2 object. Just create it at start up and let it get destroyed with all the other objects when the application is turned off. So I've been experimenting with this and now I'm getting the following output... [quote]Object of type SlimDX.XAudio2.XAudio2 was not disposed. Stack trace of object creation: Total of 1 objects still alive.[/quote] ... which makes sense. I've purposely not disposed of the XAudio2 device. So after all that rambling and backstory, my question is this: Is this a problem? I don't intend for my device to ever get destroyed except when the application shuts down, and all my sound objects will properly dispose themselves so, under ideal circumstances, we should never see this message with more than that single object still alive. But I figured it might be a good idea to check and see if anyone had any thoughts on this and if, should any SlimDX developers be watching this forum, whether or not there could be any unintended side effects of this behaviour. Thanks for reading, and thanks for any insight provided [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]
  9. Thanks for the clarification and the link. As I mentioned, I'm brand new to this and haven't used native DirectX, so there is a lot of gaps in my knowledge. Thanks again!
  10. That was exactly the problem! I was expecting it to stick around because you hand it off to the source voice, thus I was expecting a reference to be kept alive and the object to not get disposed. Apparently it does, so making the buffer a member variable and disposing it manually appears to have resolved the issue. Thank you very much!
  11. Hi Mike, I appreciate the response, that's actually not a bad idea and pretty easy to implement. That said, it doesn't seem to be the issue. I changed over the code to use a single device and the same issue is present. I should mention that I'm not locked to SlimDX... if you (or anybody else) has thoughts on alternatives I'm all ears (eyes?). My engine is structured in such a way that I can replace the component that does the actual sound playing fairly easily so I should be able to use any old sound provider. My only requirements are that it can play in a thread and that I can play/stop it (pause is a nice to have but not required). Currently SlimDX using XAudio2 grants me this functionality. I did try SlimDX with DirectSound, but was getting an odd artifact at the end of playback... just a little click sound, so I went with XAudio2. Here's the updated class for you or any others looking at this thread. [code]public class SoundPlayer { private SourceVoice m_sourceVoice = null; public SoundPlayer() { } public void Load(XAudio2 device, string fileName) { WaveStream waveStream = new WaveStream(fileName); AudioBuffer buffer = new AudioBuffer(); buffer.AudioData = waveStream; buffer.AudioBytes = (int)waveStream.Length; buffer.Flags = BufferFlags.EndOfStream; m_sourceVoice = new SourceVoice(device, waveStream.Format); m_sourceVoice.SubmitSourceBuffer(buffer); } public void Load2(XAudio2 device, string fileName) { byte[] fileData = File.ReadAllBytes(fileName); MemoryStream ms = new MemoryStream(fileData); WaveStream waveStream = new WaveStream(ms); AudioBuffer buffer = new AudioBuffer(); buffer.AudioData = waveStream; buffer.AudioBytes = (int)waveStream.Length; buffer.Flags = BufferFlags.EndOfStream; m_sourceVoice = new SourceVoice(device, waveStream.Format); m_sourceVoice.SubmitSourceBuffer(buffer); } public void Play() { Thread t = new Thread(PlayMethod); t.Start(); } private void PlayMethod() { m_sourceVoice.Start(); while (m_sourceVoice.State.BuffersQueued > 0) { Thread.Sleep(10); } m_sourceVoice.Dispose(); } }[/code] Then using it... [code]public class TestHarness { private XAudio2 m_device = new XAudio2(); public TestHarness() { MasteringVoice masteringVoice = new MasteringVoice(m_device); } public void RunTest() { SoundPlayer p1 = new SoundPlayer(); SoundPlayer p2 = new SoundPlayer(); SoundPlayer p3 = new SoundPlayer(); p1.Load2(m_device, @"..\..\klaxon2.wav"); p2.Load2(m_device, @"..\..\klaxon2.wav"); p3.Load2(m_device, @"..\..\warn2.wav"); p1.Play(); //p2.Play(); //p3.Play(); } }[/code]
  12. Hi all, I'm making my first foray into a sound engine and I'm using SlimDX in order to allow me access to DirectX in C#. I dug around and found a couple of tutorials which got me started and when playing a file from a file, everything is fine. However I also want to look at playing a file from a memory stream (loaded with the contents of a file, stored in a byte array) as I don't want to have to access the hard drive for playing sounds in quick succession. In doing so I appear to have stumbled across an issue with sound corruption. I'm able to reproduce it 100% of the time on both my home machine and my work machine (both Windows 7) but it only happens with certain files and in a certain order. In this particular case, see the attached file, sounds.zip which contains two files, klaxon2.wav (sounds like the red alert sound from star trek) and warn2.wav (the word warning repeated three times). The easiest way to describe the issue is to demonstrate the code I'm using to load and play, and the test procedure. I've boiled down the code from my main project to a fairly simple test class: [code]public class SoundPlayer { private XAudio2 m_device = new XAudio2(); private SourceVoice m_sourceVoice = null; public SoundPlayer() { MasteringVoice masteringVoice = new MasteringVoice(m_device); } public void Load(string fileName) { WaveStream waveStream = new WaveStream(fileName); AudioBuffer buffer = new AudioBuffer(); buffer.AudioData = waveStream; buffer.AudioBytes = (int)waveStream.Length; buffer.Flags = BufferFlags.EndOfStream; m_sourceVoice = new SourceVoice(m_device, waveStream.Format); m_sourceVoice.SubmitSourceBuffer(buffer); } public void Load2(string fileName) { byte[] fileData = File.ReadAllBytes(fileName); MemoryStream ms = new MemoryStream(fileData); WaveStream waveStream = new WaveStream(ms); AudioBuffer buffer = new AudioBuffer(); buffer.AudioData = waveStream; buffer.AudioBytes = (int)waveStream.Length; buffer.Flags = BufferFlags.EndOfStream; m_sourceVoice = new SourceVoice(m_device, waveStream.Format); m_sourceVoice.SubmitSourceBuffer(buffer); } public void Play() { Thread t = new Thread(PlayMethod); t.Start(); } private void PlayMethod() { m_sourceVoice.Start(); while (m_sourceVoice.State.BuffersQueued > 0) { Thread.Sleep(10); } m_sourceVoice.Dispose(); m_device.Dispose(); } }[/code] So the idea is load the sound clip into a class and call play. It will play itself in a thread and finish. Please keep in mind that this is a very bare bones example from what's in my main project. Things like proper thread management and object clean-up were not a priority, just reproducing the issue in order to post it here for help (though I'm certainly open to pointers and advice... first timer with sounds after all). Anyway, stick this class in a project somewhere and, using the attached sounds, use the following code to run it: [code]SoundPlayer p1 = new SoundPlayer(); SoundPlayer p2 = new SoundPlayer(); SoundPlayer p3 = new SoundPlayer(); p1.Load2(@"..\..\klaxon2.wav"); p2.Load2(@"..\..\klaxon2.wav"); p3.Load2(@"..\..\warn2.wav"); p1.Play();[/code] (NOTE: Replace the path with whatever directory you unzipped the files in.) What seems to happen is that when p1 is played, it plays a slowed down version of warn2 until warn2 is finished, then plays the rest of klaxon2 until klaxon2 is finished. If I were to use the Load method instead of Load2, it would work fine. If I were to not load two copies of klaxon2, it would work fine. If I were to load two copies of klaxon2 but no warn2, it would work fine. In my tests I've found a few other examples of the problem but for the most part, it's an issue that's hard to reproduce. When you do find a way to reproduce it you can always reproduce it. If that makes any sense... bleh. As you can see, the way in which I'm loading the stream isn't terribly complex, so I'm not sure what I could be doing wrong. The file data is copied out of the file and put into a new memory stream every time so there shouldn't be any corruption. Can anybody see anything wrong with what I'm doing? Note that I'm certainly not set on this method of playback either... if there was an alternative, I'm interested. I'm also curious as to whether or not it's possible there is an issue with SlimDX, and how one might go about reporting the issue if this is the case. Again, any help is appreciated as this one has me banging my head on the keyboard. Thank you!!