How to get micro volume without play back?

Hi, i’m new to FMOD, I’m making a recording sound from mic and get the volume value of it.
Here the code :

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using FMODUnity;

public class RecordMic : MonoBehaviour
{
    [Header("Choose a Microphone")]
    public int RecordingDeviceIndex = 0;
    [TextArea] public string RecordingDeviceName = null;

    [Header("How Long In Seconds Before Recording Plays")]
    public float Latency = 1f;

    [Header("Choose A Key To Play/Pause/Add To Reverb To Recording")]
    public KeyCode PlayAndPause;
    public KeyCode ReverbOnOffSwitch;

    [Header("Volume")]
    public float volume;

    // FMOD Objects
    private FMOD.Sound sound;
    private FMOD.CREATESOUNDEXINFO exinfo;
    private FMOD.Channel channel;
    private FMOD.Channel reverbChannel;
    private FMOD.ChannelGroup channelGroup;

    // Number of recording devices
    private int numOfDriversConnected = 0;
    private int numOfDrivers = 0;

    // Device information
    private System.Guid MicGUID;
    private int SampleRate = 0;
    private FMOD.SPEAKERMODE fmodSpeakerMode;
    private int NumOfChannels = 0;
    private FMOD.DRIVER_STATE driverState;
    private FMOD.DSP playerDSP;

    // Other Variables
    private bool dspEnabled = false;
    private bool playOrPause = true;
    private bool playOkay = false;

    void Start()
    {
        FMOD.RESULT result;

        // Step 1: Check if any recording devices are available
        result = RuntimeManager.CoreSystem.getRecordNumDrivers(out numOfDrivers, out numOfDriversConnected);
        if (result != FMOD.RESULT.OK || numOfDriversConnected == 0)
        {
            Debug.LogError("No microphone connected or failed to get recording devices: " + result);
            return;
        }

        Debug.Log("Microphones available: " + numOfDriversConnected);

        // Step 2: Get information about the recording device
        result = RuntimeManager.CoreSystem.getRecordDriverInfo(
            RecordingDeviceIndex,
            out RecordingDeviceName,
            50,
            out MicGUID,
            out SampleRate,
            out fmodSpeakerMode,
            out NumOfChannels,
            out driverState);

        if (result != FMOD.RESULT.OK)
        {
            Debug.LogError("Failed to get recording device info: " + result);
            return;
        }

        // Step 3: Store relevant information into FMOD.CREATESOUNDEXINFO
        exinfo.cbsize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(FMOD.CREATESOUNDEXINFO));
        exinfo.numchannels = NumOfChannels;
        exinfo.format = FMOD.SOUND_FORMAT.PCM16;
        exinfo.defaultfrequency = SampleRate;
        exinfo.length = (uint)SampleRate * sizeof(short) * (uint)NumOfChannels;

        // Step 4: Create an FMOD Sound object to hold the recording
        result = RuntimeManager.CoreSystem.createSound(
            exinfo.userdata,
            FMOD.MODE.LOOP_NORMAL | FMOD.MODE.OPENUSER,
            ref exinfo,
            out sound);

        if (result != FMOD.RESULT.OK)
        {
            Debug.LogError("Failed to create sound: " + result);
            return;
        }

        // Step 5: Start recording into the Sound object
        result = RuntimeManager.CoreSystem.recordStart(RecordingDeviceIndex, sound, true);
        if (result != FMOD.RESULT.OK)
        {
            Debug.LogError("Failed to start recording: " + result);
            return;
        }


        
        // Step 6: Start a coroutine to play the sound after a delay
        StartCoroutine(Wait());
    }

    IEnumerator Wait()
    {
        yield return new WaitForSeconds(0.002f);

        FMOD.RESULT result;

        // Create channel group
        result = RuntimeManager.CoreSystem.createChannelGroup("Recording", out channelGroup);
        if (result != FMOD.RESULT.OK)
        {
            Debug.LogError("Failed to create channel group: " + result);
            yield break;
        }

        
        // Play the sound
        result = RuntimeManager.CoreSystem.playSound(sound, channelGroup, true, out channel);
        if (result != FMOD.RESULT.OK)
        {
            Debug.LogError("Failed to play sound: " + result);
            yield break;
        }

        playOkay = true;
        Debug.Log("Ready to play");
    }

    void Update()
    {
        volume = GetLoudness();

        // Toggle play/pause on key press
        if (playOkay)
        {
            if (Input.GetKeyDown(PlayAndPause))
            {
                
                playOrPause = !playOrPause;
                FMOD.RESULT result = channel.setPaused(playOrPause);
                if (result != FMOD.RESULT.OK)
                {
                    Debug.LogError("Failed to pause/unpause channel: " + result);
                }
            }
        }

        // Toggle reverb on key press
        if (Input.GetKeyDown(ReverbOnOffSwitch))
        {
            FMOD.REVERB_PROPERTIES propOn = FMOD.PRESET.BATHROOM();
            FMOD.REVERB_PROPERTIES propOff = FMOD.PRESET.OFF();
            dspEnabled = !dspEnabled;
            FMOD.RESULT result = RuntimeManager.CoreSystem.setReverbProperties(1, ref dspEnabled ? ref propOn : ref propOff);
            if (result != FMOD.RESULT.OK)
            {
                Debug.LogError("Failed to set reverb properties: " + result);
            }
        }
    }

    float GetLoudness()
    {
        float rms = 0f;
        FMOD.RESULT result = channel.getDSP(0, out playerDSP);
        if (result != FMOD.RESULT.OK)
        {
            Debug.LogError("Failed to get DSP: " + result);
            return rms;
        }

        playerDSP.setMeteringEnabled(true, true);
        FMOD.DSP_METERING_INFO playerLevel;
        FMOD.DSP_METERING_INFO playerInput;
        result = playerDSP.getMeteringInfo(out playerInput, out playerLevel);
        if (result != FMOD.RESULT.OK)
        {
            Debug.LogError("Failed to get metering info: " + result);
            return rms;
        }

        float playerOutput = playerLevel.peaklevel[0] + playerLevel.peaklevel[1];
        rms = playerOutput * 3;

        return rms;
    }
}

Here is my question:
How can I get the volume the mic recorded without play back ?
How to reduce latency ?
Addition question:
Is it posible to make a bot listen to the sound from Fmod 3D?

Hi,

Thank you for the code.

Could you please elaborate on the behavior you are looking for?

We have documents about adjusting latency here: FMOD Engine | Core API Reference - System::setBufferSize(). In Unity this can be changed with the Unity Integration | Settings - DSP Buffer Settings.

Could you please elaborate?

I find the way to slove 2 other problems. About the NPC problem, player can hear 3D sound, I wonder is their a way to make NPC could hear them? Like hear the sound and reach the pos where the sound was playing.

Thank you for the explanation.

How are you playing the 3D Sound? If it is from an emitter attached to an object, could you pass the object’s position to the bot? If I am misunderstanding, please let me know.

I use the RuntimeManager.AttachInstanceToGameObject() function to play sound.

Thank you for the information.

An option may be passing the object’s position to the bot as the sound should be sharing its position.

Hope this helps.

You mentioned you were able to get the loudness without playing the microphone audio, how? I just want to find the volume of the microphone to drive gameplay events, I don’t want the player to hear the microphone audio.
I’ve been stuck on this 2 days, so any help would be hugely appreciated.

Hi,

What version of the FMOD integration are you using? How are you currently playing the mic input?

An option could be adding a FMOD_DSP_FADER to the CHANNELCONTROL_DSP_INDEX.HEAD of the channel the sound is created on. This will allow you to set the gain value of the fader to -79, essentially silencing the mic input while still allowing you to retrieve the volume from the original fader as NDDEVGAME is doing above. To set the gain value call DSP::setParameterInt().

Hope this helps!

Hi , I hope this code could help u. I tried my best to do it

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using FMODUnity;

public class RecordMic : MonoBehaviour
{
    [Header("Choose a Microphone")]
    public int RecordingDeviceIndex = 0;
    [TextArea] public string RecordingDeviceName = null;
    [Header("How Long In Seconds Before Recording Plays")]
    public float Latency = 1f;
    [Header("Choose A Key To Play/Pause/Add To Reverb To Recording")]
    public KeyCode PlayAndPause;
    public KeyCode ReverbOnOffSwitch;
    [Header("Volume")]
    public float volume;

    // FMOD Objects
    private FMOD.Sound sound;
    private FMOD.CREATESOUNDEXINFO exinfo;
    private FMOD.Channel channel;
    private FMOD.ChannelGroup channelGroup;
    private FMOD.Studio.EventInstance micEventInstance;

    // Recording info
    private int numOfDriversConnected = 0;
    private int numOfDrivers = 0;
    private System.Guid MicGUID;
    private int SampleRate = 0;
    private FMOD.SPEAKERMODE fmodSpeakerMode;
    private int NumOfChannels = 0;
    private FMOD.DRIVER_STATE driverState;
    private FMOD.DSP playerDSP;


    // Start is called before the first frame update
    void Start()
    {
        // Check if any recording devices are connected
        RuntimeManager.CoreSystem.getRecordNumDrivers(out numOfDrivers, out numOfDriversConnected);
        

        if (numOfDriversConnected == 0)
        {
            Debug.Log("<color=#FF00FF>Hey! Plug a Mic in ya dummy</color>");
            return;
        }
        else
        {
            Debug.Log("<color=#FF00FF>You have " + numOfDriversConnected + " microphones available to record with</color>");
        }

        // Get information about the recording device
        RuntimeManager.CoreSystem.getRecordDriverInfo(
            RecordingDeviceIndex,
            out RecordingDeviceName,
            50,
            out MicGUID,
            out SampleRate,
            out fmodSpeakerMode,
            out NumOfChannels,
            out driverState);

        // Set up the sound info
        exinfo.cbsize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(FMOD.CREATESOUNDEXINFO));
        exinfo.numchannels = NumOfChannels;
        exinfo.format = FMOD.SOUND_FORMAT.PCM16;
        exinfo.defaultfrequency = SampleRate;
        exinfo.length = (uint)SampleRate * sizeof(short) * (uint)NumOfChannels;

        // Create the sound object (used for recording only)
        RuntimeManager.CoreSystem.createSound(exinfo.userdata, FMOD.MODE.LOOP_NORMAL | FMOD.MODE.OPENUSER, ref exinfo, out sound);

        // Start recording from the microphone
        RuntimeManager.CoreSystem.recordStart(RecordingDeviceIndex, sound, true);

        StartCoroutine(Wait());
    }
    IEnumerator Wait()
    {
        yield return new WaitForSeconds(Latency);

        RuntimeManager.CoreSystem.createChannelGroup("Recording", out channelGroup);
        RuntimeManager.CoreSystem.playSound(sound, channelGroup, true, out channel);


        Debug.Log("Ready to play");
    }

    public void PlayBackSound(bool play,float volume)
    {
        channel.setVolume(volume);
        channel.setPaused(play);
    }
    public void ReverbSound(bool shouldReverb, ReverbType reverbType)
    {
        FMOD.REVERB_PROPERTIES propOff = FMOD.PRESET.OFF();
        FMOD.REVERB_PROPERTIES propOn = reverbProperties(reverbType);
        RuntimeManager.CoreSystem.setReverbProperties(1, ref shouldReverb ? ref propOn : ref propOff);
    }

    FMOD.REVERB_PROPERTIES reverbProperties(ReverbType type)
    {
        switch (type)
        {
            case ReverbType.Generic: return FMOD.PRESET.GENERIC();
            case ReverbType.PaddedCell: return FMOD.PRESET.PADDEDCELL();
            case ReverbType.Room: return FMOD.PRESET.ROOM();
            case ReverbType.Bathroom: return FMOD.PRESET.BATHROOM();
            case ReverbType.LivingRoom: return FMOD.PRESET.LIVINGROOM();
            case ReverbType.StoneRoom: return FMOD.PRESET.STONEROOM();
            case ReverbType.Auditorium: return FMOD.PRESET.AUDITORIUM();
            case ReverbType.ConcertHall: return FMOD.PRESET.CONCERTHALL();
            case ReverbType.Cave: return FMOD.PRESET.CAVE();
            case ReverbType.Arena: return FMOD.PRESET.ARENA();
            case ReverbType.Hangar: return FMOD.PRESET.HANGAR();
            case ReverbType.CarpetedHallway: return FMOD.PRESET.CARPETTEDHALLWAY();
            case ReverbType.Hallway: return FMOD.PRESET.HALLWAY();
            case ReverbType.StoneCorridor: return FMOD.PRESET.STONECORRIDOR();
            case ReverbType.Alley: return FMOD.PRESET.ALLEY();
            case ReverbType.Forest: return FMOD.PRESET.FOREST();
            case ReverbType.City: return FMOD.PRESET.CITY();
            case ReverbType.Mountains: return FMOD.PRESET.MOUNTAINS();
            case ReverbType.Quarry: return FMOD.PRESET.QUARRY();
            case ReverbType.Plain: return FMOD.PRESET.PLAIN();
            case ReverbType.ParkingLot: return FMOD.PRESET.PARKINGLOT();
            case ReverbType.SewerPipe: return FMOD.PRESET.SEWERPIPE();
            case ReverbType.Underwater: return FMOD.PRESET.UNDERWATER();
            case ReverbType.Off:
            default:
                return FMOD.PRESET.OFF();
        }
    }


    public float GetLoudness()
    {
        // Get the recording position and buffer size
        uint recordPos = 0;
        RuntimeManager.CoreSystem.getRecordPosition(RecordingDeviceIndex, out recordPos);

        // Get the current audio data
        float rms = 0f;
        IntPtr soundData;
        sound.@lock(0, exinfo.length, out soundData, out IntPtr _, out uint len1, out uint _);

        // Calculate RMS (Root Mean Square) for loudness
        short[] buffer = new short[len1 / sizeof(short)];
        System.Runtime.InteropServices.Marshal.Copy(soundData, buffer, 0, buffer.Length);

        foreach (short sample in buffer)
        {
            rms += sample * sample;
        }

        rms = Mathf.Sqrt(rms / buffer.Length) / 32768f;
        sound.unlock(soundData, IntPtr.Zero, len1, 0);

        return rms * 100f; // Scale to a more usable range
    }
}

public enum ReverbType
{
    Off,
    Generic,
    PaddedCell,
    Room,
    Bathroom,
    LivingRoom,
    StoneRoom,
    Auditorium,
    ConcertHall,
    Cave,
    Arena,
    Hangar,
    CarpetedHallway,
    Hallway,
    StoneCorridor,
    Alley,
    Forest,
    City,
    Mountains,
    Quarry,
    Plain,
    ParkingLot,
    SewerPipe,
    Underwater
}
1 Like