NonBug: Weapon Sound Clipping in 1.8.1
by Steve Acaster · in Torque Game Engine Advanced · 04/29/2009 (4:06 pm) · 22 replies
It appears the weapon sound clipping issue isn't resolved for 1.8.1. Didn't see any specific mention of it in 1.8.1 during search and not noted in the Known Issues sticky.
Hack/Fix.
Around line 1535 in ShapeImage.ccp comment out the line.
Edit
Edited the title as this isn't a bug.
Hack/Fix.
Around line 1535 in ShapeImage.ccp comment out the line.
SFX_DELETE( image.animSound );
Edit
Edited the title as this isn't a bug.
About the author
One Bloke ... In His Bedroom ... Making Indie Games ...
#2
Mentioned here in 1.7.1
04/29/2009 (4:14 pm)
The onFire state noise being cut-off prematurely when the state moves to reload, if the state timeout is shorter than the sound file (I think that's the cause anyhow). Makes auto-fire sound like a really bad, bassy, "pop-pop-pop". Mentioned here in 1.7.1
#3
04/30/2009 (8:36 am)
Hmm that's something we've got happening too too, logged during our last alpha test so would be really interested to see a proper fix, if not I'll try Steve's hack/fix and hopefully that helps.
#4
I don't believe the "fix" above will work, since the next animation will use the same channel anyway if it has a sound binded to it. But if it works for you, sure! :)
04/30/2009 (8:47 am)
This is really a design issue and not a bug. Tribes II didn't use fire sounds that were longer than the duration of the animation, for example.I don't believe the "fix" above will work, since the next animation will use the same channel anyway if it has a sound binded to it. But if it works for you, sure! :)
#5
04/30/2009 (1:59 pm)
Thanks for the input Stefan, sounds like it might be best to go with the Tribes II approach, will give it some testing to see what occurs if the sfx_delete() is removed though
#6
There are 3 SFX_DELETE()s in Shapeimage.cpp, I just commented out the last one as it seemed more specific to weapons.
04/30/2009 (2:14 pm)
Can't say I've noticed any problems or performance issues since using that hack back in 1.7, but I've not studied the situation indepth.There are 3 SFX_DELETE()s in Shapeimage.cpp, I just commented out the last one as it seemed more specific to weapons.
#7
Here's a small vid to demonstrate. First 2 weapons are standard code, second 2 are hackfix.
Obviously the sniper rifle has a lower rate of fire over the LMG so more of the sound plays. It's the harshness of the SFX_delete which makes it sound bad, as opposed to the channel simply being reused on next fire (at least that's what I think/hope the hackfix does).
04/30/2009 (2:37 pm)
The sound ends when the Fire State ends. (I just checked that).Here's a small vid to demonstrate. First 2 weapons are standard code, second 2 are hackfix.
Obviously the sniper rifle has a lower rate of fire over the LMG so more of the sound plays. It's the harshness of the SFX_delete which makes it sound bad, as opposed to the channel simply being reused on next fire (at least that's what I think/hope the hackfix does).
#8
04/30/2009 (2:49 pm)
What about memory leaking? Notice the EXE RAM footprint growing over playtesting time? That would be the only flaw i can think of possibly existing.
#9
Test:
stock and hack/mod exes. 3 AI firing 20 projectiles every 2 seconds for 5 minutes, approx 9000 audio calls.
hack exe: After 3 minutes FPS begins to drop, after 5 minutes 40% down. As soon as AI stop firing FPS immediately fully recovers.
stock exe: FPS stays constantly high, no drop not even after 10 minutes of shooting.
I had previously thought that the fall in FPS during my hack.exe test was down to the number of particle effects being spawned. I stand corrected.
04/30/2009 (3:50 pm)
Okay I think I have found an issue with my hack. Whilst there is no difference in EXE RAM growing over time, there can is a drop in FPS.Test:
stock and hack/mod exes. 3 AI firing 20 projectiles every 2 seconds for 5 minutes, approx 9000 audio calls.
hack exe: After 3 minutes FPS begins to drop, after 5 minutes 40% down. As soon as AI stop firing FPS immediately fully recovers.
stock exe: FPS stays constantly high, no drop not even after 10 minutes of shooting.
I had previously thought that the fall in FPS during my hack.exe test was down to the number of particle effects being spawned. I stand corrected.
#10
In our case we kept a second channel around for the fire sound, and played the rest of the state sounds in the same channel. That's how Source does it, and if it's good enough for them it's sure as heck good enough for me. :)
04/30/2009 (4:38 pm)
Well, your video doesn't show the problematic case where the fire state is followed by another state that has sound. In your video the states that follow have no sound as far as I can see. In that case you'll still get an abrupt ending. For instance a reload animation that follows a fire animation.In our case we kept a second channel around for the fire sound, and played the rest of the state sounds in the same channel. That's how Source does it, and if it's good enough for them it's sure as heck good enough for me. :)
#11
Another channel, now there's an idea.
04/30/2009 (4:49 pm)
It wasn't another state sound playing that was my issue, just the state change and the abrupt sound ending, which I mis-diagnosed as a bug.Another channel, now there's an idea.
#12
05/03/2009 (6:43 am)
1. Never comment out that SFX delete, or ur game will get memory lake, and that audio ch never will closed. But, I u works your project, and don't wanna rape your sounds, you remove the sound from state machine, and start your fire sound from fire script:serverPlay3D( myfireSound,%obj.getMuzzlePoint(%slot));
#13
05/03/2009 (7:52 am)
That's definatly not the way to go. serverPlay3D is a NetEvent, hence has to travel across the network, is delayed by nature, and takes up bandwidth. It's not what it was designed for.
#14
1) In shapeBase.h find the MountedImage struct and delete these fields:
animLoopingSound seems to be a legacy leftover, since it's set but never referenced anywhere. animSound we'll no longer be using.
2) Add this to MountedImage struct:
3) In shapeImage.cpp, add these methods:
4) Delete all SFX_DELETE calls from shapeImage.cpp
5) In ShapeBase::MountedImage::~MountedImage, add this:
6) In ShapeBase::setImageState, find this line:
and replace it with this:
Then remove this:
7) In ShapeBase::updateImageAnimation, delete this:
and replace it with this:
8) Go through shapeImage.cpp and delete any other references to animSound or animLoopingSound.
That should do it.
What this does is changes the setup so that a MountedImage can have more than one sound playing at any given time, updates all of them each frame, and deletes them when they're done playing. So they don't get cut off, and you don't get any resource leaks.
I may have missed a step or two in the process so if you have any problems implementing, let me know.
Cheers
05/03/2009 (9:44 am)
I finally got around to tackling this, so I'll share what I did.1) In shapeBase.h find the MountedImage struct and delete these fields:
bool animLoopingSound; ///< Are we playing a looping sound? SFXSource* animSound; ///< The current image sound.
animLoopingSound seems to be a legacy leftover, since it's set but never referenced anywhere. animSound we'll no longer be using.
2) Add this to MountedImage struct:
Vector<SFXSource*> mSoundSources; void updateSoundSources( const MatrixF& renderTransform ); void addSoundSource( SFXSource* source );
3) In shapeImage.cpp, add these methods:
void ShapeBase::MountedImage::addSoundSource( SFXSource* source )
{
if (source != NULL)
{
source->play();
mSoundSources.push_back( source );
}
}
void ShapeBase::MountedImage::updateSoundSources( const MatrixF& renderTransform )
{
//iterate through sources. if any of them have stopped playing, delete them.
//otherwise, update the transform
for (Vector<SFXSource*>::iterator i = mSoundSources.begin();
i != mSoundSources.end(); i++)
{
if ((*i)->isStopped())
{
SFX_DELETE( (*i) );
mSoundSources.erase( i );
i--;
}
else
{
(*i)->setTransform( renderTransform );
}
}
}4) Delete all SFX_DELETE calls from shapeImage.cpp
5) In ShapeBase::MountedImage::~MountedImage, add this:
for (Vector<SFXSource*>::iterator i = mSoundSources.begin();
i != mSoundSources.end(); i++)
{
SFX_DELETE( (*i) );
}
mSoundSources.clear();6) In ShapeBase::setImageState, find this line:
image.animSound = SFX->createSource( stateData.sound, &getRenderTransform(), &velocity );
and replace it with this:
image.addSoundSource( SFX->createSource( stateData.sound, &getRenderTransform(), &velocity ) );
Then remove this:
if ( image.animSound )
{
image.animLoopingSound = image.animSound->isLooping();
image.animSound->play();
}7) In ShapeBase::updateImageAnimation, delete this:
image.animSound->setTransform( getRenderTransform() );
and replace it with this:
image.updateSoundSources( getRenderTransform() );
8) Go through shapeImage.cpp and delete any other references to animSound or animLoopingSound.
That should do it.
What this does is changes the setup so that a MountedImage can have more than one sound playing at any given time, updates all of them each frame, and deletes them when they're done playing. So they don't get cut off, and you don't get any resource leaks.
I may have missed a step or two in the process so if you have any problems implementing, let me know.
Cheers
#15
edit: I think I screwed soemthing up.. revert
05/03/2009 (10:24 am)
I'm getting some errors, all in Shapeimage.cpp when I try to compile the file on it's own.Error 1 error C2601: 'ShapeBase::MountedImage::addSoundSource' : local function definitions are illegal c:TorqueTGEA_1_8_1enginesourceT3DshapeImage.cpp 1689 Error 2 error C2601: 'ShapeBase::MountedImage::updateSoundSources' : local function definitions are illegal c:TorqueTGEA_1_8_1enginesourceT3DshapeImage.cpp 1699 Error 3 error C2601: 'ShapeBase::updateImageState' : local function definitions are illegal c:TorqueTGEA_1_8_1enginesourceT3DshapeImage.cpp 1721 Error 4 error C2601: 'ShapeBase::updateImageAnimation' : local function definitions are illegal c:TorqueTGEA_1_8_1enginesourceT3DshapeImage.cpp 1808 Error 5 error C2601: 'ShapeBase::startImageEmitter' : local function definitions are illegal c:TorqueTGEA_1_8_1enginesourceT3DshapeImage.cpp 1858 Error 6 error C2601: 'ShapeBase::getImageLight' : local function definitions are illegal c:TorqueTGEA_1_8_1enginesourceT3DshapeImage.cpp 1892 Error 7 error C2601: 'ShapeBase::registerLights' : local function definitions are illegal c:TorqueTGEA_1_8_1enginesourceT3DshapeImage.cpp 1931 Error 8 error C2601: 'ShapeBase::ejectShellCasing' : local function definitions are illegal c:TorqueTGEA_1_8_1enginesourceT3DshapeImage.cpp 1945
edit: I think I screwed soemthing up.. revert
#16
05/03/2009 (10:37 am)
You must have deleted an extra } somewhere before the addSoundSource method.
#17
Thanks a lot Gerald, you oughta submit this a resource.
05/03/2009 (11:39 am)
Lovely job! Works fine (once I inputed it correctly).Thanks a lot Gerald, you oughta submit this a resource.
#18
05/03/2009 (2:13 pm)
Better yet, is it alright if I put this in TGEA 1.8.x trunk Gerald?
#20
1) In void ShapeBase::resetImageSlot(U32) I replaced
2) In the ShapeBaseImageData datablock I added a maxConcurrentSounds setting, which caps the number of sounds the image can be playing. If you try to add more sounds, it'll just delete the least recently added sound. Setting maxConcurrentSounds to a value <= 0 allows the image to play an infinite number of concurrent sounds.
05/04/2009 (8:03 pm)
Right, this is in TGEA 1.8.x trunk now with a couple of minor tweaks.1) In void ShapeBase::resetImageSlot(U32) I replaced
SFX_DELETE( image.animSound );with
// stop sound
for(Vector<SFXSource*>::iterator i = image.mSoundSources.begin(); i != image.mSoundSources.end(); i++)
{
SFX_DELETE((*i));
}
image.mSoundSources.clear();. Without that we leak if resetImageSlot is called.2) In the ShapeBaseImageData datablock I added a maxConcurrentSounds setting, which caps the number of sounds the image can be playing. If you try to add more sounds, it'll just delete the least recently added sound. Setting maxConcurrentSounds to a value <= 0 allows the image to play an infinite number of concurrent sounds.
Associate Alex Scarborough