Ayhem
Ayhem

Reputation: 247

Check microphone for silence

While recording user voice, i want to know when he/she stopped talking to end the recording and send the audio file to google speech recognition API.

I found this thread here and tried to use it's solution but i am always getting the same value from the average of spectrum data which is 5.004574E-08: Unity - Microphone check if silent

This is the code i am using for getting the GetSpectrumData value:

public void StartRecordingSpeech()
    {
        //If there is a microphone
        if (micConnected)
        {
            if (!Microphone.IsRecording(null))
            {
                goAudioSource.clip = Microphone.Start(null, true, 10, 44100); //Currently set for a 10 second clip max
                goAudioSource.Play();
                StartCoroutine(StartRecordingSpeechCo());
            }
        }
        else
        {
            Debug.LogError("No microphone is available");
        }
    }

IEnumerator StartRecordingSpeechCo()
    {
        while (Microphone.IsRecording(null))
        {
            float[] clipSampleData = new float[128];
            goAudioSource.GetSpectrumData(clipSampleData, 0, FFTWindow.Rectangular);
            Debug.Log(clipSampleData.Average());
            yield return null;
        }
    }

PS: I am able to record the users voice, save it and get the right response from the voice recognition api.

Upvotes: 0

Views: 1432

Answers (2)

Ayhem
Ayhem

Reputation: 247

The following method is what worked for me. it detect the volume of the microphone, turn it into decibels. It does not need to play the recorded audio or anything. (credit goes to this old thread in the unity answers: https://forum.unity.com/threads/check-current-microphone-input-volume.133501/).

    public 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;
            goAudioSource.clip.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;
                }
            }
float db = 20 * Mathf.Log10(Mathf.Abs(levelMax));
            return db;
        }

In my case, if the value is bigger then -40 then the user is talking!if its 0 or bigger then there is a loud noise, other then that, its silence!

Upvotes: 1

derHugo
derHugo

Reputation: 90580

If you are interested in a volume then GetSpectrumData is actually not really what you want. This is used for frequency analysis and returns - as the name says - a frequency spectrum so how laud is which frequency in a given frequency range.


What you rather want to use is GetOutputData which afaik returns an array with amplitudes from -1 to 1. So you have to square all values, get the average and take the square root of this result (source)

float[] clipSampleData = new float[128];
goAudioSource.GetOutputData(clipSampleData, 0);

Debug.Log(Mathf.Sqrt(clipSampleData.Select(f => f*f).Average()));

Upvotes: 0

Related Questions