I really need your guys help on this one. Shakti and I have both attempted to debug this code and we simpy cannot figure out what is going on.
We keep getting an access violation error when the engine shuts down, but only in debug mode. The engine shuts down fine when in retail builds and you can also re-fire up DirectX and play any game you want. So to me....it seems like my code is ok.
I've attached the code.
The header CQuickCom.h defines SAFE_RELEASE as:
Code:if (COMobject) COMobject->Release();
Forgive the mess - this engine is still a work in progress.
I hope you can see how this system works from the code, but just in case...here is how you use it. No latency is supported in this version of the code...I have a newer version that does. You would set the latency by passing a 2nd param to Create() that specifies the desired latency in ms.
And that's it. Really simple to use.Code://Base DirectMusic object CDXAudio SFX; //Create using 1 pchannel SFX.Create(1); //Sound emitter object CDXSoundEmitter SFXSystem; //Create system using CDXAudio object and its properties SFXSystem.Create(SFX.GetPerformance(),SFC.GetLoader()); //Structure to track sound IDs struct tagTestSounds { DWORD sndHello; DWORD sndTest; }TestSounds; TestSounds.sndHello=SFXSystem.LoadSound(L"Hello.wav"); TestSounds.sndTest=SFXSystem.LoadSound(L"Test.wav"); //Play the sounds as secondary segments //Primary segments will stop all currently playing segments //Secondary segments will be mixed - thus good for sound effects SFXSystem.Play(TestSounds.sndHello,CDX_SECONDARY_SEG); SFXSystem.Play(TestSounds.sndTest,CDX_SECONDARY_SEG);
Now for a description of the classes:
CDXAudio is the base IDirectMusic8 object. It creates the performance, creates the loader, sets the number of pchannels, and sets the latency in ms.
CDXSoundEmitter is an object that emits sounds -> it requires a CDXAudio object, an IDirectMusicPerformance8 object, and an IDirectMusicLoader8 object.
CDXSoundEmitter has a vector of CDXSoundSegments.
CDXSoundSegment encapsulates one complete IDirectMusicSoundSegment8 along with segment state information. Sound segments are added to the vector by calling LoadSound() which in turn calls IDirectMusicLoader8::LoadSound which actually creates a valid segment interface pointer. The temporary in this function is suspect. However we have both tested the pointers and the pointers in the temporary and the pointers in the copy DO NOT point to the same memory. They are not the same. So this can't be the problem. Besides if this was the case, SAFE_RELEASE() would figure out that the segment pointer was invalid and would not call Release().
The problem according to the debugger is the destructor in CDXSoundSegment when we try to release SoundSegment and SoundSegState. Now get this.
- Remove SAFE_RELEASE() from the CDXSoundSegment destructor.
- In the CDXSoundEmitter destructor immediately after unload is called, call the Release() function on the segment and the segstate. This works perfect - no errors.
- This is the current state of the code. The commented lines in the CDXSoundSegment destructor are the lines that are causing the error. The new code can be seen in the destructor for CDXSoundEmitter.
Now why would releasing the segment and segstate from outside of the object work, but not work inside of the object? The only thing you are changing is the order in which things happen.
If you call Release() in the destructor here is what happens.
Event:....CDXSoundEmitter is going out of scope.
- CDXSoundEmitter's destructor is called
- The destructor iterates through the vector and calls unload on all the sound segments. According to DXSDK Unload() will work in all cases, even if no data has been downloaded.
- Vector is then emptied, which calls the destructor for each object in the vector.
- When object is deleted by vector code, CDXSoundSegment destructor is called.
- CDXSoundSegment releases the segment and the segstate COM interfaces. ---> MSVC flags access violation error.
If you make the changes I stated earlier to CDXSoundSegment and CDXSoundEmitter, here is what happens.
Event:....CDXSoundEmitter is going out of scope.
- CDXSoundEmitter's destructor is called
- The destructor iterates through the vector and calls unload on all the sound segments. According to DXSDK Unload() will work in all cases, even if no data has been downloaded.
- Iterator code then calls Release() on Segment object inside of CDXSoundSegment
- Iterator code then calls Release() on SegmentState object inside of CDXSoundSegment
- Vector is then emptied, which calls the destructor for each object in the vector.
- When object is deleted by vector code, CDXSoundSegment destructor is called -> no actions are performed.
I'm totally lost as to why the error happens when you release the segment and segstate inside of the destructor for CDXSoundSegment.
Anyone have any ideas as to why this might be happening? Salem, Prelude, --- I'm clueless.
Sorry so long but this system is complex so I posted all the code.
BTW feel free to use this code.