Creating Reverb3D with CoreSystem not producing expected results

Hello!

I have been trying to get 3d Reverbs to work in my project. I have a script that creates the reverb3D, sets its 3d attributes and properties. I also modified RuntimeManager to set the reverb level for index 0 to 100% for all 3d instances. From the reading I’ve done on the docs, I was expecting to notice reverb attenuation as my character with the listener moved closer to the reverb zones. Does the RuntimeManager.CoreSystem.set3DListenerAttributes have to be called manually for all listeners? I thought the StudioListener kept track of its own position. Is the CoreSystem not included? Is there something I’m missing? Any help would be greatly appreciated. Thanks!

-Mitch

here is my code for the reverb zones

using UnityEngine;
using FMODUnity;
using FMOD;

namespace DarkData.Gameplay.Audio
{
    public class DynamicReverbArea : MonoBehaviour
    {
        public enum ReverbType
        {
            CAVE,
            UNDERWATER,
            SEWER_PIPE,
            VENT,
            ARENA,
            BATHROOM,
            ROOM
        }

        [SerializeField] ReverbType reverbPreset;
        [SerializeField] Reverb3D reverb;
        protected Reverb3D GetReverb() { return reverb; }
        [SerializeField] REVERB_PROPERTIES propertiersOne;
        [SerializeField] [Range(1, 100)] float minDistance;
        protected float GetMinDistance() { return minDistance; }
        [SerializeField] [Range(1, 100)] float maxDistance;
        protected float GetMaxDistance() { return maxDistance; }
        protected FMOD.VECTOR positionReference;

        private Color minDistanceColor = new Color(0.488f, 0, 0.488f, 0.6f);
        private Color maxDistanceColor = new Color(0.3f, 0.2f, 0.7f, 0.4f);        

        protected virtual void Start()
        {
            Init();
        }

        protected void Init()
        {
            positionReference = RuntimeUtils.ToFMODVector(transform.position);
            SetReverbProperties(out propertiersOne);            
            RuntimeManager.CoreSystem.createReverb3D(out reverb);
            reverb.set3DAttributes(ref positionReference, minDistance, maxDistance);
            reverb.setProperties(ref propertiersOne);
            reverb.setActive(true);            
        }

        private void Update()
        {
            //hack testing, remove this if it works and move to audio manager

            for (int i = 0; i < RuntimeManager.Listeners.Count; i++)
            {
                if (RuntimeManager.Listeners[i] == null)
                    continue;
                if (RuntimeManager.Listeners[i].transform == null)
                    continue;

                VECTOR pos = RuntimeUtils.ToFMODVector(RuntimeManager.Listeners[i].transform.position);
                VECTOR vel = RuntimeUtils.ToFMODVector(Vector3.zero);
                VECTOR forward = RuntimeUtils.ToFMODVector(RuntimeManager.Listeners[i].transform.forward);
                VECTOR up = RuntimeUtils.ToFMODVector(RuntimeManager.Listeners[i].transform.up);
                //RuntimeManager.CoreSystem.set3DListenerAttributes(i, ref pos, ref pos, ref pos, ref pos);
                RuntimeManager.CoreSystem.set3DListenerAttributes(i, ref pos, ref vel, ref forward, ref up);
            }

            UnityEngine.Debug.LogWarning("Reverb Instance stats =  " + reverb.getProperties(ref propertiersOne).ToString() + " " + reverb.hasHandle().ToString());
        }

        private void SetReverbProperties(out REVERB_PROPERTIES prop)
        {
            switch (reverbPreset)
            {
                case ReverbType.CAVE:
                    prop = PRESET.CAVE();
                    break;
                case ReverbType.UNDERWATER:
                    prop = PRESET.UNDERWATER();
                    break;
                case ReverbType.SEWER_PIPE:
                    prop = PRESET.SEWERPIPE();
                    break;
                case ReverbType.VENT:
                    prop = PRESET.STONECORRIDOR();
                    break;
                case ReverbType.ARENA:
                    prop = PRESET.ARENA();
                    break;
                case ReverbType.BATHROOM:
                    prop = PRESET.BATHROOM();
                    break;
                case ReverbType.ROOM:
                default:
                    prop = PRESET.ROOM();
                    break;
            }            
        }

        private void OnDestroy()
        {
            reverb.release();
            reverb.setActive(false);
        }

        private void OnDrawGizmos()
        {
            Gizmos.color = minDistanceColor;
            Gizmos.DrawSphere(transform.position, minDistance);
            Gizmos.color = maxDistanceColor;
            Gizmos.DrawSphere(transform.position, maxDistance);
        }

    }
}


and here is the modification I made to RuntimeManager

        public static FMOD.Studio.EventInstance CreateInstance(FMOD.GUID guid)
        {
            FMOD.Studio.EventDescription eventDesc = GetEventDescription(guid);
            FMOD.Studio.EventInstance newInstance;
            eventDesc.createInstance(out newInstance);
            bool is3D = false;
            eventDesc.is3D(out is3D);

            #if UNITY_EDITOR
            if (is3D)
            {
                // Set position to 1e+18F, set3DAttributes should be called by the dev after this.
                newInstance.set3DAttributes(RuntimeUtils.To3DAttributes(new Vector3(1e+18F, 1e+18F, 1e+18F)));
                instance.eventPositionWarnings.Add(newInstance);
            }
            #endif

            if (is3D)
            {
                newInstance.setReverbLevel(0, 1);
            }

            return newInstance;
        }

While you have created an instance of the Reverb DSP, you have not added it to the signal chain. To do that you need to get the FMOD.Studio.Bus you want reverb on (the master bus if you want reverb to affect everything), get the underlying FMOD.ChannelGroup and attach the Reverb DSP using ChannelControl.addDSP.

FMOD.Studio.Bus masterBus = FMODUnity.RuntimeManager.GetBus("bus:/");
masterBus.getChannelGroup(out FMOD.ChannelGroup channelGroup);
channelGroup.addDSP(FMOD.CHANNELCONTROL_DSP_INDEX.HEAD, reverb);

You should also detach the DSP when you are finished with it to avoid resource leaks. Please have a look at the Spectrum Analysis Example for more details on working with DSPs in Unity.

As for the RuntimeManager change, I see you are setting reverb using setReverbLevel. This is for use with Core 3D Reverb, which is another way you could approach adding reverb and you can read about in the 3D Reverb Whitepaper. When using the DSP approach you can set Reverb parameters using DSP.setParameterFloat, passing in a FMOD_DSP_SFXREVERB as the index.

Hey @jeff_fmod , thanks for the info! I think the route I want to go is using Core 3D Reverb, as I want its weight to be affected by the position of the listeners. I followed the 3D Reverb Whitepaper as well as checking out related forum posts. I am definitely missing some key steps I’d imagine.

If I were to continue down this route,

        protected void Init()
        {
            positionReference = RuntimeUtils.ToFMODVector(transform.position);
            SetReverbProperties(out propertiersOne);            
            RuntimeManager.CoreSystem.createReverb3D(out reverb);
            reverb.set3DAttributes(ref positionReference, minDistance, maxDistance);
            reverb.setProperties(ref propertiersOne);
            reverb.setActive(true);            
        }

Do I still need to attach that reverb to a bus? From the reading, I thought the Reverb3Ds all used one physical Reverb and you can have as many virtual ones per scene to simulate 3d sphere reverb zones. I feel like I’m close to getting my head around it. Could you help point me in the right direction to using the core system virtual reverbs, and what I’m missing to use runtime created reverbs that use listener location for their effect? It would make my month! I really appreciate the help.

-Mitch

I must have misread which type of reverb you were using there- you do not need to attach the 3D Reverb to any bus.
Your script is working fine for me using FMOD Studio Listeners. You are correct their positions are updated automatically. What version of FMOD are you using?

No worries at all there.

I’m using 2.02.04 for the plugin, and the Unity verified Studio release (I think 2.02). All on MacOS and am using the LTS version of 2019 Unity.

Some caveats of mine to mention:

  • I’m using between 1 and 4 listeners (splitscreen)
  • Could I be using the FMOD Vector and RuntimeUtils wrong? Putting the Reverbs in the wrong world space or something?

Thanks again for helping me out.

**Edit, just checked my studio build, it is the same as the unity plugin (2.02.04)

Is this the case with using my DynamicReverbArea script along with
events from an FMOD Studio Desktop build and setting the EventInstance’s setReverbLevel(0, 1) ?

I’m curious what I am doing that is causing it not to give any reverb in my case.

Thanks for the extra info, I was only testing with a single listener at first but can reproduce this issue now with multiple listeners.
I am finding that the first listener is getting reverb, but none of the others, so this seems to be a bug. I have passed this along to the Dev team to investigate further. Are you finding it’s working with a single listener?

Yes I am using your script and have set the EventInstance’s reverb level.

Hey @jeff_fmod,

After testing some more with the information you gave me, I am getting the same results.

Only the Listener with the index of 0 is affecting the reverb strength. It is not mixing based on the other listener positions.

Any other listeners with indexes above 0 don’t change the reverb strength at all.

If the player with the listener index 0 goes toward the center of a reverb zone, it makes all 3d sounds 100% wet.

Looking forward to hearing a possible quick fix/work around. Using reverb this way sounds awesome and would be perfect if the zones got weighted by multiple listener position. Thanks for all the help. I’ll keep an eye out!

The best workaround to have 3D reverb working with multiple listeners would be to use snapshots. Here is a video explanation of how to get that setup: FMOD & Unity | Creating Reverb Zones - YouTube
It won’t quite give you the same distance attenuation result, but this is currently the recommended approach for confining reverb to a space.