Implementing I3DL2 sounds with FMOD

Hi everyone!
Lately I’ve been trying to rewrite EAX part of the game sound engine, I’m working on. Code is based on I3DL2 standard and uses EAX effect on top of this base to implement spatial sounds in different environments. There are 2 ways effects are processed in the engine:

  • by setting global reverb for the environment listener is in;
  • by configuring individual sound sources in these environments;

So I decided to handle global reverb by setting SFX Reverb effect (via System::setReverbProperties()) and passing I3DL2 reverb params to it when environment is changed.

Things get complicated with sound sources. Cause EAX allows for wide range of parameters to be set on sources which influences how individual sound is processed by global reverb effect. These are:
Direct, DirectHF, Room, RoomHF, Obstruction, ObstructionLFRatio, Occlusion, OcclusionLFRatio, OcclusionRoomRatio, OcclusionDirectRatio, RoomRolloffFactor.
And this is how I handled part of these parameters to configure individual sound sources:

float room = Snd::ConvertLinearToLog(sourceI3DL2->GetRoomGain());
float wetLevel = Clamp(room, -10000.f, 0.f) / -10000.f;
fmodResult = channelObject->setReverbProperties(0, wetLevel);

float obstruction = Snd::ConvertLinearToLog(sourceI3DL2->GetObstructionHFGain());
obstruction = Clamp(obstruction, -10000.f, 0.f) / -10000.f;

float occlusion = Snd::ConvertLinearToLog(sourceI3DL2->GetOcclusionHFGain());
occlusion = Clamp(occlusion, -10000.f, 0.f) / -10000.f;
float occlusionRoomRatio = 1.5f;
fmodResult = channelObject->set3DOcclusion(occlusion + obstruction, occlusion * occlusionRoomRatio);

And I literarlly have no idea, how to handle the rest of parameters. Problem is I’m not even sure if the way I handle them now has any effect on spatial sounds in game. Cause global reverb I set doesn’t seem to make any difference to how sounds sound in the game. And I’m completely lost at this point. Would be gratful for any help regarding handling effects for individual sounds as well as why global reverb might/might not affect other sounds in game.

Hi,

What you want should be achievable by using System::setReverbProperties to set the properties of a given reverb instance. You’ll want to create an object of the struct FMOD_REVERB_PROPERTIES, use it to define your I3DL2 parameters, and then pass a pointer to it to the function.

If you have any further questions, feel free to ask!

Hi,
Thank you for your reply. That is exactly what I did to set global reverb. Thing was I accidentally set wet level to 0 for some channel objects, which caused reverb not to affect game sounds. But now everything is okay with reverb effect.

I would like to know, how can I set properties of individual sounds like EAX did with its ‘sound sources’. As far as I understand, these properties influenced how global reverb affected each sound individualy. I have no idea, how to set OcclusionLFRatio to FMOD sound for example. I guess, this can be achieved by adding some DSP units to specific channel object. But my understanding of sound manipulation is really bad, so I’m not sure which EAX effects correspond with FMOD ones.

Apologies for the brevity of my previous response, I misread your initial post.

Unfortunately, besides my unfamiliarity with the specifics of EAX, some of these settings don’t have direct analogues in FMOD, so I can’t give you a reference setting for each that will match EAX. That said:

  • Occlusion scales the reverb path and direct path , and can be handled using Channel::set3DOcclusion - FMOD_INIT_CHANNEL_LOWPASS or FMOD_INIT_CHANNEL_DISTANCEFILTER are the relevant system initialization flags to use to enable occlusion.
  • Obstruction exclusively scales the direct path, post-send to the global reverb - to implement this, you would need to modify the DSP connection to the reverb rather than the general volume of the channel.
  • Exclusion exclusively scales the reverb path, which you can set by modifying the wet level using ChannelControl::setReverbProperties.
  • Anything related to HF/LF and air absorption would likely require you to place DSPs in the signal chain to filter frequencies. I don’t have a comparative reference to EAX to offer, but FMOD_INIT_CHANNEL_DISTANCEFILTER automatically handles some filtering, and may accomplish some of what you’re looking for there. Due to the more complex manipulation of the DSP chain and DSP parameters, you may wish to hold off on this until you know for certain that it’s needed.
  • Additionally, Channel::set3DDopplerLevel will allow you to set per-source doppler.

As an aside, if you still find you’re running into issues with reverb properties, you may wish to consult our documentation on converting FMOD reverb parameters to convert from traditional I3DL2 values (which is what FMOD Ex used to use) to an FMOD Studio value.

Thank you a lot for your reply! This would definitely help me to finish my work now.