Hello!
We are using FMOD for the PS5 audio based vibrations and also the controller sound. We went the recommended path and used send effects and return buses to implement these features. They work great in most cases (except for the 1 tick delay of the send effect), but we ran into a problem with sustain sounds. We would like to fade out the vibration after all the sounds have played that start before the sustain point. So basically we don’t want to vibrate the looping portion of the event. There are 2 questions here that arise:
- How do we know when to fade out the vibration?
- How do we fade out the vibration without making the whole event fade out?
For 1) we can’t just take the sustain point and fade out when it’s reached, because the sustain point can be for example at 0.5 second on the timeline, but in that 0.5 second it might have started a sound that takes longer than 0.5 second, so that sound would be cut off. We can take all the sounds before the sustain point and find (considering randomization as well) the longest possible playtime and take that as the fade out starting point. This works okay, but I’m wondering if there would be a better solution for this that would make the fade out accurate every time.
For 2) we can manually simulate a fade out effect from code by gradually lowering the value of the FMOD_DSP_SEND_LEVEL parameter on the send effect DSP until it reaches 0. But once again, I’m asking if there is a better solution, as I don’t have much experience on both the Studio or Engine side.
So for the vibration for example, we’ve made the following objects in FMOD Studio for each controller:
- VibrationPort: port with Vibration as Port Type
- VibrationReturn: return bus under the VibrationPort port
- vibration: VCA containing VibrationPort
The rest is handled from the code. Below you can see the relevant code snippets. I don’t include the part where we set up the bus and the port, and link the port to the user, etc.
When we want to vibrate the sound event instance, we do the following:
// Get return ID of return bus
int nReturnId;
FMOD::DSP* pVibrationReturnTailDsp;
pVibrationReturnChannelGroup->getDSP(FMOD_CHANNELCONTROL_DSP_INDEX::FMOD_CHANNELCONTROL_DSP_TAIL, &pVibrationReturnTailDsp);
pVibrationReturnTailDsp->getParameterInt(FMOD_DSP_RETURN_ID, &nReturnId, nullptr, 0);
// Create a send effect, set its target to the return bus, set the vibration strength
pFmodSystem->createDSPByType(FMOD_DSP_TYPE_SEND, &m_pVibrationSendDsp);
m_pVibrationSendDsp->setParameterInt(FMOD_DSP_SEND_RETURNID, nReturnId);
m_pVibrationSendDsp->setParameterFloat(FMOD_DSP_SEND_LEVEL, fVibrationStrength);
// Add the send effect to the end of the event's master signal
pEventChannelGroup->addDSP(FMOD_CHANNELCONTROL_DSP_INDEX::FMOD_CHANNELCONTROL_DSP_HEAD, m_pVibrationSendDsp);
In the case of a sustain event, we call the following function multiple times to simulate a fade out (fSendVolumeLevel changes with time, down to 0):
m_pVibrationSendDsp->setParameterFloat(FMOD_DSP_SEND_LEVEL, fSendVolumeLevel);
Thanks for any help,
Richárd