I’m working on a Unity project for mobile devices where I need to synchronize a metronome with incoming audio from a microphone. The goal is to detect drum hits in real-time and align them with the metronome ticks. Below is a simplified version of my current DrumInput script:
using UnityEngine;
using System.Collections;
public class DrumInput : MonoBehaviour
{
private AudioClip microphoneClip; // Audio clip to capture microphone input
private int sampleRate = 44100; // Sample rate for audio capture
public float threshold = 0.1f; // Threshold to detect drum hits
public int smoothingWindow = 10; // Window size for smoothing amplitude
public float checkInterval = 0.01f; // Interval for checking audio input
private float[] prevSamples; // Array to store previous samples for smoothing
void Start()
{
StartMicrophone();
prevSamples = new float[smoothingWindow];
StartCoroutine(CheckAudio());
}
// Start capturing audio from the microphone
void StartMicrophone()
{
string device = Microphone.devices[0];
microphoneClip = Microphone.Start(device, true, 1, sampleRate);
}
// Coroutine to periodically check audio input
IEnumerator CheckAudio()
{
while (true)
{
int micPosition = Microphone.GetPosition(null);
float[] samples = new float[microphoneClip.samples * microphoneClip.channels];
microphoneClip.GetData(samples, 0);
ProcessAudio(samples, micPosition);
yield return new WaitForSeconds(checkInterval);
}
}
// Process audio samples to detect drum hits
void ProcessAudio(float[] samples, int micPosition)
{
float smoothedAmplitude = 0.0f;
for (int i = 0; i < micPosition; i++)
{
smoothedAmplitude = (smoothedAmplitude * (smoothingWindow - 1) + Mathf.Abs(samples[i])) / smoothingWindow;
prevSamples[i % smoothingWindow] = Mathf.Abs(samples[i]);
if (smoothedAmplitude > threshold)
{
double currentTime = AudioSettings.dspTime;
double inputLatency = (micPosition / (double)sampleRate);
double adjustedHitTime = currentTime - inputLatency;
Debug.Log($"Drum hit detected at: {currentTime:F1}, Adjusted Hit Time: {adjustedHitTime:F1}, Amplitude: {smoothedAmplitude}, Threshold exceeded by: {smoothedAmplitude - threshold}, Input Latency: {inputLatency * 1000:F1}ms (Compensation Time: {inputLatency:F4}s)");
// Handle drum hit detection
break;
}
}
}
}
The script captures audio input, processes it to detect drum hits, and attempts to compensate for input latency. However, I’m having difficulty achieving precise synchronization between the detected drum hits and the metronome ticks.Does anyone have experience or advice on how to better synchronize real-time audio input with a metronome in Unity, particularly for mobile devices? Any tips on improving the accuracy of latency compensation or handling timing discrepancies would be greatly appreciated.
Thank you!
The script captures audio input, processes it to detect drum hits, and attempts to compensate for input latency. However, I’m having difficulty achieving precise synchronization between the detected drum hits and the metronome ticks.
Семён Горгель is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.