check current Microphone input volume

hi there!

i'm trying to use the player's voice to control ingame objects directly (without any delay). i have to check how loud the user shouts into his/her microphone. currently it looks like this:

//Script MicrophoneInput
void Start(){
if (device == null) device = Microphone.devices[0];
audio.clip = Microphone.Start(MicrophoneInput.device, true, 999, 44100);
while (!(Microphone.GetPosition(device) > 0))
{} audio.Play();
}
void Update(){

        if (!active) return;
        float[] data = new float[735];
        audio.GetOutputData(data, 0);
//take the median of the recorded samples
        ArrayList s = new ArrayList();
        foreach (float f in data)
        {
            s.Add(Mathf.Abs(f));
        }
        s.Sort();
        Volume = (float)s[735 / 2];
}

this works so far, but only if the audiosource of the object isn't muted. the problem is, i don't want the player to hear her-/himself

i would appreciate any suggestions!

3 Likes

Perhaps you could create an audio listener way outside the map and have it play on that one and determine the volume there, instead?

There's probably a better way, but that would seem to work, if nothing else.

ya that seems to work at first. problem is, that the audioclip created by the Microphone.Start-method is a 2D-Clip, so it doesn't matter where i play it, it's always the same volume

I believe that the 3d aspect is in the audio source. I dont believe any clip is 3d initially, it is all in how you use it.

well, as far as i know are audiosources capable of both, 2d and 3d sound. if i import some audioclips, i can choose if they are used 2d or 3d within the optionbox, but not via a script. at least i couldn't find the fitting methods. so i can't change that the clip that's produced by the Microphone-class is 2d, not 3d.

It's been one year there is no activity on this thread, but Google brings me there.
For the ones looking for a solution, I have one;

int dec = 128;
float[] waveData = new float[dec];
int micPosition = Microphone.GetPosition(null)-(dec+1); // null means the first microphone
clipRecord.GetData(waveData, micPosition);

// Getting a peak on the last 128 samples
float levelMax = 0;
for (int i = 0; i < dec; i++) {
    float wavePeak = waveData[i] * waveData[i];
    if (levelMax < wavePeak) {
        levelMax = wavePeak;
    }
}
// levelMax equals to the highest normalized value power 2, a small number because < 1
// use it like:
UIGauge.level = Mathf.Sqrt(levelMax);

We just read the current recording audioclip, at the current recording position of the microphone

3 Likes

Hi,

@crazyrems

just to step in cause I implement your code. You need to check that micposition is not a negative value else, GetData will fire "result == FMOD_OK" and it doesn't fire an exception so that error is fatal in all cases.

so don't sample if micPosition<0

bye,

Jean

Here is a complete script implementing the solution from above,
as well as making sure that the app doesn't crash when it gets focused/unfocused on a mobile device, or the next level gets loaded.

To access the Value from anywhere just do:

MicInput.MicLoudness;
public class MicInput : MonoBehaviour {

        public static float MicLoudness;

        private string _device;

        //mic initialization
        void InitMic(){
            if(_device == null) _device = Microphone.devices[0];
            _clipRecord = Microphone.Start(_device, true, 999, 44100);
        }

        void StopMicrophone()
        {
            Microphone.End(_device);
        }


        AudioClip _clipRecord = new AudioClip();
        int _sampleWindow = 128;

        //get data from microphone into audioclip
        float  LevelMax()
        {
            float levelMax = 0;
            float[] waveData = new float[_sampleWindow];
            int micPosition = Microphone.GetPosition(null)-(_sampleWindow+1); // null means the first microphone
            if (micPosition < 0) return 0;
            _clipRecord.GetData(waveData, micPosition);
            // Getting a peak on the last 128 samples
            for (int i = 0; i < _sampleWindow; i++) {
                float wavePeak = waveData[i] * waveData[i];
                if (levelMax < wavePeak) {
                    levelMax = wavePeak;
                }
            }
            return levelMax;
        }



        void Update()
        {
            // levelMax equals to the highest normalized value power 2, a small number because < 1
            // pass the value to a static var so we can access it from anywhere
            MicLoudness = LevelMax ();
        }

        bool _isInitialized;
        // start mic when scene starts
        void OnEnable()
        {
            InitMic();
            _isInitialized=true;
        }

        //stop mic when loading a new level or quit application
        void OnDisable()
        {
            StopMicrophone();
        }

        void OnDestroy()
        {
            StopMicrophone();
        }


        // make sure the mic gets started & stopped when application gets focused
        void OnApplicationFocus(bool focus) {
            if (focus)
            {
                //Debug.Log("Focus");

                if(!_isInitialized){
                    //Debug.Log("Init Mic");
                    InitMic();
                    _isInitialized=true;
                }
            }      
            if (!focus)
            {
                //Debug.Log("Pause");
                StopMicrophone();
                //Debug.Log("Stop Mic");
                _isInitialized=false;

            }
        }
    }
11 Likes

Thank you man! This is one of the simplest and working scripts for Mic input out there!

1 Like

[quote=“atomtwist”, post:8, topic: 474574]
Here is a complete script implementing the solution from above,
as well as making sure that the app doesn’t crash when it gets focused/unfocused on a mobile device, or the next level gets loaded.

To access the Value from anywhere just do:

MicInput.MicLoudness;
public class MicInput : MonoBehaviour {
  
        public static float MicLoudness;

        private string _device;
  
        //mic initialization
        void InitMic(){
            if(_device == null) _device = Microphone.devices[0];
            _clipRecord = Microphone.Start(_device, true, 999, 44100);
        }
  
        void StopMicrophone()
        {
            Microphone.End(_device);
        }
  

        AudioClip _clipRecord = new AudioClip();
        int _sampleWindow = 128;
  
        //get data from microphone into audioclip
        float  LevelMax()
        {
            float levelMax = 0;
            float[] waveData = new float[_sampleWindow];
            int micPosition = Microphone.GetPosition(null)-(_sampleWindow+1); // null means the first microphone
            if (micPosition < 0) return 0;
            _clipRecord.GetData(waveData, micPosition);
            // Getting a peak on the last 128 samples
            for (int i = 0; i < _sampleWindow; i++) {
                float wavePeak = waveData[i] * waveData[i];
                if (levelMax < wavePeak) {
                    levelMax = wavePeak;
                }
            }
            return levelMax;
        }
  
  
  
        void Update()
        {
            // levelMax equals to the highest normalized value power 2, a small number because < 1
            // pass the value to a static var so we can access it from anywhere
            MicLoudness = LevelMax ();
        }
  
        bool _isInitialized;
        // start mic when scene starts
        void OnEnable()
        {
            InitMic();
            _isInitialized=true;
        }
  
        //stop mic when loading a new level or quit application
        void OnDisable()
        {
            StopMicrophone();
        }
  
        void OnDestroy()
        {
            StopMicrophone();
        }
  
  
        // make sure the mic gets started & stopped when application gets focused
        void OnApplicationFocus(bool focus) {
            if (focus)
            {
                //Debug.Log("Focus");
          
                if(!_isInitialized){
                    //Debug.Log("Init Mic");
                    InitMic();
                    _isInitialized=true;
                }
            }  
            if (!focus)
            {
                //Debug.Log("Pause");
                StopMicrophone();
                //Debug.Log("Stop Mic");
                _isInitialized=false;
          
            }
        }
    }

[/quote]
Thanks to your answer. If I want to display the realtime volume in decibel, how to calculate by “wavedata”. I mean I can not understand these numbers of MicLoudness.


I have made it now! Thanks!

1 Like

[quote=“Shulin_S”, post:10, topic: 474574]
Thanks to your answer. If I want to display the realtime volume in decibel, how to calculate by “wavedata”. I mean I can not understand these numbers of MicLoudness.


I have made it now! Thanks!
[/quote]

how you have solved it?

[quote=“atomtwist”, post:8, topic: 474574]
Here is a complete script implementing the solution from above,
as well as making sure that the app doesn’t crash when it gets focused/unfocused on a mobile device, or the next level gets loaded.

To access the Value from anywhere just do:

MicInput.MicLoudness;

[/quote]

Hi, i have try your script but it seems that the MicLoudNess no different between silent and noisy…

or any idea to convert to desible unit ?

any idea ?[/QUOTE]

Hi!
I've been using this script and it works great. Does anyone know how to adjust the microphone sensitivity? Not sure how it works.

Thanks!

Info/Explaination

Hi!

Okay, now to end this threat once and for all. READ CLOSELY(for people like me)

The values MicLoudness returns, is a float linear to get it in decibels you need to do this

float db = 20 * Mathf.Log10(Mathf.Abs(MicInput.MicLoudness));

And there you have it Your volume in decibels

If you want to get decibels or float linear of a recorded/audio clip

First do not init the mic and in one of your scripts in start method call MicInput.StopMicrophone

Then use the same code but just change the _cliprecord with your audio clip and instead of 128 use the length of the samples i.e

AudioClip clip = myRecordedOrOwnClip;

_sampleWindow = clip.samples;

If you have any problems let me know

Full Script

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

public class MicInput : MonoBehaviour
{
    #region SingleTon

    public static MicInput Inctance { set; get; }

    #endregion

    public static float MicLoudness;
    public static float MicLoudnessinDecibels;

    private string _device;

    //mic initialization
    public void InitMic()
    {
        if (_device == null)
        {
            _device = Microphone.devices[0];
        }
        _clipRecord = Microphone.Start(_device, true, 999, 44100);
        _isInitialized = true;
    }

    public void StopMicrophone()
    {
        Microphone.End(_device);
        _isInitialized = false;
    }


    AudioClip _clipRecord = new AudioClip();
    AudioClip _recordedClip = new AudioClip();
    int _sampleWindow = 128;

    //get data from microphone into audioclip
    float MicrophoneLevelMax()
    {
        float levelMax = 0;
        float[] waveData = new float[_sampleWindow];
        int micPosition = Microphone.GetPosition(null) - (_sampleWindow + 1); // null means the first microphone
        if (micPosition < 0) return 0;
        _clipRecord.GetData(waveData, micPosition);
        // Getting a peak on the last 128 samples
        for (int i = 0; i < _sampleWindow; i++)
        {
            float wavePeak = waveData[i] * waveData[i];
            if (levelMax < wavePeak)
            {
                levelMax = wavePeak;
            }
        }
        return levelMax;
    }

    //get data from microphone into audioclip
    float MicrophoneLevelMaxDecibels()
    {

        float db = 20 * Mathf.Log10(Mathf.Abs(MicLoudness));

        return db;
    }

    public float FloatLinearOfClip(AudioClip clip)
    {
        StopMicrophone();

        _recordedClip = clip;

        float levelMax = 0;
        float[] waveData = new float[_recordedClip.samples];

        _recordedClip.GetData(waveData, 0);
        // Getting a peak on the last 128 samples
        for (int i = 0; i < _recordedClip.samples; i++)
        {
            float wavePeak = waveData[i] * waveData[i];
            if (levelMax < wavePeak)
            {
                levelMax = wavePeak;
            }
        }
        return levelMax;
    }

    public float DecibelsOfClip(AudioClip clip)
    {
        StopMicrophone();

        _recordedClip = clip;

        float levelMax = 0;
        float[] waveData = new float[_recordedClip.samples];

        _recordedClip.GetData(waveData, 0);
        // Getting a peak on the last 128 samples
        for (int i = 0; i < _recordedClip.samples; i++)
        {
            float wavePeak = waveData[i] * waveData[i];
            if (levelMax < wavePeak)
            {
                levelMax = wavePeak;
            }
        }

        float db = 20 * Mathf.Log10(Mathf.Abs(levelMax));

        return db;
    }



    void Update()
    {
        // levelMax equals to the highest normalized value power 2, a small number because < 1
        // pass the value to a static var so we can access it from anywhere
        MicLoudness = MicrophoneLevelMax();
        MicLoudnessinDecibels = MicrophoneLevelMaxDecibels();
    }

    bool _isInitialized;
    // start mic when scene starts
    void OnEnable()
    {
        InitMic();
        _isInitialized = true;
        Inctance = this;
    }

    //stop mic when loading a new level or quit application
    void OnDisable()
    {
        StopMicrophone();
    }

    void OnDestroy()
    {
        StopMicrophone();
    }


    // make sure the mic gets started & stopped when application gets focused
    void OnApplicationFocus(bool focus)
    {
        if (focus)
        {
            //Debug.Log("Focus");

            if (!_isInitialized)
            {
                //Debug.Log("Init Mic");
                InitMic();
            }
        }
        if (!focus)
        {
            //Debug.Log("Pause");
            StopMicrophone();
            //Debug.Log("Stop Mic");

        }
    }
}

Thanks!

6 Likes

After I updated to Unity 2018.1, I got such error:
NullReferenceException: Object reference not set to an instance of an object
MicInput.LevelMax () (at Assets/MicInput.cs:33)
MicInput.Update () (at Assets/MicInput.cs:50)

which line 33 is:

        _clipRecord.GetData(waveData, micPosition);

and line 50 is:

        MicLoudness = LevelMax ();

Does anyone knows how to fix it?

error

MicInput.cs(26,26): Error CS0143: El tipo 'UnityEngine.AudioClip' no tiene constructores definidos (CS0143) (Assembly-CSharp)
MicInput.cs(28,28): Error CS0143: El tipo 'UnityEngine.AudioClip' no tiene constructores definidos (CS0143) (Assembly-CSharp)

Here is the line 19 : AudioClip _clipRecord = new AudioClip();
On line 19 it gives an error and says: "AudioClip " does not take a constructor that takes 0 arguments.

How to fix it?

[quote=“atomtwist”, post:8, topic: 474574]
Here is a complete script implementing the solution from above,
as well as making sure that the app doesn’t crash when it gets focused/unfocused on a mobile device, or the next level gets loaded.

To access the Value from anywhere just do:

MicInput.MicLoudness;
public class MicInput : MonoBehaviour {
     
        public static float MicLoudness;

        private string _device;
     
        //mic initialization
        void InitMic(){
            if(_device == null) _device = Microphone.devices[0];
            _clipRecord = Microphone.Start(_device, true, 999, 44100);
        }
     
        void StopMicrophone()
        {
            Microphone.End(_device);
        }
     

        AudioClip _clipRecord = new AudioClip();
        int _sampleWindow = 128;
     
        //get data from microphone into audioclip
        float  LevelMax()
        {
            float levelMax = 0;
            float[] waveData = new float[_sampleWindow];
            int micPosition = Microphone.GetPosition(null)-(_sampleWindow+1); // null means the first microphone
            if (micPosition < 0) return 0;
            _clipRecord.GetData(waveData, micPosition);
            // Getting a peak on the last 128 samples
            for (int i = 0; i < _sampleWindow; i++) {
                float wavePeak = waveData[i] * waveData[i];
                if (levelMax < wavePeak) {
                    levelMax = wavePeak;
                }
            }
            return levelMax;
        }
     
     
     
        void Update()
        {
            // levelMax equals to the highest normalized value power 2, a small number because < 1
            // pass the value to a static var so we can access it from anywhere
            MicLoudness = LevelMax ();
        }
     
        bool _isInitialized;
        // start mic when scene starts
        void OnEnable()
        {
            InitMic();
            _isInitialized=true;
        }
     
        //stop mic when loading a new level or quit application
        void OnDisable()
        {
            StopMicrophone();
        }
     
        void OnDestroy()
        {
            StopMicrophone();
        }
     
     
        // make sure the mic gets started & stopped when application gets focused
        void OnApplicationFocus(bool focus) {
            if (focus)
            {
                //Debug.Log("Focus");
             
                if(!_isInitialized){
                    //Debug.Log("Init Mic");
                    InitMic();
                    _isInitialized=true;
                }
            }     
            if (!focus)
            {
                //Debug.Log("Pause");
                StopMicrophone();
                //Debug.Log("Stop Mic");
                _isInitialized=false;
             
            }
        }
    }

[/quote]

Here is the line 19 : AudioClip _clipRecord = new AudioClip();
On line 19 it gives an error and says: "AudioClip " does not take a constructor that takes 0 arguments.

How to fix it?

[quote=“lilshaque”, post:17, topic: 474574]
Here is the line 19 : AudioClip _clipRecord = new AudioClip();
On line 19 it gives an error and says: "AudioClip " does not take a constructor that takes 0 arguments.

How to fix it?
[/quote]

Just remove = new AudioClip()
The microphone class is creating the audioclip anyway, so it’s redundant.

Hey guys, can i increase input decibels then output it?

[quote=“atomtwist”, post:8, topic: 474574]
MicInput.MicLoudness;
[/quote]