Sound fade in/out script?

I’m making very detailed environments for my games, as I’m sure most of you know, and I would like to be able to have certain sound effects in certain locations. This is easy enough to set up, and you may have noticed it a couple times in the last Zark game. However, the way the sounds come on and off instantly is kind of disconcerting and detracts greatly from the realism.

What I’m looking for is a script that would fade in a sound when the player is in a certain location (this could be controlled by Collision or Near sensors) and fade out the sound when the player leaves. I found an old script that did this once, but it was useless because when you start the game, every stinkin’ sound was playing, and they didn’t fade out until after you visited their respective hotspots. The sounds MUST NOT START until the player goes to their origin.

I’ve tried setting up 3d sounds, but they don’t work very well. It seems like depending on the settings, you either hear them constantly or not at all. Also, they must be playing constantly, a drag on the framerate.

A script seems like the best way to go, does anyone know of one?

There is a setGain(gain) function in the sound actuator.
http://www.blender.org/modules/documentation/pydoc_gameengine/PyDoc-Gameengine-2.34/KX_SoundActuator.KX_SoundActuator-class.html#setGain

Maybe this helps

I am having simular issues with sound as well. This script will be useful for combat music that would turn on when an enemy is near. Then it would need to fade out as the original score faded back in when the enemy dies.

It looks good, but I’m not a script writer. I’m not sure how to use it.
A good script would be one that would start playing the sound and fade it in when its associated TRUE sensor fired. When the sensor stopped firing it would fade out the sound and then stop playing it once it was inaudible.

I can probably help, but I have to think about it for a little bit. I’m not very good off the cuff. What you would basically need is an always sensor and the near sensor and then start the gain at 0 and move it to one after so many seconds. If someone can rattle it off, go ahead, otherwise I’ll respond something between a few minutes and few days, week at the top.


import GameLogic
cont = GameLogic.getCurrentController()
owner = cont.getOwner()
near = cont.getSensor("near")
sound = cont.getActuator("act")
if near.isPositive():
	if not owner.isNear:
		owner.isNear = 1
		owner.fadeIn = 1
		owner.time = 0
		GameLogic.addActiveActuator(sound,True)	
	if owner.fadeIn and owner.time < 10:
		sound.setGain((owner.time )/10) 
	elif owner.fadeIn and owner.time > 10:
		owner.fadeIn = 0
else:
	if owner.isNear:
		owner.isNear = 0
		owner.fadeOut = 1
		owner.time = 0
	if owner.fadeOut:		
		if owner.time < 5:
			sound.setGain((10 - 2 * owner.time)/10)
		else:
			sound.setGain(0)
			owner.fadeOut = 0
			owner.fadeIn = 0
			owner.isNear = 0
			GameLogic.addActiveActuator(sound,False)

This script requires a near sensor called near, an always sensor called always
The sound actuator right now is just called act. If you rename it, rename it also in the sound = cont.getActuator(“act”)
The object must have the following properties:
A timer property named time
a bool property named fadeIn (the I in fadeIn is capitalized) set to false
a bool property named isNear (the N is capitalized) set to false
a bool property named fadeOut (the O is capitalized) set to false

I have a blend file but I can’t upload right now. Modem problems and probably Linux, I’m not sure. It’s off again on again with file uploading.

Found code tags. Don’t use the script posted previously without them.

Would it be possible to use a near sensor in lieu of the Always sensor, so that the sound is not playing constantly? That will eat up processing power.

The sound isn’t playing constantly. It’s only added to the GameLogic when the near sensor is activated. If you look at one of the last lines of code where it says GameLogic.addActiveActuator(sound,false), that’s the sound being taken from the game logic actuator list when the near sensor is out of range. The always sensor is needed to dynamically adjust the volume. A near sensor only gives one pulse. So it’s an on or off type sensor.
What is happening is that the script is coming up every pulse and checking 3 booleans that are false except when near sensor is not activated. It is an acceptable resource drain, nearly non-existent in computer terms. Your asking something to dynamically change over time. Unfortunately, an always sensor doesn’t have a property field. If it did it could be turned off and on by the near sensor. Still, depending on how many total sounds are in the scene it shouldn’t make a noticable influence. You should be able to check the influence by taking the sound objects out of the system and watching the frame rate, etc. What I would do is make some sound object planes connected to the script. Put a bunch of them around in the scene and check framerate and profile. If it makes a difference, let me know.

I’ve considered alternatives. The only other one I can think of is to use perhaps 3 or 4 near sensors that would step up the volume as you got closer to the object, and step it back down when you went further away, and finally remove it. The steps might be noticable, I’m not sure. I’m not sure I’d be willing to do it unless there actually was a problem with that script.

If I may butt in, I’ll say that near sensors should be avoided at all costs. They take up more power (in my experience) than other sensors, and when on objects that get Added, Blender instanly crashes. Instead, I’d use some sort of distance formula. Then, you could set up if statements to presicely determine the distances you want without using any sensors.

If, as Toomai says, Near sensors are not a good way to go, I’d like to suggest using collision sensors to trigger the sound instead. I’m not really looking for fake 3D sound simulation, I just want something that fades in a sound when I’m in a location, and then fades it out when I leave. Nothing complicated.

Fireside, I’m sorry I haven’t tried the script yet. I’ve been busy. I hope to try it this afternoon, if not, then definitely tomorrow.

I put about 20 of them in my game scene and didn’t see a slow down. I don’t get frame rate and resource specs on linux, though, so let me know what your results are. That’s the trouble, though. Adding collision sensors, adding near sensors. Everything you do has some effect on resources. There’s no free lunch. All you can do is minimise the draw. Computers are fast and if we couldn’t do things like that, we couldn’t make games. One of these days I’d like to get into the source code and make some changes, though. Like being able to chain the python script after the other controls instead of being one of them would save a lot, or having a property on the always sensor.

Remember to compare it to the same number of near sensors connected to an and controller and a sound actuator.

Hmm. I can see a way of making this script quite a bit more efficient. You only have one always sensor and one timer per scene. A near sensor would send a message or change a property and the always sensor would fill in the sound needed from a list into a single sound actuator. So you would only have one timer, one always sensor, and one sound actuator per scene.

That’s been sitting at the back of my head for days and I couldn’t quite get a fix on it. Now it seems so obvious. Could use an overlay scene or something and then you’d only need one for the entire game. You have to messages then, though, and it’s a little more of a pain than changing properties.

Well, I’ve just set up the script in my game and it seems to work fine just the way it is. Thanks fireside.

You’re welcome. I’ll probably work on it some more eventually just because I like things to be as efficient as possible but it’s hard to say when I’ll get around to it. Glad it worked out.