Lowering 3D panning effect in channels

Our game is a top-down 2D game, and we are playing most of our sounds via FMod Studio events. However, as a fallback for modders, we have the ability to define simple sounds to play, and for this we use the low-level API.

Now the problem with this is that if such a “simple” sound is emitted on the left side of the player, the sound is mostly panned on the left ear, and barely audible on the right ear. In our FMod Studio events we have the 3D Panner set up to minimize this effect, but I can’t seem to imitate this for the low-level API channels.

This is how we create our FMOD::Sound objects:

  FMOD::Sound* sound;
  auto ret = m_lowLevelEngine->createSound(src->GetData(),
    FMOD_OPENMEMORY_POINT | FMOD_CREATESTREAM | FMOD_3D | FMOD_3D_LINEARSQUAREROLLOFF,
    &exinfo, &sound);

We then play the sound and get its channel like this: (we unpause it a bit later)

  m_lowLevelEngine->playSound(ss, grp, true, &chnl);

Then, we set the 3D position in the channel directly after initialization as well as on update whenever the sound source changes position: (SOUND_SCALE is 64.0f)

  FMOD_VECTOR vel = { 0, 0, 0 };
  FMOD_VECTOR position = { pos.x / SOUND_SCALE, pos.y / SOUND_SCALE, pos.z / SOUND_SCALE };
  chnl->set3DAttributes(&position, &vel);

But this causes the extreme panning that I’m trying to avoid/minimize.

I’ve tried adding a 3D panner DSP to the channel in an attempt to mimic the Studio event’s properties in this channel, but it doesn’t make a lot of difference: (I’ve tried a bunch of different values for these as well)

  FMOD::DSP* panDSP = nullptr;
  m_lowLevelEngine->createDSPByType(FMOD_DSP_TYPE_PAN, &panDSP);
  panDSP->setParameterFloat(FMOD_DSP_PAN_2D_DIRECTION, 0.0f);
  panDSP->setParameterFloat(FMOD_DSP_PAN_2D_EXTENT, 0.0f);
  panDSP->setParameterFloat(FMOD_DSP_PAN_3D_MIN_DISTANCE, desc.m_minDist / SOUND_SCALE);
  panDSP->setParameterFloat(FMOD_DSP_PAN_3D_MAX_DISTANCE, desc.m_maxDist / SOUND_SCALE);
  panDSP->setParameterInt(FMOD_DSP_PAN_3D_EXTENT_MODE, FMOD_DSP_PAN_3D_EXTENT_MODE_USER);
  panDSP->setParameterFloat(FMOD_DSP_PAN_3D_MIN_EXTENT, 360.0f);
  panDSP->setParameterFloat(FMOD_DSP_PAN_3D_PAN_BLEND, 0.05f);
  chnl->addDSP(0, panDSP);

What am I missing? Any help or pointers to put me in the right direction would be appreciated. Thanks!

Checkout the 3D project in the LowLevel API examples (api/lowlevel/examples/3d.cpp).
You don’t need to add a panner to the 3D sound because the system will set a matrix on the channel fader or channelgroup fader, and use its own code in update to do the 3d calculations.

This allows you to use event->set3DMinMaxDistance() and channel->set3DAttributes.

That example is pretty much what we were doing before, but how would I stop or lessen the panning/fading on each channel with this when the sound source is on the left or right side? Is the only thing you can do here tweak the sound scale?

You can use Channel::set3DLevel to make the sound more ‘2d’, ie if it was 0.0 there would be no panning or doppler or attenuation. If it is 1.0 (default) it is fully 3d. you can get a good blend inbetween, and especially if it is distance based, to avoid ‘flipping’ from one speaker to another for example.
This is pretty much how the auto envelopment works in studio.

Pulling the listener up from the plane also helps lessen the harshness of panning and makes it bleed in each speaker more too.

Thanks for the reply. Sadly, set3DLevel does not help me here, because I do want the volume to be lower when the sound is emitted at far distance. Setting this value to anything lower than 1.0 will make it hearable from far away distances.

Setting the height of the sound does kind of work to lower the weird effect you get when the sound is on top of you (where you only hear the sound from 1 ear), but when the sound goes further away from you, you of course still hear it in 1 ear.

So I don’t think either of these solutions will work for me. :confused:

An alternative method to make the panning bleed but not the volume, is to use set3DLevel, and FMOD_3D_CUSTOMROLLOFF when loading the sound, so volume is not done at all in 3d, just panning.

You can then simply use setVolume(distance > mindistance ? mindistance / distance : 1.0f); for example to attenuate the signal yourself.