Skip to main content
Search our knowledge base

How do I get Unity to playback a Microphone input in real time?

Comments

15 comments

  • Ted Barnett

    Following the instructions above, I still see latency of over 220 msec using the Microphone on Windows, Unity 5.4.1 (see image).  Is that the expected minimum?  I've tried disabling all effects, using both USB and line-in mics, and varying the sample size without success.  

    I'm trying to build a Unity app that allows users to sing through the speakers, but this delay makes singing impossible.  

    Any hints/samples/suggestions appreciated!

     

     My code is as follows:

    using UnityEngine;
    using System.Collections;
    [RequireComponent (typeof(AudioSource))]

    public class MicrophoneOn : MonoBehaviour {

    void Start ()
    {
    AudioSource audio = GetComponent<AudioSource>();
    audio.clip = Microphone.Start(null, true, 100, 44100);
    audio.loop = true;
    while (!(Microphone.GetPosition(null) > 0)){}
    Debug.Log("start playing... position is " + Microphone.GetPosition(null));
    audio.Play();
    }

     

    1
  • Pino of DFT Games Studios

    Unity is not designed for real time mic management, so if you want to create a Karaoke game you can't use Unity internal microphone management.

    0
  • Ted Barnett

    Thanks, Pino.  I thought so, though the text above (from Unity!) deceptively suggests that it CAN work:

    "To ensure your Microphone audio plays back in real time..."

    -1
  • Andy

    Hi Ted,

    There will always be some inherent latency when processing audio. Depending on the platform(s) you are targeting this audio latency will occur at different rates.

    Something you can do if you haven’t yet done so to improve audio latency is by reducing the DSP buffer size: 

    • Edit -> Project Settings -> Audio

           Set DSP Buffer Size to ‘Best Latency’

    Hope this helps.

    Andy

    3
  • Max Aigner

    Hi Ted,

    If you change your code to that, it is a lot faster and really great:

     

    Snippet

    AudioSource audio = GetComponent<AudioSource>();
           audio.clip = Microphone.Start(null, true, 1, 22050);
           audio.loop = true;
           while (!(Microphone.GetPosition(null) > 0)) { }
           Debug.Log("start playing... position is " + Microphone.GetPosition(null));
           audio.Play();

     

    ( a Pity we cannot change the Microphone LengthSec to 0.1 something or another float, but it's quite nice already.)

     

    yours

     

    Max Aigner

    (Signature: www.maxaigner.de )

    0
  • Arnas Cibulskis

    Hi, this doesn't seem to be working in 2018, any suggestions?

    1
  • axi zapantis

    This script used to work in unity 5.6 for my gearvr app.I updated to unity 2018.1.0f2 and the gearvr app freezes on a frame but headtracking continues to work.I know this script is the problem because when i uncheck it the app is working fine...Is there an alternative way to playback a mic in realtime in unity 2018?Thanks.

    0
  • Chris Kibitlewski

    I just tried this script in 2018.3.0b5 Personal and it is working for me.  I hear the slightly delayed sound in my headphones, so it works. 

    Some slight adjustments:
    I didn't need to include any namespace - it just worked with Microphone,

    Had to use Microphone.devices to get the name of my microphone (since Built-in Microphone didn't exist for my machine).

    0
  • axi zapantis

    The problem in my occassion was caused by the permission request "Record audio" .Even if i had the reference UnityEngine.Microphone in my script it didnt ask for this permission when i was starting my app.I created a new project and copy pasted everything and now it asks for the permission "record audio" and everything works fine like before...

    0
  • rahul patil

    when first microphone is start how to stop for the 5 seconds

    StartCoroutine(RecordVoice());

    IEnumerator RecordVoice()
    {
    yield return new WaitForSeconds(5);
    //Microphone.End(null);
    }

    0
  • wsdfz

    @Megan I tested the codes on Mac and android platforms, there was a little latency on MAC which can satisfy my requirement, but on android platform the latency was longer, and the experience was bad,how to solve this?

    1
  • Paulo Renan

    A slightly more flexible implementation could be like that

    (just save the code below as AudioSourceAssigner.cs and drag it into an empty gameobject)

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

    [RequireComponent(typeof(AudioSource))]
    public class AudioSourceAssigner : MonoBehaviour
    {
        [SerializeField] private string useSpecificDevice = "";

        [SerializeField] private int refreshMicEveryNSeconds = 5;

        IEnumerator Start()
        {
            var audio = GetComponent<AudioSource>();

            if (audio == null || Microphone.devices == null || Microphone.devices.Length == 0) yield break;

            string deviceName = Microphone.devices.FirstOrDefault(x =>
                !string.IsNullOrEmpty(x) &&
                (string.IsNullOrEmpty(useSpecificDevice) ? true : x.Contains(useSpecificDevice))
            );
            if (string.IsNullOrEmpty(deviceName)) yield break;

            int minFreq, maxFreq;
            Microphone.GetDeviceCaps(deviceName, out minFreq, out maxFreq);
            int freq = maxFreq;

            foreach (var item in Microphone.devices)
                Debug.Log("Microphone device: " + item);
            Debug.Log("Using: " + deviceName);

            audio.loop = false;
            audio.clip = Microphone.Start(deviceName, true, 10, freq);

            while (Microphone.devices.Any(x => x == deviceName))
            {
                while (!Microphone.IsRecording(deviceName) || !audio.isPlaying)
                {

                    refreshMicEveryNSeconds = Mathf.Clamp(refreshMicEveryNSeconds, 1, 60 * 60); // unity requires this to be between 1 second and an hour
                    audio.clip = Microphone.Start(deviceName, true, refreshMicEveryNSeconds, freq);

                    while (Microphone.GetPosition(deviceName) == 0)
                        yield return null;

                    audio.Play();
                    yield return null;
                }
                yield return null;
            }
            yield return null;

        }
    }

    0
  • dan rares

    Hello. I have implented the audio in this way, and while the mic picks up my voice (and with little latency), it also picks up any sound, no matter how little, so I end up with a ton of background noise.

    I've been looking into it, but I can't seem to find any fixes.

    0
  • Don Pinkus

    This is not real-time. This will process your audio with ~1 second delay depending on device. 

    If you are trying to give a user real-time feedback, for example controlling a character with their voice - this will likely not work due to the 1 second delay. 

    While things like loudness can be computed almost instantly off the AudioClip, getting the spectrum data off the AudioSource seems to be much slower. Unsure of the reasons why. 

    0
  • Max Aigner

    it can never be real time because a computer is not made for realtime computation - there is the drivers, the OS, all other tasks that require processing, the sound card.. you can be happy if you only have a couple 100ms latency and also the latency might change from one pc restart to another.. I think the fastest I ever got was about 100-200ms

    If you really need realtime, then you might want to create your own hardware FPGA or ASIC like they do in microphones or maybe redesign your software so that you don't need realtime anymore.. what do you need it for anyway?

    0

Article is closed for comments.