FreeSL Destroy Remove Sound

koirat

29-06-2009 20:00:20

When i do not need a sound anymore i call.


sound.RemoveSound();
sound.Destroy();


sound is of type FSLSoundObject (SoundEntity to be more specific)

And then after when updating frame
FSLSoundManager.Instance.UpdateSoundObjects();
i got this:


Object reference not set to an instance of an object.

at Mogre.Node.GetWorldTransforms(NativeValue* xform)
at FSLOgreCS.FSLSoundEntity.Update()
at FSLOgreCS.FSLSoundManager.UpdateSoundObjects()


Any solutions ??

smiley80

29-06-2009 20:14:20

FSLSoundManager.Instance.RemoveSound(name);


sound.RemoveSound();
sound.Destroy();

The only thing Destroy does is calling RemoveSound.

koirat

29-06-2009 22:20:26

I think there are some serious mistakes in this wrapper. I have done some repairs, I'm posting it here as a text.
/*commented stuff means what was*/

I see c++ coder in here :P
It is inside FSLSoundManager

public void RemoveSound(string name)
{
FSLSoundObject sound = GetSound(name);
if (sound == null)
return;
else
sound.RemoveSound();
/*
FSLSoundObject sound = GetSound( name );
if ( sound == null)
return;
else
sound = null;
*/
}

public void UpdateSoundObjects()
{
if (!_initSound)
return;
_listener.Update();

for (int i = _soundObjectVector.Count-1; i >= 0; i--)
{
FSLSoundObject sound=_soundObjectVector[i];
if(sound.isDestroyed) //I have added isDestroyed to FSLSoundObject class
_soundObjectVector.RemoveAt(i);
}
/*
foreach (FSLSoundObject sound in _soundObjectVector)
{
sound.Update();
}
*/
}


FSLSoundObject

public bool isDestroyed = false;

public void RemoveSound(){
if (_withSound){
FreeSL.fslFreeSound(_sound,true);
_withSound = false;
}
isDestroyed = true;
}



FSLSoundEntity

public override void Update()
{
/*
FreeSL.fslSoundSetPosition( _sound,
_renderable.WorldPosition.x,
_renderable.WorldPosition.y,
_renderable.WorldPosition.z );
*/
if (isDestroyed == true) return;
Mogre.Matrix4 worldTransform = new Mogre.Matrix4();
unsafe
{
fixed (Mogre.Matrix4.NativeValue* natVal = &(worldTransform.value))
{
_renderable.GetWorldTransforms(natVal);
}
}

Mogre.Vector3 trans = worldTransform.GetTrans();

FreeSL.fslSoundSetPosition(_sound,trans.x,trans.y,trans.z);
}


Summary.
After Calling Destroy or Remove the sound was not removed from the manager list, and during update there was an error if IRenderable object was already destroyed by ogre. I added isDestroyed variable to FSLSOundObject and before updating manager list i remove all sounds with isDestroyed==true. This is a little messy. It will be probably better to add reference to manager inside sound class and do remove and destroy on a manager object. That time we will not need isDestroyed variable.

btw. Is there someone who maintains FreeSL for Mogre ?
Or im free to update it without asking ?

smiley80

29-06-2009 22:48:35

Or:

public void RemoveSound(string name)
{
FSLSoundObject sound = GetSound(name);
if (sound == null)
{
return;
}
else
{
sound.RemoveSound();
_soundObjectVector.Remove(sound);
}
}


and in FSLSoundObject
public void Destroy()
{
FSLSoundManager.Instance.RemoveSound(_name);
}

koirat

30-06-2009 12:06:20

I was thinking about this one, but i do not know if you can create more than one SoundManager so i decided to do with isDestroyed for now.

smiley80

01-07-2009 19:48:15

FSLSoundManager is a singleton, so 'There Can Only Be One'.

koirat

02-07-2009 11:01:48

You are right. I have changed everything to:

FSLSoundObject

private uint _sound;
public uint SoundID
{
get { return _sound; }
}

public void Destroy(){
RemoveSound();
}


public void RemoveSound(){
FSLSoundManager.Instance.RemoveSound(this);
}


FSLSoundManager

public bool RemoveSound(string name)
{
FSLSoundObject sound = GetSound(name);
return RemoveSound(sound);
}

public bool RemoveSound(FSLSoundObject sound)
{
if (sound.HasSound())
FreeSL.fslFreeSound(sound.SoundID, true);
return _soundObjectVector.Remove(sound);
}

public void UpdateSoundObjects()
{
if (!_initSound)
return;
_listener.Update();

foreach (FSLSoundObject sound in _soundObjectVector)
{
sound.Update();
}
}


and removed IsDestroyed
Also i do not set _withSound to false. since you should not to use things you are removing anyway, and i do not want to do this variable public.