I am working on building a simple framework for using sounds generated by FMOD in Godot 4, utilizing the C# wrapper classes around fmod.dll
and fmodstudio.dll
.
I have successfully initialized the Studio System, played sounds imported from .bank
files, set both global and local parameters, and controlled the volume by adjusting the associated bus.
I also wanted to explore FMOD Studio’s capability of setting up listeners and adding sound sources by using a spatializer. While this works fine in the sandbox, I haven’t made much progress when attempting to implement it in code.
The sound plays correctly without the spatializer, but once I add the spatializer, I hear no sound with settings like this:
The maximum distance is set to 40. The test setup is simple: when starting the game test, the objects are about 3.5 meters apart from each other.
If I increase the maximum distance to something extreme, like 1000, I can hear the sound for a short while, but it quickly fades out.
In the setup, the player acts as the listener (using RigidBody3D
to track the player’s position), and I attach the music events to other RigidBody3D
nodes to track their positions.
I update the positions each frame using the following methods:
The listener:
public void UpdateListenerAttributes()
{
if (_listenerRigidBody != null)
{
Vector3 listenerPos = _listenerRigidBody.GlobalTransform.Origin;
Vector3 listenerVel = _listenerRigidBody.LinearVelocity;
FMOD.VECTOR fmodListenerPos = ConvertToFMODCoordinates(listenerPos);
FMOD.VECTOR fmodListenerVel = ConvertToFMODCoordinates(listenerVel);
FMOD.ATTRIBUTES_3D listenerAttributes = new FMOD.ATTRIBUTES_3D()
{
position = fmodListenerPos,
velocity = fmodListenerVel,
forward = new FMOD.VECTOR() { x = 0, y = 0, z = 1 }, // Set based on the forward direction of your listener
up = new FMOD.VECTOR() { x = 0, y = 1, z = 0 } // Set based on the up direction of your listener
};
_studioSystem.setListenerAttributes(0, listenerAttributes);
}
}
The sounds:
public void UpdateSoundSourceAttributes()
{
Vector3 sourcePos = _soundSource.GlobalTransform.Origin;
Vector3 sourceVel = _soundSource.LinearVelocity;
FMOD.VECTOR fmodSourcePos = ConvertToFMODCoordinates(sourcePos);
FMOD.VECTOR fmodSourceVel = ConvertToFMODCoordinates(sourceVel);
// UpdateSoundSourceAttributes the 3D attributes for the event instance
FMOD.ATTRIBUTES_3D attributes = new FMOD.ATTRIBUTES_3D()
{
position = fmodSourcePos,
velocity = fmodSourceVel,
forward = new FMOD.VECTOR() { x = 0, y = 0, z = 1 }, // Example forward vector
up = new FMOD.VECTOR() { x = 0, y = 1, z = 0 } // Example up vector
};
_eventInstance.set3DAttributes(attributes);
}
private FMOD.VECTOR ConvertToFMODCoordinates(Vector3 godotVector)
{
return new FMOD.VECTOR() { x = godotVector.X, y = godotVector.Y, z = -godotVector.Z };
}
I added a check using this method:
public float CalculateDistanceToSoundSource(string soundEventName)
{
// Retrieve the listener's 3D attributes from FMOD
FMOD.ATTRIBUTES_3D listenerAttributes;
_studioSystem.getListenerAttributes(0, out listenerAttributes); // 0 is the listener index
// Retrieve the sound event instance for the provided sound name
if (TryGetSoundEventByNodeName(soundEventName, out SoundEvent soundEvent))
{
FMOD.ATTRIBUTES_3D soundAttributes;
soundEvent.EventInstance.get3DAttributes(out soundAttributes);
// Calculate the distance between the listener and the sound source
float dx = listenerAttributes.position.x - soundAttributes.position.x;
float dy = listenerAttributes.position.y - soundAttributes.position.y;
float dz = listenerAttributes.position.z - soundAttributes.position.z;
return Mathf.Sqrt(dx * dx + dy * dy + dz * dz); // Euclidean distance
}
return -1.0f; // Return -1 if the sound event is not found
}
public override void _Process(double delta)
{
if (_studioSystem.isValid())
{
_studioSystem.update();
UpdateFMOD();
LogMessage($"Distance listener and sound {CalculateDistanceToSoundSource("GameTestIntro")}");
}
}
And it shows that the distance between the listener and the sound source increases. (And when we reach the set max value the sound of course disappears.)
So the system actually works but for some reason I add a little distance with each setting of attributes [the FMOD.ATTRIBUTES_3D attributes] - well it sure looks like that - but I just do not see why I do that. Perhaps I am just to tired
Any help will be greatly appreciated as usual.