using UnityEngine; [RequireComponent(typeof(AudioSource))] public class MicrophoneTesting : MonoBehaviour { [Header("Mic settings")] [Tooltip("Leave empty for default device")] public string deviceName = ""; [Range(1, 60)] public int bufferLengthSec = 10; // rolling buffer for mic clip public int requestedSampleRate = 48000; // 48000 is best match for Quest & many headsets public bool playOnStart = true; [Header("Runtime")] public bool isRecording; public bool isPlaying; private AudioSource _src; private AudioClip _micClip; void Awake() { _src = GetComponent(); _src.loop = true; // continuous playback _src.playOnAwake = false; // we will start manually } void Start() { if (playOnStart) StartLoopback(); } public void StartLoopback() { if (isRecording) return; // Pick default mic if none specified string dev = deviceName; if (string.IsNullOrEmpty(dev) && Microphone.devices.Length > 0) dev = Microphone.devices[0]; // Optionally query supported sample range Microphone.GetDeviceCaps(dev, out int minFreq, out int maxFreq); int sampleRate = requestedSampleRate; if (minFreq != 0 && maxFreq != 0) { // Clamp to supported range sampleRate = Mathf.Clamp(requestedSampleRate, minFreq, maxFreq); } // Start recording into an AudioClip Unity manages _micClip = Microphone.Start(dev, true, bufferLengthSec, sampleRate); isRecording = true; Debug.Log("Recording started. device name:"); Debug.Log(Microphone.GetPosition(deviceName)); // Wait until the mic has written at least one sample StartCoroutine(PlayWhenReady()); } System.Collections.IEnumerator PlayWhenReady() { // Ensure mic buffer has started writing Debug.Log("device name: " + deviceName); while (Microphone.GetPosition(deviceName) <= 0) { Debug.Log("Stuck in enumerator"); yield return null; } _src.clip = _micClip; Debug.Log("Playing clip " + _src.clip); _src.Play(); isPlaying = true; } public void StopLoopback() { if (!isRecording) return; _src.Stop(); if (_micClip != null) { Microphone.End(null); // stop default device _micClip = null; } isPlaying = false; isRecording = false; } void OnDisable() { StopLoopback(); } }