Some basic questions about the 3D mode

I’ve been using FMOD_2D mode, so I’m not familiar with the 3D mode.
I’m trying to convert one of my old projects to 3D mode, and have some questions.

  1. If all the objects don’t move and the listener’s position is fixed at the center position, do I still need to initialize the listener by calling set3DListenerAttributes() with the following values?
FMOD_VECTOR listenerpos  = { 0.0f, 0.0f, 0.0f };
FMOD_VECTOR forward	= { 0.0f, 0.0f, 1.0f };
FMOD_VECTOR up		= { 0.0f, 1.0f, 0.0f };
FMOD_VECTOR vel		= { 0.0f, 0.0f, 0.0f };
  1. How can I set the orientation using set3DAttributes()?
    I have some stereo sound sources, and so I need to set the forward directions for them.

  2. Can FMOD_DSP_PAN_3D_* and FMOD_DSP_OBJECTPAN_3D_* be used together with set3DAttributes()?

  3. Can I keep using FMOD_DSP_TYPE_SFXREVERB instead of the 3D reverb?
    I was using it just for the global background effect.

  4. Will my existing DSPs (PITCHSHIFT, FLANGE, CHORUS, DISTORTION, LIMITER, COMPRESSOR, THREE_EQ) work as before with the 3D reverb without any code modifications?

It won’t hurt, but it won’t make a difference.

Orientation/rotation is calculated from the forward and up unit vectors. If you were to define orientation in terms of pitch and yaw, this would be the way to calculate appropriate forward and up vectors.

forward.x = cos(pitch) * sin(yaw);
forward.y = -sin(pitch);
forward.z = cos(pitch) * cos(yaw);
up.x = sin(pitch) * sin(yaw);
up.y = cos(pitch);
up.z = sin(pitch) * cos(yaw);

Yes, set3DAttributes will tell the spatializer where it is, so you should use set3DAttributes in conjunction with spatializers.

You can still use the reverb DSP, 3D reverb is just for setting a 3D position for the reverb, and automatically attenuating the wet level of the reveb signal based on distance.

All your existing DSPs will work fine.

1 Like

Thank you very much for the detailed answer.
All my doubts were cleared thanks to it, except for the number two.
I asked the question because set3DAttributes() only takes two parameters unlike set3DListenerAttributes().
There’s no way to pass the forward and up vectors, which was my real question.

I want to give a user options to rotate both the camera (which is a listener) and the game characters such as a drummer.

Oh so you are using ChannelControl::set3DAttributes and not Studio::EventInstance::set3DAttributes? If you are using Channels / Core API, you can set orientation using ChannelControl::set3DConeOrientation, and adjust the sound’s directivity using ChannelControl::set3DConeSettings.

1 Like

Thanks for those two functions.
I would never know they existed because those weren’t introduced in both the example file 3d.cpp and White Paper on 3D Sounds at all.
It seems useful in some cases and I may utilize them in the future.
But what I want to achieve by rotating sounds now isn’t the volume attenuation effect.

Let’s say you have a set of drums in front of you.
If we rotate the set 180 degrees, a hi-hat cymbal will be placed on the right instead of the left.
That’s what I want.
But today I realized that just switching from FMOD_2D to FMOD_3D collapses stereo channels into mono. My sound immediately lost all the details.

White Paper said:

Stereo and multi-channel sounds can be 3D!

A stereo sound when played as 3d, will be split into 2 mono voices internally which are separately 3d positionable. Multi-channel sounds are also supported, so an 8 channel sound for example will allocate 8 mono voices internally in FMOD. To rotate the left and right part of the stereo 3d sound in 3D space, use the ChannelControl::set3DSpread function. By default the subchannels position themselves in the same place, therefore sounding ‘mono’.

So I tried the ChannelControl::set3DSpread() with different values but it made no difference at all, even though the function returned FMOD_OK.

  1. Can I preserve the stereo channels when using the FMOD_3D mode?
    At least, it needs to sound the exact same as the FMOD_2D when both the listener and the sound source are in the initial state at the center. And the separate channels should be audible when the listener is close to the sound source.
    I even tried FMOD_3D_HEADRELATIVE as suggested on the White Paper, but it just followed the listener with a mono channel.

  2. How do I rotate the stereo sound sources. (I don’t care about the attenuation here.)

  3. Is what I understood in the below comment correct?

White Paper says:

All 3 settings can be set with System::set3DSettings. Generally the user will not want to set these.

But the example file 3d.cpp uses the function, and multiplies the distance factor value all over the place like below :

...
const float DISTANCEFACTOR = 1.0f;          // Units per meter.  I.e feet would = 3.28.  centimeters would = 100.
...
/*
	Set the distance units. (meters/feet etc).
*/
result = system->set3DSettings(1.0, DISTANCEFACTOR, 1.0f);
...
result = sound1->set3DMinMaxDistance(0.5f * DISTANCEFACTOR, 5000.0f * DISTANCEFACTOR);
...
FMOD_VECTOR pos = { -10.0f * DISTANCEFACTOR, 0.0f, 0.0f };
FMOD_VECTOR vel = {  0.0f, 0.0f, 0.0f };
...
result = channel1->set3DAttributes(&pos, &vel);
...

And this page explains the distancefactor saying “This only affects doppler”.

So I’m confused.
I concluded this way.

  • The distancefactor value set by the System::set3DSettings() is only used to set the “minimum distance” values of new instances automatically.
  • In general, I don’t need to call set3DAttributes() at all, but still, all the position and velocity vectors are needed to be multiplied by the distance factor.
  • If all the objects and listeners in the game are fixed or don’t need any doppler effects, then both calling set3DAttributes() and multiplying by the distance factor aren’t needed.

Am I correct?

I see what you mean now. Can you can try adding a pan DSP to rotate the sound of an FMOD_2D event? eg

system->playSound(sound1, 0, false, &channel);

FMOD::DSP *dsp;
system->createDSPByType(FMOD_DSP_TYPE_PAN, &dsp);

channel->addDSP(0, dsp);
dsp->setParameterFloat(FMOD_DSP_PAN_2D_ROTATION, 180.0f);

You still need to call Channel::set3DAttributes to set a sound’s x,y,z position in space, regardless of whether you are using doppler. You are correct System::set3DSettings is only required if you want finer control over doppler.

1 Like

Oops. Stupid mistake in my question. It was set3DSettings not set3DAttributes.
Thanks for the confirmation about the set3DSettings.

As for set3DAttributes, even when I don’t use doppler,
do I still need to pass position vectors multiplied by the distance factor?

About the FMOD_DSP_TYPE_PAN trick, I’ll try and tell you the result when I get back home,
but I don’t think it will help, because the FMOD_3D sound is mono in the first place as explained above.
To be honest, I can give up on the rotation feature if it’s really hard, but not on the stereo sounds.

Anyway, I’ll come back and let you know soon.

Update:
No difference.
As said earlier, it becomes mono sound, so for now, I would be happy if I can prevent it at least aside from the rotation,
so that players can hear original stereo sounds when they get closer to each sound source.

ChannelControl::set3DSpread() does something to the sound source, but not the way I expected.
For instance, if the sound is located at { -1000.0f, 0.0f, 0.0f }, I can hear it from the left.
If I call set3DSpread and pass the value 180, I hear it from the center.
And with the value 360, from the right.

I’ve been tinkering with the FMOD_3D this weekend and noticed strange behaviors.

I could turn an FMOD_3D sound into a stereo sound by calling ChannelControl::set3DSpread() with the value 180, but there are some catches.

Only certain combinations of x, y, and z of the position vector worked.
I was testing with different values to see if there’s a rule or something but soon gave up for other reasons, which I will explain below.
Anyway, below are some combinations I tested.

{ 0.0f,			0.0f,			0.0f }			: Mono at the center
{ 0.0f,			0.0f,			0.000000001f }	: Stereo at the center
{ 0.0f,			0.0f,			-0.000000001f }	: Mono at the far left
{ -50.0f,		-50.0f,			-50.0f }		: Stereo at the center
{ 50.0f,		50.0f,			50.0f }			: Stereo at the center
{ 0.000000001f,	0.000000001f,	0.000000001f }	: Stereo at the center
{ 0.0f,			0.000000001f,	0.000000001f }	: Stereo at the center
{ 0.0f,			-0.000000001f,	0.000000001f }	: Stereo at the center
{ 0.000000001f,	0.0,			0.000000001f }	: Stereo at the center
{ -0.000000001f,0.0,			0.000000001f }	: Stereo at the center
{ 0.0f,			0.00000001f,	0.000000001f }	: Mono at the center
{ 0.0f,			-0.00000001f,	0.000000001f }	: Mono at the center
{ 0.00000001f,	0.0,			0.000000001f }	: Mono at the center
{ -0.00000001f,	0.0,			0.000000001f }	: Mono at the center
{ -5000.0f,		-5000.0f,		5000.0f }		: Stereo at the center
{ 0.0f,			0.0f,			5000.0f }		: Stereo at the center

I stopped testing because :

  • If a different value is passed to ChannelControl::set3DSpread, then different combinations are needed.

  • After setting the 3D spread thing, the sound doesn’t work as other FMOD_3D sounds anymore. I tried many different positions, but all I got was one of the three types as listed above.
    “Mono at the center, Stereo at the center, and Mono at the far left.”
    I couldn’t locate the sound at the exact position I wanted at all.

  • After adding FMOD_DSP_TYPE_PAN to the channel, it suddenly feels like as if set3DSpread was called with the value 85 or something. I mean, it feels much narrower than 180.

  • Whatever I do with FMOD_DSP_PAN_2D_ROTATION, it didn’t make any difference at all.

Sorry for spamming here.
Let me ask again:

  1. When I don’t use doppler, do I still need to pass position vectors multiplied by the distance factor to set3DAttributes?
  2. Is there any way to locate a stereo sound in a 3D space?