How can one keep a continuously looping mic synchronized?

My app continuously processes the latest microphone data. It works for a while but eventually loses sync. I am looking for a way to either re-sync or never lose sync. Either option is fine. I have read a lot of posts here which have gotten me as far as I am. I haven’t found anything that completely solves the problem but do apologize if this has already been answered.

The app consists of an AudioListener (named Microphone below) which is assigned a continuous mic clip like this…

Microphone.Stop();
Microphone.clip = UnityEngine.Microphone.Start(
    micName,
    true,
    1,
    AudioSettings.GetConfiguration().sampleRate);
Microphone.Play();
Microphone.timeSamples = 0;

The app implements OnAudioFilterRead which enqueues the data to be processed by the main thread (and the dsp time of the data) like this…

void OnAudioFilterRead(float[] data, int channels)
{
    // Copy interleaved Microphone channel data
    for (var i = 0; i < data.Length; i += 2) {
        // Use channel 0, discard channel 1
        audioBuffer[i >> 1] = data[i];
    }
    audioBuffers.Enqueue((AudioSettings.dspTime, audioBuffer));
}

The main thread processes these buffers and calls GetOutputData throwing away the results (to stay in sync) like this…

// Do some processing...
AudioListener.GetOutputData(trashBuf, 0);

As a side note, it seems odd that I need to call GetOutputData since I already have the data. Is there a more direct way to keep the read/write pointers sync’d?

This runs ok for a while but eventually it loses sync. I can see from examining the dsp time that occasionally some buffers are not delivered to OnAudioFilterRead. This problem is easy to repeat when I load scenes (the GameObject that does all this is set to DontDestroyOnLoad), and probably other times as well.

I would like to be able to re-sync whenever I detect a buffer has been skipped. Can anyone explain the sequence to restart all this so that its back in sync?

I guess I finally realized at the end of writing the original post that staying in sync was a fools errand and it would be better to be able to detect and recover from syncloss. Restarting the mic turns out to be a lot like starting it in the first place :wink: This seems to be working now.

public static void RestartMic()
{
    Microphone.Stop();
    Microphone.clip = UnityEngine.Microphone.Start(
        MicName,
        true,
        MIC_LOOP_TIME,
        AudioSettings.GetConfiguration().sampleRate);
    Microphone.Play();
    Microphone.timeSamples = 0;
    Debug.Log($"mic restarted");
}
1 Like