Forum Discussion

wondder's avatar
wondder
Honored Guest
23 days ago

Quest 2 – Microphone.IsRecording == true but Microphone.GetPosition stays 0

Device: Meta Quest 2
OS: 81.0.0.1083.403
Unity: 6000.0.43f (Android, IL2CPP)
API: UnityEngine.Microphone
Use-case: Starting the microphone & checking if there is some data coming out of it

Hi everyone, 

I have experienced a very weird bug on my Quest 2 app recently. I basically have a screen that checks that the mic is on when a user starts my application, as my app needs a microphone, it's to prevent users from starting it while their mic is muted and they can't go through the app. And recently I have had reports from users telling me that their mic is not muted & the app has the correct permissions but they still see that screen.
The fix for now that I have made is that I added that when the app is paused with `OnApplicationPause`, that I stop the microphone & then when the app is unpaused, I restart it. And this works. 
Interestingly, restarting the app when they see that screen, without puting the headset to sleep & waking up again (just with a short tap on the quest power button) is NOT fixing the issue, it needs to be put to sleep. And that is where I start getting quite confusing and I am asking for some help of people who know more than I do.

And the very very annoying thing about this bug is that it is super inconsistent, sometimes I have it 5 times in a row. And sometimes I don't have it when starting my app 30 times in a row. I have the feeling that it happens more often when I have just switched on the headset and start the app right after, but this might just have been a coincidence. I don't have a stable way to reproduce that error, it's just happening sometimes.

This is what I have checked:

  • Microphone.Start(device, true, ..., 16000) returns a non-null AudioClip.
  • Microphone.IsRecording(device) returns true.
  • But Microphone.GetPosition(device) stays at 0 forever – I poll it every frame for >5 seconds.
  • No exceptions. The clip exists, but no samples are ever written; my loudness stays at 0.

Does anybody have any hint about where I can look at? I am pretty stuck right now.

This are my logs from my quest

12:19:10.123  Unity  I  <b><color=purple>RECOGNISSIMO Start Mic Starting</color></b>
12:19:10.123  Unity  I  InitMic: recording=True pos=0 device=''

12:19:10.123  AAudio I  AAudioStreamBuilder_openStream() called ----------------------------
12:19:10.123  AAudio I  AudioStreamBuilder: rate = 16000, channels = 1, format = 5, dir = INPUT
12:19:10.123  AAudio D  AudioStreamBuilder: build() enable (auto) aaudio input mmap via gk
12:19:10.123  AAudio D  AudioStreamBuilder: build() package com.wondder.GivingFeedback denied mmap

12:19:10.146  Unity  I  InitMic: recording=True pos=0 device=''
12:19:10.159  Unity  I  InitMic: recording=True pos=0 device=''
12:19:10.267  Unity  I  InitMic: recording=True pos=0 device=''

12:19:10.268  EffectHAL  W  Effect ... SET_CONFIG returned status: Invalid argument
12:19:10.273  EffectHAL  W  Effect ... SET_CONFIG returned status: Invalid argument
12:19:10.296  AudioFlinger W createRecordTrack_l(): mismatch between requested flags (...) and input flags (...)
12:19:10.324  audio_hw_primary D adev_close_input_stream: ...
12:19:10.324  audio_hw_primary D io_streams_map_remove: Removed stream with handle ...
12:19:10.324  audio_hw_primary D in_standby: usecase(30: low-latency-record)


This is my code simplified

using UnityEngine;
using System.Collections;

public class MicInitTest : MonoBehaviour
{
    public string DeviceName = null; 
    public int SampleRate = 16000;
    public float TimeSensitivity = 0.25f;

    AudioClip _clip;
    bool _micInitializing;
    bool _microphoneInitialized;

    IEnumerator Start()
    {
        yield return InitializeMicrophone();
    }

    IEnumerator InitializeMicrophone()
    {
        if (_micInitializing || _microphoneInitialized)
            yield break;

        _micInitializing = true;

        // 1) Stop any previous recording
        if (Microphone.IsRecording(DeviceName))
        {
            Debug.Log("MIC was already recording, calling End()");
            Microphone.End(DeviceName);

            float endStart = Time.realtimeSinceStartup;
            const float endTimeout = 3f;

            while (Microphone.IsRecording(DeviceName) &&
                   Time.realtimeSinceStartup - endStart < endTimeout)
            {
                Debug.Log("Waiting for mic to end recording…");
                yield return null;
            }
        }

        // 2) Start recording
        int maxRecordingTime = Mathf.Max(2, (int)(TimeSensitivity + 1f));
        _clip = Microphone.Start(DeviceName, true, maxRecordingTime, SampleRate);
        Debug.Log("<b><color=purple>RECOGNISSIMO Start Mic Starting</color></b>");

        if (_clip == null)
        {
            Debug.LogError("Microphone.Start returned null clip");
            _micInitializing = false;
            yield break;
        }

        // 3) Wait until GetPosition > 0 (or timeout). On good runs this happens
        // after a few frames, on bad runs it never happens.
        float startTime = Time.realtimeSinceStartup;
        const float timeoutSeconds = 5f;
        int nbOfTry = 0;
        const int maxNbOfTry = 1;

        while (true)
        {
            int pos = Microphone.GetPosition(DeviceName);
            bool recording = Microphone.IsRecording(DeviceName);

            Debug.Log($"InitMic: recording={recording} pos={pos} device='{DeviceName}'");

            if (pos > 0)
                break;

            if (!recording && Time.realtimeSinceStartup - startTime > timeoutSeconds)
            {
                Debug.LogError("Microphone is not recording, aborting init");
                _micInitializing = false;
                yield break;
            }

            if (Time.realtimeSinceStartup - startTime > timeoutSeconds)
            {
                if (nbOfTry >= maxNbOfTry)
                {
                    Debug.LogError("Timeout waiting for mic position > 0");
                    _micInitializing = false;
                    yield break;
                }

                nbOfTry++;
                yield return HardResetAudio();
                // Retry once
                _clip = Microphone.Start(DeviceName, true, maxRecordingTime, SampleRate);
                startTime = Time.realtimeSinceStartup;
            }

            yield return null;
        }

        _microphoneInitialized = true;
        _micInitializing = false;
        Debug.Log("<b><color=green>Microphone initialized successfully.</color></b>");
    }

    IEnumerator HardResetAudio()
    {
        Debug.Log("Hard reset audio and mic (StopAudioOutput/StartAudioOutput)");

        AudioSettings.Mobile.StopAudioOutput();
        yield return new WaitForEndOfFrame();
        AudioSettings.Mobile.StartAudioOutput();
        yield return new WaitForEndOfFrame();
    }
}

 

No RepliesBe the first to reply

→ Find helpful resources to begin your development journey in Getting Started

→ Get the latest information about HorizonOS development in News & Announcements.

→ Access Start program mentor videos and share knowledge, tutorials, and videos in Community Resources.

→ Get support or provide help in Questions & Discussions.

→ Show off your work in What I’m Building to get feedback and find playtesters.

→ Looking for documentation?  Developer Docs

→ Looking for account support?  Support Center

→ Looking for the previous forum?  Forum Archive

→ Looking to join the Start program? Apply here.

 

Recent Discussions