0
0

Hello,

I am using FMOD for a small 2D game and I need to perform various tasks involving volume adjustments.
For exemple, some sounds need to be played with a volume proportional to their distance to a certain point.
What I am doing at the moment is
volume = (maxDistance – distance) / maxDistance

But the volume scale does not seems to be linear, though. If I get closer and closer at a constant speed, the sound doesn’t seem to increase linearly.

Also, at some point I need to fade out a sound and I just went with the simple solution that consists in decrementing the volume by a constant value every 100ms.
Again, the fade out doesn’t seem to be linear to me.

So my question is : what is the scale of the volume ? Is it logarythmic ?
How should I calculate the volume in both cases, then ?

• You must to post comments
0
0

Thanks a lot csakanai, I think this is going to be really helpful!

• You must to post comments
0
0

fmod’s volume is linear from 0 to 1, its not logarithmic or anything like that.

• You must to post comments
0
0

Simple, fast code for converting a linear volume (such as a UI slider) to a reasonable exponential volume. Thus, .5 is about 1/2 the perceived volume, volume increases as expected as the slider is moved, etc. Code is straight from my game:

[code:14awzrcc]

inline flt rLerp(flt a,flt lo,flt hi) {
return lo + (hi – lo)*a;
} // rLerp

flt linearToExp(flt linearVol) {
flt ev;
if (linearVol > 0.f) {
linearVol = rLerp(linearVol,.15f,1.f); // Usable range is from lo to hi.
ev = linearVollinearVollinearVollinearVol; // Slightly less non-linear than standard exp()-based linear to dB:
// ev = exp(6.908f
linearVol)/1000.f;
// Checks not needed if input linearVol is clamped from 0..1
if (ev > 1.f) ev = 1.f;
else if (ev < .0001f) ev = 0.f; // Guarantee no denormal floats
} else {
ev = 0.f;
} // if
return ev;
} // linearToExp
[/code:14awzrcc]

• You must to post comments
0
0

Brett, I am quite surprised to hear that the volume follows a linear scale. As I mistrusted my perception, I asked a few people to listen. All of them noticed that the volume increases quite strangely – and definitely not linearly – when they got closer to the sound emiter at constant speed (as explained in my first post).
And even without moving, I peformed a test where the character is right on the sound emiter, and then moved instantly at half the maximum distance. Neither I nor the people I asked perceived the sound as being half as loud as when the character is right on the emiter.

Would it be something I don’t know about sound perception? Does the volume need to follow an exponential scale to be percieved as linear? (as John Schultz suggested if I got his point right)

I am quite confused!

• You must to post comments
0
0

[quote="bob2356":2boizkbe]Would it be something I don’t know about sound perception?[/quote:2boizkbe]

bingo, it’s not linear, and it even depends on frequency and your age 😉

• You must to post comments
0
0

Remember also that the sound won’t start attenuating until you’ve reached the min distance.

• You must to post comments
0
0

I didn’t get your point Adiss… What minimum distance are you talking about? Why should a sound be attenuated when reaching this minimum distance?

What I am trying to do is the closer the character is from a sound emiter, the louder the sound is. There is a maximum distance threshold from which a sound start being played, and thus heard, but no minimum distance…

Anyway, thanks a lot FireStorm and John Schultz! It is working just fine now, thanks to you.

• You must to post comments
0
0

If you set up your sound effects as FMOD_3D and use set3DMinMaxDistance(), set3DAttributes(), set3DListenerAttributes(), the sound will taper, [b:1a9fk44e]non-linearly[/b:1a9fk44e] ([i:1a9fk44e]logrithmically[/i:1a9fk44e]: see the 3D sound tutorial page in FMODEx help) after the sound is farther than the min distance (set with set3DMinMaxDistance()). The code I supplied is useful for setting the volume in the UI, but is not needed for 3D sounds. You could implement your own 3D effects using 2D sound, but hardware 3D filtering is quite good, and is easy to set up and use.

For a 2D game, just set the vertical coordinate to 0, and use the 3D API. Also keep in mind that if you use hardware 3D mixing (should be a user UI option, as hardware 3D support can have issues due to buggy/slow drivers), some sound cards do an excellent job of 3D filtering the sound (Creative X-Fi, for example) so that 3D spatialization is much better than simple volume panning (HRTF filtering on the DSP, see google for more info). Unless you write your own custom HRTF filter for FMOD (possible, but a lot of work), you won’t get high-quality 3D spatialization. With a few simple source changes to use FMOD 3D API calls, you can get fast HW DSP 3D-spatialization support with recent modern sound cards, and decent, fast software panning support for computers without fast/stable 3D DSP hardware.

• You must to post comments
0
0

bob-

Sorry, I guess I didn’t explain myself very well

Okay, so in "real life" sounds attenuate logarithmically as 1/distance. For 3D software, though, there are some physical limitations to how "loud" a signal can get – ie you’re typically limited to a 16-bit dynamic range. In order to simulate a much louder sound without exceeding the range, a "minimum distance" has been introduced. Inside of that minimum distance, the sound will play at the maximum volume (unless you’ve specified otherwise via a Channel::setVolume() or Sound::setDefaults() call, it’ll be 1.0f).

Once you’ve reached the minimum distance, the sound starts to attenuate logarithmically until it reaches the maximum distance. Once it reaches the max distance, the sound stops attenuating and remains playing at whatever volume it’s at, no matter how much farther away you get from it.

So, let’s say that you’ve got a sound with a min distance of 1 and a max distance of 10. If you go 5 meters out from that sound, you won’t be getting a sound that’s been attenuated for 5 meters, you’ll be getting a sound that’s been attenuated for 4 meters (because it didn’t start attenuating until it hit that 1 meter minimum distance mark).

According to the documentation, the default minimum distance is 1.0.

A few useful functions are:
Sound::set3DMinMaxDistance() (and get3DMinMaxDistance())
(also Channel:: of the same function)
Channel::getAudibility() will give you the current attenuated volume.

• You must to post comments
0
0

Hello all!

Thanks for your explanations, but… I’m not so good with the math, and I have now another problem!
I have a jauge rating some character hability, and I want the music to reflect that jauge. What I am doing isthat two music are playing all the time, and I crossfade the two of them according to the jauge. The jauge is ranged from 0 to 1.
Problem is, if I just peform a simple sound1->setVolume(jauge->value); sound2->setVolume(1-jauge->value), the overall perceived volume tends to get lower for mid values (0.5)… It is quite logical as two sounds played at 0.5 aren’t as loud as one of them played at 1.0

I cannot figure out the function to use to get this right, without loosing loudness for mid-values.

I hope I was clear enough!

• You must to post comments
0
0

[quote="bob2356":16s0p805]I cannot figure out the function to use to get this right, without loosing loudness for mid-values.[/quote:16s0p805]

It’s a similar loudness perception problem as your distance attenuation. I normally run my crossfades logarithmically. It’s pretty easy to do if you keep your volume in a decibel scale (since it’s a logarithmic scale) because you can just linearly fade the dB values. Then you just convert from dB to volume before sending it to FMOD.

Keeping things in dB makes a lot of things easier. You can just add dB values together instead of multiplying. Crossfades become linear. Plus most sound designers are used to working in a dB scale.

Volume to dB:
[code:16s0p805]volume = powf(10.0f, dB / 20.0f);[/code:16s0p805]

dB to Volume:
[code:16s0p805]dB = 20.0f * log10f(volume);[/code:16s0p805]

If you want to do a better sounding distance based attenuation, here’s the I3DL2 standard (IASIG I3DL2 http://www.iasig.org/pubs/3dl2v1a.pdf):
[code:16s0p805]volume = DistanceMin / (DistanceMin + RolloffFactor * (Distance – DistanceMin))[/code:16s0p805]
The above code will reduce the volume by half when you double the distance. If you want to increase how far away a sound can be heard, just increase it’s min distance. There is also a rolloff factor that can be used to increase or decrease how quickly the volume attenuates (just set to 1.0 if you don’t want to use it).

Also, you will notice the max distance is not used. It’s normally just used as a clamping value at which point you can either set the volume to zero or stop playing the sound because it’s out of range.

Hope this helps.
-Chris

• You must to post comments
Showing 11 results