# GC Alloc in DSP.getMeteringInfo

**URL:** <https://qa.fmod.com/t/gc-alloc-in-dsp-getmeteringinfo/22712>\
**Category:** Unity\
**Tags:** unity, csharp\
**Created:** [March 20, 2025, 12:55am UTC](https://qa.fmod.com/t/gc-alloc-in-dsp-getmeteringinfo/22712 "2025-03-20T00:55:23Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![fendercodes](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/fendercodes/32/2971_2.png) [@fendercodes](https://qa.fmod.com/u/fendercodes)\
**Post date:** [March 20, 2025, 12:55am UTC](https://qa.fmod.com/t/gc-alloc-in-dsp-getmeteringinfo/22712/1 "2025-03-20T00:55:23Z")

</div>

I’m noticing that there is GC allocation when calling DSP.getMeteringInfo, as shown in the (deep) profile below:

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/fmod/original/2X/a/af80c03faf2a6de7a0ec76d7d798662eda6de0d9.png)

I’ve cached the variables that I can on my side, and so the code is simply just this now:

```auto
void LateUpdate() {
  m_VoiceEventInstanceDSP.getMeteringInfo(out inputInfo, IntPtr.Zero);
}

```

For something that is typically run frequently, it would be great if this could be made to not allocate.

---

<div class="post-metadata">

**Author:** ![Leah\_FMOD](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/leah_fmod/32/3685_2.png) [@Leah\_FMOD](https://qa.fmod.com/u/Leah_FMOD)\
**Post date:** [March 25, 2025, 2:25am UTC](https://qa.fmod.com/t/gc-alloc-in-dsp-getmeteringinfo/22712/2 "2025-03-25T02:25:11Z")

</div>

Thanks for pointing the allocation out, I can definitely see what you mean regarding the frequency the method is usually called with. I’ve added your suggestion to our internal improvement tracker.

---

<div class="post-metadata">

**Author:** ![fendercodes](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/fendercodes/32/2971_2.png) [@fendercodes](https://qa.fmod.com/u/fendercodes)\
**Post date:** [March 25, 2025, 7:12am UTC](https://qa.fmod.com/t/gc-alloc-in-dsp-getmeteringinfo/22712/3 "2025-03-25T07:12:43Z")

</div>

Thanks, that would be great as we are hoping to go to production with our title before long.

---

<div class="post-metadata">

**Author:** ![Leah\_FMOD](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/leah_fmod/32/3685_2.png) [@Leah\_FMOD](https://qa.fmod.com/u/Leah_FMOD)\
**Post date:** [April 14, 2025, 6:21am UTC](https://qa.fmod.com/t/gc-alloc-in-dsp-getmeteringinfo/22712/4 "2025-04-14T06:21:47Z")

</div>

Just to follow up on this, if you’re willing to modify the FMOD Unity integration code, you can swap usages of the `out` keyword for `ref` for `DSP.getMeteringInfo()`, and it should remove the GC allocation. You’d also need to make sure to initialize any `DSP_METERING_INFO` structs with `new FMOD.DSP_METERING_INFO()` since you’re passing them to the function instead of having them passed out.

For just the code in the FMOD Unity integration (exact lines may differ based on your version), you’d need to modify the following:

- fmod.cs, lines ~3434 - ~3444: change any usages of `out` to `ref` for all `getMeteringInfo` overloads
- RuntimeManager.cs, lines ~721 - ~722: add struct initialization and change keyword usage
- EditorUtils.cs, lines ~816 - ~817: add struct initialization and change keyword usage

---

<div class="post-metadata">

**Author:** ![fendercodes](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/fendercodes/32/2971_2.png) [@fendercodes](https://qa.fmod.com/u/fendercodes)\
**Post date:** [April 15, 2025, 3:19am UTC](https://qa.fmod.com/t/gc-alloc-in-dsp-getmeteringinfo/22712/5 "2025-04-15T03:19:29Z")

</div>

Thanks for the update! I am assuming that these improvements will make it in to an official update? We regularly update FMOD to the latest version so this would be a bit cumbersome to remember to apply every time.

---

<div class="post-metadata">

**Author:** ![Leah\_FMOD](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/leah_fmod/32/3685_2.png) [@Leah\_FMOD](https://qa.fmod.com/u/Leah_FMOD)\
**Post date:** [April 16, 2025, 2:16am UTC](https://qa.fmod.com/t/gc-alloc-in-dsp-getmeteringinfo/22712/6 "2025-04-16T02:16:30Z")

</div>

The improvements are scheduled to be included in an official update, yes. However, since we aim to maintain code compatibility between minor API versions, it’s unlikely to be until our next major version update (2.04) since the keyword change would necessitate code changes on the part of people using DSP\_METERING\_INFO structs in their own code.

---

<div class="post-metadata">

**Author:** ![fendercodes](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/fendercodes/32/2971_2.png) [@fendercodes](https://qa.fmod.com/u/fendercodes)\
**Post date:** [April 22, 2025, 12:22am UTC](https://qa.fmod.com/t/gc-alloc-in-dsp-getmeteringinfo/22712/7 "2025-04-22T00:22:07Z")

</div>

So I tried your suggestions but still get the GC as seen here:

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/fmod/original/2X/f/f1ccf34010b30ae88740399798296a4b8e51292e.png)

This is a patch file showing what changes I made.

```auto
diff --git a/Assets/Plugins/FMOD/src/Editor/EditorUtils.cs b/Assets/Plugins/FMOD/src/Editor/EditorUtils.cs
index bdcffac7a..da2982370 100644
--- a/Assets/Plugins/FMOD/src/Editor/EditorUtils.cs
+++ b/Assets/Plugins/FMOD/src/Editor/EditorUtils.cs
@@ -813,8 +813,8 @@ public static float[] GetMetering()
             FMOD.DSP masterHead;
             CheckResult(master.getDSP(FMOD.CHANNELCONTROL_DSP_INDEX.HEAD, out masterHead));
 
- FMOD.DSP_METERING_INFO outputMetering;
- CheckResult(masterHead.getMeteringInfo(IntPtr.Zero, out outputMetering));
+ FMOD.DSP_METERING_INFO outputMetering = new();
+ CheckResult(masterHead.getMeteringInfo(IntPtr.Zero, ref outputMetering));
 
             FMOD.SPEAKERMODE mode;
             int rate, raw;
diff --git a/Assets/Plugins/FMOD/src/RuntimeManager.cs b/Assets/Plugins/FMOD/src/RuntimeManager.cs
index b3e5f6a83..921d1437a 100644
--- a/Assets/Plugins/FMOD/src/RuntimeManager.cs
+++ b/Assets/Plugins/FMOD/src/RuntimeManager.cs
@@ -718,8 +718,8 @@ private void UpdateDebugText()
                     coreSystem.getChannelsPlaying(out channels, out realchannels);
                     debug.AppendFormat("CHANNELS: real = {0}, total = {1}\n", realchannels, channels);
 
- FMOD.DSP_METERING_INFO outputMetering;
- mixerHead.getMeteringInfo(IntPtr.Zero, out outputMetering);
+ FMOD.DSP_METERING_INFO outputMetering = new();
+ mixerHead.getMeteringInfo(IntPtr.Zero, ref outputMetering);
                     float rms = 0;
                     for (int i = 0; i < outputMetering.numchannels; i++)
                     {
diff --git a/Assets/Plugins/FMOD/src/fmod.cs b/Assets/Plugins/FMOD/src/fmod.cs
index 0ab3b032a..c45d312db 100644
--- a/Assets/Plugins/FMOD/src/fmod.cs
+++ b/Assets/Plugins/FMOD/src/fmod.cs
@@ -3440,17 +3440,17 @@ public RESULT getMeteringEnabled(out bool inputEnabled, out bool outputEnabled)
             return FMOD5_DSP_GetMeteringEnabled(this.handle, out inputEnabled, out outputEnabled);
         }
 
- public RESULT getMeteringInfo(IntPtr zero, out DSP_METERING_INFO outputInfo)
+ public RESULT getMeteringInfo(IntPtr zero, ref DSP_METERING_INFO outputInfo)
         {
- return FMOD5_DSP_GetMeteringInfo(this.handle, zero, out outputInfo);
+ return FMOD5_DSP_GetMeteringInfo(this.handle, zero, ref outputInfo);
         }
- public RESULT getMeteringInfo(out DSP_METERING_INFO inputInfo, IntPtr zero)
+ public RESULT getMeteringInfo(ref DSP_METERING_INFO inputInfo, IntPtr zero)
         {
- return FMOD5_DSP_GetMeteringInfo(this.handle, out inputInfo, zero);
+ return FMOD5_DSP_GetMeteringInfo(this.handle, ref inputInfo, zero);
         }
- public RESULT getMeteringInfo(out DSP_METERING_INFO inputInfo, out DSP_METERING_INFO outputInfo)
+ public RESULT getMeteringInfo(ref DSP_METERING_INFO inputInfo, ref DSP_METERING_INFO outputInfo)
         {
- return FMOD5_DSP_GetMeteringInfo(this.handle, out inputInfo, out outputInfo);
+ return FMOD5_DSP_GetMeteringInfo(this.handle, ref inputInfo, ref outputInfo);
         }
 
         public RESULT getCPUUsage(out uint exclusive, out uint inclusive)
@@ -3540,11 +3540,11 @@ public RESULT getCPUUsage(out uint exclusive, out uint inclusive)
         [DllImport(VERSION.dll)]
         public static extern RESULT FMOD5_DSP_GetMeteringEnabled (IntPtr dsp, out bool inputEnabled, out bool outputEnabled);
         [DllImport(VERSION.dll)]
- public static extern RESULT FMOD5_DSP_GetMeteringInfo (IntPtr dsp, IntPtr zero, out DSP_METERING_INFO outputInfo);
+ public static extern RESULT FMOD5_DSP_GetMeteringInfo (IntPtr dsp, IntPtr zero, ref DSP_METERING_INFO outputInfo);
         [DllImport(VERSION.dll)]
- public static extern RESULT FMOD5_DSP_GetMeteringInfo (IntPtr dsp, out DSP_METERING_INFO inputInfo, IntPtr zero);
+ public static extern RESULT FMOD5_DSP_GetMeteringInfo (IntPtr dsp, ref DSP_METERING_INFO inputInfo, IntPtr zero);
         [DllImport(VERSION.dll)]
- public static extern RESULT FMOD5_DSP_GetMeteringInfo (IntPtr dsp, out DSP_METERING_INFO inputInfo, out DSP_METERING_INFO outputInfo);
+ public static extern RESULT FMOD5_DSP_GetMeteringInfo (IntPtr dsp, ref DSP_METERING_INFO inputInfo, ref DSP_METERING_INFO outputInfo);
         [DllImport(VERSION.dll)]
         public static extern RESULT FMOD5_DSP_GetCPUUsage (IntPtr dsp, out uint exclusive, out uint inclusive);
         #endregion
diff --git a/Assets/Scripts/Player/PlayerVoiceSpeaker.cs b/Assets/Scripts/Player/PlayerVoiceSpeaker.cs
index 05bd2f60d..b2a49828c 100644
--- a/Assets/Scripts/Player/PlayerVoiceSpeaker.cs
+++ b/Assets/Scripts/Player/PlayerVoiceSpeaker.cs
@@ -26,7 +26,7 @@ public class PlayerVoiceSpeaker : Speaker {
     PARAMETER_ID m_OcclusionParameter;
     IAudioOut<float> m_VoiceEvent;
     Transform m_Head;
- DSP_METERING_INFO inputInfo;
+ DSP_METERING_INFO inputInfo = new();
 
     protected override void Awake() {
         base.Awake();
@@ -75,7 +75,7 @@ public class PlayerVoiceSpeaker : Speaker {
             }
         }
 
- m_VoiceEventInstanceDSP.getMeteringInfo(out inputInfo, IntPtr.Zero);
+ m_VoiceEventInstanceDSP.getMeteringInfo(ref inputInfo, IntPtr.Zero);
         VoiceEventDecibels = FMODUtility.lin2dB(inputInfo.rmslevel[0]);
 
         // OcclusionAudioSource on the Player only sets Occlusion for child StudioEventEmitter components

```

Separately, if you ever wanted to release it in a minor API version update you could add a new function override for this non-GC alternative and add the Obsolete attribute to the old ones.

---

<div class="post-metadata">

**Author:** ![Leah\_FMOD](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/leah_fmod/32/3685_2.png) [@Leah\_FMOD](https://qa.fmod.com/u/Leah_FMOD)\
**Post date:** [April 28, 2025, 7:01am UTC](https://qa.fmod.com/t/gc-alloc-in-dsp-getmeteringinfo/22712/8 "2025-04-28T07:01:24Z")

</div>

> [@fendercodes](#):
>
> So I tried your suggestions but still get the GC as seen here:

My apologies - the issue is a little more complex than just changing the keyword, and has to do with the whether or not members of the struct are blittable. Unfortunately I don’t have a workaround for you at the moment, but I’ll update you when I do.

> [@fendercodes](#):
>
> Separately, if you ever wanted to release it in a minor API version update you could add a new function override for this non-GC alternative and add the Obsolete attribute to the old ones.

I will note this on our feature tracker; I can’t make any promises, but it may be possible depending on the implementation of the fix.

---

<div class="post-metadata">

**Author:** ![Leah\_FMOD](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/leah_fmod/32/3685_2.png) [@Leah\_FMOD](https://qa.fmod.com/u/Leah_FMOD)\
**Post date:** [September 3, 2025, 4:45am UTC](https://qa.fmod.com/t/gc-alloc-in-dsp-getmeteringinfo/22712/9 "2025-09-03T04:45:18Z")

</div>

Hi,

Just to follow up on this - a fix for this has been found to be compatible with 2.03, and is currently scheduled for our next 2.03 release, 2.03.10. The fix changes the `DSP_METERING_ARRAY` struct in fmod\_dsp.cs to the following:

```csharp
    [StructLayout(LayoutKind.Sequential)]
    public struct DSP_METERING_INFO
    {
        public int numsamples;
        public LEVEL_ARRAY peaklevel;
        public LEVEL_ARRAY rmslevel;
        public short numchannels;
 
        #region wrapperinternal
 
        [StructLayout(LayoutKind.Sequential)]
        public struct LEVEL_ARRAY
        {
            // Explicitly define level array elements to avoid allocation
            private float ch0, ch1, ch2, ch3, ch4, ch5, ch6, ch7;
            private float ch8, ch9, ch10, ch11, ch12, ch13, ch14, ch15;
            private float ch16, ch17, ch18, ch19, ch20, ch21, ch22, ch23;
            private float ch24, ch25, ch26, ch27, ch28, ch29, ch30, ch31;
 
            // Indexer for access to elements
            public float this[int index]
            {
                get
                {
                    switch (index)
                    {
                        case 0: return ch0;
                        case 1: return ch1;
                        case 2: return ch2;
                        case 3: return ch3;
                        case 4: return ch4;
                        case 5: return ch5;
                        case 6: return ch6;
                        case 7: return ch7;
                        case 8: return ch8;
                        case 9: return ch9;
                        case 10: return ch10;
                        case 11: return ch11;
                        case 12: return ch12;
                        case 13: return ch13;
                        case 14: return ch14;
                        case 15: return ch15;
                        case 16: return ch16;
                        case 17: return ch17;
                        case 18: return ch18;
                        case 19: return ch19;
                        case 20: return ch20;
                        case 21: return ch21;
                        case 22: return ch22;
                        case 23: return ch23;
                        case 24: return ch24;
                        case 25: return ch25;
                        case 26: return ch26;
                        case 27: return ch27;
                        case 28: return ch28;
                        case 29: return ch29;
                        case 30: return ch30;
                        case 31: return ch31;
                        default: throw new IndexOutOfRangeException();
                    }
                }
            }
 
            public readonly int Length => 32;
 
            // Implicit conversion for unchanged access to entire array
            public static implicit operator float[](LEVEL_ARRAY levels)
            {
                float[] buffer = new float[levels.Length];
                for (int i = 0; i < levels.Length; i++)
                {
                    buffer[i] = levels[i];
                }
                return buffer;
            }
 
            // Zero allocation copy-to
            public void CopyTo(float[] buffer)
            {
                int len = buffer.Length >= this.Length ? this.Length : buffer.Length;
                for (int i = 0; i < len; i++)
                {
                    buffer[i] = this[i];
                }
            }
        }
 
        #endregion
    }

```

This change means that metering level data can be accessed in three ways:

- By element i.e. `meteringInfo.rmslevel[i]` - should cause no `GC.Alloc`
- Using `.CopyTo()`i.e. `meteringInfo.rmslevel.CopyTo(yourArray) -`should cause no `GC.Alloc`
- Directly accessing the entire array i.e. `var yourArray = meteringInfo.rmslevel` - uses an implicit conversion to maintain compatibility, but will cause `GC.Alloc`

I unfortunately can’t give you a timeline for when 2.03.10 will release, but if you update to it when it releases, or choose to modify the existing code with the above snippet, please let me know whether it addresses the issue for you!

---

<div class="post-metadata">

**Author:** ![fendercodes](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/fendercodes/32/2971_2.png) [@fendercodes](https://qa.fmod.com/u/fendercodes)\
**Post date:** [September 14, 2025, 6:17pm UTC](https://qa.fmod.com/t/gc-alloc-in-dsp-getmeteringinfo/22712/10 "2025-09-14T18:17:14Z")

</div>

That’s great! Thank you. I’ll wait for 2.03.10 to drop before updating and taking it for a spin. Hopefully not much longer now?

---

<div class="post-metadata">

**Author:** ![Leah\_FMOD](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/leah_fmod/32/3685_2.png) [@Leah\_FMOD](https://qa.fmod.com/u/Leah_FMOD)\
**Post date:** [September 22, 2025, 7:08am UTC](https://qa.fmod.com/t/gc-alloc-in-dsp-getmeteringinfo/22712/11 "2025-09-22T07:08:14Z")

</div>

> [@fendercodes](#):
>
> Hopefully not much longer now?

We’re hard at work on the next release, but again, I unfortunately can’t provide an exact timeline.

---

<div class="post-metadata">

**Author:** ![fendercodes](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/fendercodes/32/2971_2.png) [@fendercodes](https://qa.fmod.com/u/fendercodes)\
**Post date:** [November 19, 2025, 7:29am UTC](https://qa.fmod.com/t/gc-alloc-in-dsp-getmeteringinfo/22712/12 "2025-11-19T07:29:36Z")

</div>

I see that it dropped, thanks for all the hard work! 🙂
