# How can I get each Tracks Volume Level?

**URL:** <https://qa.fmod.com/t/how-can-i-get-each-tracks-volume-level/17440>\
**Category:** Unreal Engine\
**Created:** [July 15, 2021, 4:03am UTC](https://qa.fmod.com/t/how-can-i-get-each-tracks-volume-level/17440 "2021-07-15T04:03:51Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![nosestudiokr](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/nosestudiokr/32/2179_2.png) [@nosestudiokr](https://qa.fmod.com/u/nosestudiokr)\
**Post date:** [July 15, 2021, 4:03am UTC](https://qa.fmod.com/t/how-can-i-get-each-tracks-volume-level/17440/1 "2021-07-15T04:03:51Z")

</div>

I could get Master RMS level metering data.  
How can I get each Tracks Volume Level?  
Main\_Track(Event) have multiple instruments. Hope to get each tracks volume.

Thanks in advance.

 ![studio_project](https://canada1.discourse-cdn.com/flex036/uploads/fmod/original/2X/8/816ab6403ebc5b6e73b13fc1b7da0d33b53f3e01.png)

---

<div class="post-metadata">

**Author:** ![richard\_simms](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/richard_simms/32/261_2.png) [@richard\_simms](https://qa.fmod.com/u/richard_simms)\
**Post date:** [July 19, 2021, 3:23am UTC](https://qa.fmod.com/t/how-can-i-get-each-tracks-volume-level/17440/2 "2021-07-19T03:23:42Z")

</div>

You can place a Loudness Meter plugin on each track. In the deck of each track right click and select Add Effect \> FMOD Loudness Meter.

---

<div class="post-metadata">

**Author:** ![nosestudiokr](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/nosestudiokr/32/2179_2.png) [@nosestudiokr](https://qa.fmod.com/u/nosestudiokr)\
**Post date:** [July 20, 2021, 2:57am UTC](https://qa.fmod.com/t/how-can-i-get-each-tracks-volume-level/17440/3 "2021-07-20T02:57:23Z")

</div>

I placed LoudnessMeter(EBU R-128) to each tracks in FMOD Studio.  
I hope to get each track’s metering info in c++.  
How can I get each datas in code.

Thanks for your time.

 ![FS_C](https://canada1.discourse-cdn.com/flex036/uploads/fmod/original/2X/9/91517780b5d65ef7a2c5157fba84301f264e36d5.png)

---

<div class="post-metadata">

**Author:** ![richard\_simms](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/richard_simms/32/261_2.png) [@richard\_simms](https://qa.fmod.com/u/richard_simms)\
**Post date:** [July 20, 2021, 4:53am UTC](https://qa.fmod.com/t/how-can-i-get-each-tracks-volume-level/17440/4 "2021-07-20T04:53:57Z")

</div>

If you want to get the RMS metering data from the API then you can use `DSP::setMeteringEnabled()` and `DSP::getMeteringInfo()`.

[https://www.fmod.com/resources/documentation-api?version=2.02&page=core-api-dsp.html#dsp\_setmeteringenabled](https://www.fmod.com/resources/documentation-api?version=2.02&page=core-api-dsp.html#dsp_setmeteringenabled)

[https://www.fmod.com/resources/documentation-api?version=2.02&page=core-api-dsp.html#dsp\_getmeteringinfo](https://www.fmod.com/resources/documentation-api?version=2.02&page=core-api-dsp.html#dsp_getmeteringinfo)

---

<div class="post-metadata">

**Author:** ![samuelmar](https://avatars.discourse-cdn.com/v4/letter/s/ba9def/32.png) [@samuelmar](https://qa.fmod.com/u/samuelmar)\
**Post date:** [June 23, 2023, 2:38am UTC](https://qa.fmod.com/t/how-can-i-get-each-tracks-volume-level/17440/5 "2023-06-23T02:38:11Z")

</div>

Hi Richard.

Sorry, I can’t figure out how to get eack RMS track using these functions. FMOD\_DSP\_METERING\_INFO is only delivering Master RMS (using “rmslevel”). Could you explain with more detail, please?

In case FMOD Loudness Meter plugins-effect on each track is the only way. How I can get the RMS info of each track by code?

Thanks in advance.

---

<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:** [June 23, 2023, 5:18am UTC](https://qa.fmod.com/t/how-can-i-get-each-tracks-volume-level/17440/6 "2023-06-23T05:18:52Z")

</div>

Hi,

> [@samuelmar](#):
>
> Sorry, I can’t figure out how to get eack RMS track using these functions. FMOD\_DSP\_METERING\_INFO is only delivering Master RMS (using “rmslevel”). Could you explain with more detail, please?

Please take a look at this thread, which contains an overview of how to drill down into FMOD’s DSP chain to retrieve metering info with the functions that Richard mentions: [Unity: getVolume only returning a value of 1? - #6 by Leah\_FMOD](https://qa.fmod.com/t/unity-getvolume-only-returning-a-value-of-1/20128/6)

The code snippets are in C#, but should be fairly easily to convert to C++.

> [@samuelmar](#):
>
> In case FMOD Loudness Meter plugins-effect on each track is the only way. How I can get the RMS info of each track by code?

As for getting metering info for each audio track in an event, it can be a bit more complex - would you mind explaining what you’re trying to accomplish, so that I have a better picture of how to address what you need?

---

<div class="post-metadata">

**Author:** ![samuelmar](https://avatars.discourse-cdn.com/v4/letter/s/ba9def/32.png) [@samuelmar](https://qa.fmod.com/u/samuelmar)\
**Post date:** [June 23, 2023, 5:36am UTC](https://qa.fmod.com/t/how-can-i-get-each-tracks-volume-level/17440/7 "2023-06-23T05:36:16Z")

</div>

Thanks for your quick reply!

Actually I’m working on a Unity project so C# code examples are perfect for me.

I hadn’t thought about the possibility to set channelgroup to anything different than channelgroup-master. Gonna attempt the first solution you have given me and let you know if there is any issue! I think with the first solution I can get the results I expect.

Thanks again, Regards.

---

<div class="post-metadata">

**Author:** ![samuelmar](https://avatars.discourse-cdn.com/v4/letter/s/ba9def/32.png) [@samuelmar](https://qa.fmod.com/u/samuelmar)\
**Post date:** [June 23, 2023, 8:25pm UTC](https://qa.fmod.com/t/how-can-i-get-each-tracks-volume-level/17440/8 "2023-06-23T20:25:18Z")

</div>

Me again, sorry, I wasn’t able to get the metering with each audio track with the first solution.

 ![exampleFMOD](https://canada1.discourse-cdn.com/flex036/uploads/fmod/original/2X/1/11bf270a9faeaef5c9d309bcbf61807c43283455.jpeg)

Here is an example of one of multiple events that I have in my project (as you can see is a song with its multiple tracks) I am programming a mixer in Unity and I need to display metering of each track and the master track. I was able to get master metering info using the next functions:

```auto
private IEnumerator Training_GetChannelGroup() // Called once after load bank and create an instance
    {
        if (eventInstance_Training_User.isValid())
        {
            while (eventInstance_Training_User.getChannelGroup(out channelGroupTraining) != FMOD.RESULT.OK)
            {
                yield return new WaitForEndOfFrame();
            }

            channelGroupTraining.getDSP(0, out dspTraining);
            dspTraining.setMeteringEnabled(false, true);
        }
        else
        {
            yield return null;
        }
    }

    public float Training_GetRMS() //Called everytime I need master info for metering.
    {
        float rms = 0f;

        dspTraining.getMeteringInfo(IntPtr.Zero, out meterInfoTraining);
        for (int i = 0; i < meterInfoTraining.numchannels; i++)
        {
            rms += meterInfoTraining.rmslevel[i] * meterInfoTraining.rmslevel[i];
        }

        rms = Mathf.Sqrt(rms / (float)meterInfoTraining.numchannels);

        float dB = rms > 0 ? 20.0f * Mathf.Log10(rms * Mathf.Sqrt(2.0f)) : -80.0f;
        if (dB > 10.0f) dB = 10.0f;
        return dB;
    }

```

What should be the easist way to get metering of each individual track of an event like this?  
Thanks in advance!

---

<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:** [June 27, 2023, 10:41pm UTC](https://qa.fmod.com/t/how-can-i-get-each-tracks-volume-level/17440/9 "2023-06-27T22:41:33Z")

</div>

> [@samuelmar](#):
>
> What should be the easist way to get metering of each individual track of an event like this?

You can get the ChannelGroups that correspond to each Audio Track in Studio for the event by enumerating them with [`ChannelGroup::getNumGroups`](https://www.fmod.com/docs/2.02/api/core-api-channelgroup.html#channelgroup_getnumgroups) and [`ChannelGroup:getGroup`](https://www.fmod.com/docs/2.02/api/core-api-channelgroup.html#channelgroup_getgroup). The difficult part is being able to identify which Audio Track in Studio matches with each ChannelGroup, as this cannot be done solely via the API.

Thankfully, I have a Studio script on hand that will, for events that you have selected in the event browser in Studio, calculate the order that the event’s Audio Tracks will be returned when using `ChannelGroup::getGroup`, and write that order to the event’s User Properties delimited with commas.

You can retrieve this info in-game from the event’s description with [`Studio::EventDescription::getUserProperty`](https://www.fmod.com/docs/2.02/api/studio-api-eventdescription.html#studio_eventdescription_getuserproperty) and parse it to help sort each Channel Group.

The script is as follows:

```auto
studio.menu.addMenuItem({
    name: "Write Group Order to User Properties",
    execute: function() {
        writeGroupOrder();
    }
});

function writeGroupOrder(){

    // Get all events selected
    var allEvents = studio.window.browserSelection();

    // Check that only events are selected
    var isOnlyEvents = true;
    allEvents.forEach(function(event) {
        if (!(event.isOfExactType("Event"))){
            console.log("object is not event - returning false")
            isOnlyEvents = false;
            return;
        }
    });

    // Show dialog box for error and return early if no selection or objects other than events selected
    if (!isOnlyEvents || allEvents.length == 0) {
        studio.ui.showModalDialog({
            windowTitle: "Warning - Error running script",
            widgetType: studio.ui.widgetType.Layout,
            layout: studio.ui.layoutType.VBoxLayout,
            items: [
                {
                    widgetType: studio.ui.widgetType.Label, text: "No selection, or objects other than events have been selected - please ensure only events are selected when running this script."
                }
            ]
        });
        return false;
    }

    // iterate through events
    allEvents.forEach(function(event) {

        // Create an array of groups that we will sort
        var groups = [];
        // Fill "groups" array with each track from the Event
        event.groupTracks.forEach(function(track) {
            groups.push(track.mixerGroup)
        });

        // Sort the "groups" array based on each track's internal ID
        groups.sort(function(a, b) {
            var id_a = guidToBytes(a.id);
            var id_b = guidToBytes(b.id);
            return intCompare(id_a, id_b);
        });

        // Create string of all IDs in order
        var string = "";
        var delimiter = ",";
        groups.forEach(function(group) {
            string += group.name + delimiter;
        });

        // iterate over event's existing user properties
        // and update Track Order property if it exists already
        var exists = false;
        event.userProperties.every(function(p){
            if (p.key === "Group Order"){
                p.value = string;
                exists = true;
                return false;
            }
            return true;
        });

        // if Track order does not exist already, create and add it to event
        if (!exists){
            var property = studio.project.create("UserProperty");
            property.key = "Group Order";
            property.value = string;
            property.event = event;
        }
        
    });

}

// Function to compare arrays by iterating through each element and comparing them
function intCompare(array1, array2){
    for (var i = 0; i < array1.length; i++){
        var result = array1[i] < array2[i] ? -1 : (array1[i] > array2[i]) ? 1 : 0;
        if (result != 0){
            return result;
        }
    }
    return 0;
}

// Function to convert a GUID string to a byte array
function guidToBytes(guid) {
    var bytes = [];
    // Strip braces and split into segments based on hyphen
    var segmentedGuid = guid.replace(/[{}]/g, "").split('-');
    segmentedGuid.forEach(function(segment, index) {
        // Extract the bytes, the first three segments must be reversed due to endian
        var bytesInSegment = index < 3 ? segment.match(/.{1,2}/g).reverse() : segment.match(/.{1,2}/g);
        bytesInSegment.forEach(function(element) {
            // Convert hex to decimal and add to output
            bytes.push(parseInt(element, 16));
        });
    });
    return bytes;
}

```

Place this script in a `.js` file in the `./scripts` directory of your FMOD Studio install directory or project directory, selected the events you want it to write the order for, and run the script from the “Scripts” menu. Let me know if you run into any issues with it.

---

<div class="post-metadata">

**Author:** ![samuelmar](https://avatars.discourse-cdn.com/v4/letter/s/ba9def/32.png) [@samuelmar](https://qa.fmod.com/u/samuelmar)\
**Post date:** [June 29, 2023, 1:09am UTC](https://qa.fmod.com/t/how-can-i-get-each-tracks-volume-level/17440/10 "2023-06-29T01:09:26Z")

</div>

> [@Leah\_FMOD](#):
>
> ```auto
> studio.menu.addMenuItem({
> name: "Write Group Order to User Properties",
> execute: function() {
> writeGroupOrder();
> }
> });
> 
> function writeGroupOrder(){
> 
> // Get all events selected
> var allEvents = studio.window.browserSelection();
> 
> // Check that only events are selected
> var isOnlyEvents = true;
> allEvents.forEach(function(event) {
> if (!(event.isOfExactType("Event"))){
> console.log("object is not event - returning false")
> isOnlyEvents = false;
> return;
> }
> });
> 
> // Show dialog box for error and return early if no selection or objects other than events selected
> if (!isOnlyEvents || allEvents.length == 0) {
> studio.ui.showModalDialog({
> windowTitle: "Warning - Error running script",
> widgetType: studio.ui.widgetType.Layout,
> layout: studio.ui.layoutType.VBoxLayout,
> items: [
> {
> widgetType: studio.ui.widgetType.Label, text: "No selection, or objects other than events have been selected - please ensure only events are selected when running this script."
> }
> ]
> });
> return false;
> }
> 
> // iterate through events
> allEvents.forEach(function(event) {
> 
> // Create an array of groups that we will sort
> var groups = [];
> // Fill "groups" array with each track from the Event
> event.groupTracks.forEach(function(track) {
> groups.push(track.mixerGroup)
> });
> 
> // Sort the "groups" array based on each track's internal ID
> groups.sort(function(a, b) {
> var id_a = guidToBytes(a.id);
> var id_b = guidToBytes(b.id);
> return intCompare(id_a, id_b);
> });
> 
> // Create string of all IDs in order
> var string = "";
> var delimiter = ",";
> groups.forEach(function(group) {
> string += group.name + delimiter;
> });
> 
> // iterate over event's existing user properties
> // and update Track Order property if it exists already
> var exists = false;
> event.userProperties.every(function(p){
> if (p.key === "Group Order"){
> p.value = string;
> exists = true;
> return false;
> }
> return true;
> });
> 
> // if Track order does not exist already, create and add it to event
> if (!exists){
> var property = studio.project.create("UserProperty");
> property.key = "Group Order";
> property.value = string;
> property.event = event;
> }
>         
> });
> 
> }
> 
> // Function to compare arrays by iterating through each element and comparing them
> function intCompare(array1, array2){
> for (var i = 0; i < array1.length; i++){
> var result = array1[i] < array2[i] ? -1 : (array1[i] > array2[i]) ? 1 : 0;
> if (result != 0){
> return result;
> }
> }
> return 0;
> }
> 
> // Function to convert a GUID string to a byte array
> function guidToBytes(guid) {
> var bytes = [];
> // Strip braces and split into segments based on hyphen
> var segmentedGuid = guid.replace(/[{}]/g, "").split('-');
> segmentedGuid.forEach(function(segment, index) {
> // Extract the bytes, the first three segments must be reversed due to endian
> var bytesInSegment = index < 3 ? segment.match(/.{1,2}/g).reverse() : segment.match(/.{1,2}/g);
> bytesInSegment.forEach(function(element) {
> // Convert hex to decimal and add to output
> bytes.push(parseInt(element, 16));
> });
> });
> return bytes;
> }
> 
> ```

Awesome! Thanks for share me this script and a detailed solution to reach my goal.

I followed your steps and I got the results that I expected,

thanks a lot for all your help with this issue!

Samuel.
