Sync animation triggers to music

Hi everybody,

I am trying to sync animator triggers to the music of my game. The problem is, that the beats are slightly slowing down. The first beat is 58 Samples off, the second 117, the third 411 and so on…
So far, here is what I got:

using UnityEngine;
using System.Collections;

public class BeatSync : MonoBehaviour {

    private AudioSource music;
    private Animator animator;

    private float MusicPos; //Position of the playback head from the last beat
    [Tooltip("Interval of the trigger")]
    public float BPM = 60;
    [Tooltip("Sample Rate")]
    public float SampleRate = 44100;

    void Start()
    {
        music = GameObject.Find("Music").GetComponent<AudioSource>();
        animator = GetComponent<Animator>();
        StartMusic();
    }

    void StartMusic()
    {
        MusicPos = 0;
        music.Play();
    }

    void Update()
    {
        if (music.timeSamples - MusicPos > SampleRate * (60 / BPM))
        {
            animator.SetTrigger("Beat");
            MusicPos = music.timeSamples;
        }
    }
}

the music file settings are
Decompress on load
PCM compression
Preserve samplin rate

Is there anything wrong with it or maybe some better way to do this?

A little overshoot isn’t unexpected, since audio continues sampling even when scripts slow down/stop and you are checking for when the number of samples exceeds that of the number of samples in a beat. This is fine and wouldn’t be noticable, but since you are always comparing with the previous position in the track that this condition was detected, it’s not surprising that it compounds.

To use the above conditions as an example: if it was a little late on the first beat, then it’s still going to look 44100 samples ahead (at 60 BPM) for the next one, which means that it will look a little later than the actual beat happens. Then it will be a little late for THAT, et cetera… beat frequency exists.

I think you could instead divide the total number of samples by the number of samples in a beat, and check to see if it’s within a certain range of a whole number. Since it’s off by ~50 samples each time, maybe somewhere in +/- 75 samples? Yes, the object will miss its opportunity to trigger the animation if there is a processing hiccup at just the right time, but that doesn’t seem like it would be the end of the world, and it wouldn’t happen very often if the host device can handle the your project, which is obviously a fair requirement.